diff --git a/src/main/ffmpeg.ts b/src/main/ffmpeg.ts index 630f68ba..c29f2e96 100644 --- a/src/main/ffmpeg.ts +++ b/src/main/ffmpeg.ts @@ -279,7 +279,7 @@ export async function detectSceneChanges({ filePath, minChange, onProgress, from const segments = mapTimesToSegments(times, false); - return adjustSegmentsWithOffset({ segments, from }); + return { detectedSegments: adjustSegmentsWithOffset({ segments, from }), ffmpegArgs: args }; } async function detectIntervals({ filePath, customArgs, onProgress, from, to, matchLineTokens, boundingMode }: { @@ -328,7 +328,7 @@ async function detectIntervals({ filePath, customArgs, onProgress, from, to, mat } } - return adjustSegmentsWithOffset({ segments, from }); + return { detectedSegments: adjustSegmentsWithOffset({ segments, from }), ffmpegArgs: args }; } const mapFilterOptions = (options: Record) => Object.entries(options).map(([key, value]) => `${key}=${value}`).join(':'); diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 4350d306..4a7ff794 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -59,6 +59,7 @@ import { getDuration, getTimecodeFromStreams, createChaptersFromSegments, RefuseOverwriteError, extractSubtitleTrackToSegments, mapRecommendedDefaultFormat, + getFfCommandLine, } from './ffmpeg'; import { shouldCopyStreamByDefault, getAudioStreams, getRealVideoStreams, isAudioDefinitelyNotSupported, willPlayerProperlyHandleVideo, doesPlayerSupportHevcPlayback, getSubtitleStreams, enableVideoTrack, enableAudioTrack, canHtml5PlayerPlayStreams } from './util/streams'; import { exportEdlFile, readEdlFile, loadLlcProject, askForEdlImport } from './edlStore'; @@ -251,6 +252,7 @@ function App() { const appendLastCommandsLog = useCallback((command: string) => { setFfmpegCommandLog((old) => [...old, { command, time: new Date() }]); }, []); + const appendFfmpegCommandLog = useCallback((args: string[]) => appendLastCommandsLog(getFfCommandLine('ffmpeg', args)), [appendLastCommandsLog]); const toggleSegmentsList = useCallback(() => setShowRightBar((v) => !v), []); @@ -332,7 +334,7 @@ function App() { const { cutSegments, cutSegmentsHistory, createSegmentsFromKeyframes, shuffleSegments, detectBlackScenes, detectSilentScenes, detectSceneChanges, removeCutSegment, invertAllSegments, fillSegmentsGaps, combineOverlappingSegments, combineSelectedSegments, shiftAllSegmentTimes, alignSegmentTimesToKeyframes, updateSegOrder, updateSegOrders, reorderSegsByStartTime, addSegment, setCutStart, setCutEnd, onLabelSegment, splitCurrentSegment, focusSegmentAtCursor, createNumSegments, createFixedDurationSegments, createRandomSegments, apparentCutSegments, haveInvalidSegs, currentSegIndexSafe, currentCutSeg, currentApparentCutSeg, inverseCutSegments, clearSegments, loadCutSegments, isSegmentSelected, setCutTime, setCurrentSegIndex, onLabelSelectedSegments, deselectAllSegments, selectAllSegments, selectOnlyCurrentSegment, toggleCurrentSegmentSelected, invertSelectedSegments, removeSelectedSegments, setDeselectedSegmentIds, onSelectSegmentsByLabel, onSelectSegmentsByExpr, toggleSegmentSelected, selectOnlySegment, getApparentCutSegmentById, selectedSegments, selectedSegmentsOrInverse, nonFilteredSegmentsOrInverse, segmentsToExport, duplicateCurrentSegment, duplicateSegment, updateSegAtIndex, - } = useSegments({ filePath, workingRef, setWorking, setProgress, videoStream: activeVideoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly, timecodePlaceholder, parseTimecode }); + } = useSegments({ filePath, workingRef, setWorking, setProgress, videoStream: activeVideoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly, timecodePlaceholder, parseTimecode, appendFfmpegCommandLog }); const { getEdlFilePath, getEdlFilePathOld, projectFileSavePath, getProjectFileSavePath } = useSegmentsAutoSave({ autoSaveProjectFile, storeProjectInWorkingDir, filePath, customOutDir, cutSegments }); @@ -594,8 +596,8 @@ function App() { const needSmartCut = !!(areWeCutting && enableSmartCut); const { - appendFfmpegCommandLog, concatFiles, html5ifyDummy, cutMultiple, autoConcatCutSegments, html5ify, fixInvalidDuration, extractStreams, - } = useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, treatOutputFileModifiedTimeAsStart, needSmartCut, enableOverwriteOutput, outputPlaybackRate, cutFromAdjustmentFrames, appendLastCommandsLog, smartCutCustomBitrate: smartCutBitrate }); + concatFiles, html5ifyDummy, cutMultiple, autoConcatCutSegments, html5ify, fixInvalidDuration, extractStreams, + } = useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, treatOutputFileModifiedTimeAsStart, needSmartCut, enableOverwriteOutput, outputPlaybackRate, cutFromAdjustmentFrames, appendLastCommandsLog, smartCutCustomBitrate: smartCutBitrate, appendFfmpegCommandLog }); const { captureFrameFromTag, captureFrameFromFfmpeg, captureFramesRange } = useFrameCapture({ appendFfmpegCommandLog, formatTimecode, treatOutputFileModifiedTimeAsStart }); diff --git a/src/renderer/src/hooks/useFfmpegOperations.ts b/src/renderer/src/hooks/useFfmpegOperations.ts index ef73252e..753705ba 100644 --- a/src/renderer/src/hooks/useFfmpegOperations.ts +++ b/src/renderer/src/hooks/useFfmpegOperations.ts @@ -76,7 +76,7 @@ async function pathExists(path: string) { } } -function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, treatOutputFileModifiedTimeAsStart, needSmartCut, enableOverwriteOutput, outputPlaybackRate, cutFromAdjustmentFrames, appendLastCommandsLog, smartCutCustomBitrate }: { +function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, treatOutputFileModifiedTimeAsStart, needSmartCut, enableOverwriteOutput, outputPlaybackRate, cutFromAdjustmentFrames, appendLastCommandsLog, smartCutCustomBitrate, appendFfmpegCommandLog }: { filePath: string | undefined, treatInputFileModifiedTimeAsStart: boolean | null | undefined, treatOutputFileModifiedTimeAsStart: boolean | null | undefined, @@ -86,9 +86,8 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea cutFromAdjustmentFrames: number, appendLastCommandsLog: (a: string) => void, smartCutCustomBitrate: number | undefined, + appendFfmpegCommandLog: (args: string[]) => void, }) { - const appendFfmpegCommandLog = useCallback((args: string[]) => appendLastCommandsLog(getFfCommandLine('ffmpeg', args)), [appendLastCommandsLog]); - const shouldSkipExistingFile = useCallback(async (path: string) => { const fileExists = await pathExists(path); @@ -969,7 +968,7 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea }, [extractAttachmentStreams, extractNonAttachmentStreams, filePath]); return { - appendFfmpegCommandLog, cutMultiple, concatFiles, html5ify, html5ifyDummy, fixInvalidDuration, autoConcatCutSegments, extractStreams, + cutMultiple, concatFiles, html5ify, html5ifyDummy, fixInvalidDuration, autoConcatCutSegments, extractStreams, }; } diff --git a/src/renderer/src/hooks/useSegments.ts b/src/renderer/src/hooks/useSegments.ts index 9dcbb585..c0929e46 100644 --- a/src/renderer/src/hooks/useSegments.ts +++ b/src/renderer/src/hooks/useSegments.ts @@ -21,7 +21,7 @@ import { FFprobeStream } from '../../../../ffprobe'; const { ffmpeg: { blackDetect, silenceDetect } } = window.require('@electron/remote').require('./index.js'); -function useSegments({ filePath, workingRef, setWorking, setProgress, videoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly, timecodePlaceholder, parseTimecode }: { +function useSegments({ filePath, workingRef, setWorking, setProgress, videoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly, timecodePlaceholder, parseTimecode, appendFfmpegCommandLog }: { filePath?: string | undefined, workingRef: MutableRefObject, setWorking: (w: { text: string, abortController?: AbortController } | undefined) => void, @@ -35,6 +35,7 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea segmentsToChaptersOnly: boolean, timecodePlaceholder: string, parseTimecode: ParseTimecode, + appendFfmpegCommandLog: (args: string[]) => void, }) { // Segment related state const segCounterRef = useRef(0); @@ -94,7 +95,10 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea }, [clearSegCounter, createIndexedSegment, setCutSegments]); const detectSegments = useCallback(async ({ name, workingText, errorText, fn }: { - name: string, workingText: string, errorText: string, fn: () => Promise, + name: string, + workingText: string, + errorText: string, + fn: () => Promise<{ detectedSegments: SegmentBase[], ffmpegArgs: string[] }>, }) => { if (!filePath) return; if (workingRef.current) return; @@ -102,16 +106,18 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea setWorking({ text: workingText }); setProgress(0); - const newSegments = await fn(); - console.log(name, newSegments); - loadCutSegments(newSegments, true); + const { detectedSegments, ffmpegArgs } = await fn(); + appendFfmpegCommandLog(ffmpegArgs); + + console.log(name, detectedSegments); + loadCutSegments(detectedSegments, true); } catch (err) { if (!(err instanceof Error && err.name === 'AbortError')) handleError(errorText, err); } finally { setWorking(undefined); setProgress(undefined); } - }, [filePath, workingRef, setWorking, setProgress, loadCutSegments]); + }, [filePath, workingRef, setWorking, setProgress, appendFfmpegCommandLog, loadCutSegments]); const getSegApparentEnd = useCallback((seg: SegmentBase) => getSegApparentEnd2(seg, duration), [duration]);