From 332259d63472f5a0d4dd7b7cd623603e8294c440 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Thu, 13 Feb 2025 15:40:50 +0800 Subject: [PATCH] refactor --- src/renderer/src/App.tsx | 6 ++-- src/renderer/src/hooks/useFrameCapture.ts | 40 ++++++++++++++--------- src/renderer/src/segments.ts | 2 +- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 6699ebd3..366b46ff 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -1154,8 +1154,8 @@ function App() { if (video == null) throw new Error(); const useFffmpeg = usingPreviewFile || captureFrameMethod === 'ffmpeg'; const outPath = useFffmpeg - ? await captureFrameFromFfmpeg({ customOutDir, filePath, fromTime: currentTime, captureFormat, quality: captureFrameQuality }) - : await captureFrameFromTag({ customOutDir, filePath, currentTime, captureFormat, video, quality: captureFrameQuality }); + ? await captureFrameFromFfmpeg({ customOutDir, filePath, time: currentTime, captureFormat, quality: captureFrameQuality }) + : await captureFrameFromTag({ customOutDir, filePath, time: currentTime, captureFormat, quality: captureFrameQuality, video }); if (!hideAllNotifications) openDirToast({ icon: 'success', filePath: outPath, text: `${i18n.t('Screenshot captured to:')} ${outPath}` }); }, i18n.t('Failed to capture frame')); @@ -1650,7 +1650,7 @@ function App() { if (!filePath) return; await withErrorHandling(async () => { const currentTime = getRelevantTime(); - const path = await captureFrameFromFfmpeg({ customOutDir, filePath, fromTime: currentTime, captureFormat, quality: captureFrameQuality }); + const path = await captureFrameFromFfmpeg({ customOutDir, filePath, time: currentTime, captureFormat, quality: captureFrameQuality }); if (!(await addFileAsCoverArt(path))) return; showNotification({ text: i18n.t('Current frame has been set as cover art') }); }, i18n.t('Failed to capture frame')); diff --git a/src/renderer/src/hooks/useFrameCapture.ts b/src/renderer/src/hooks/useFrameCapture.ts index 7e2bfa16..7bcb6401 100644 --- a/src/renderer/src/hooks/useFrameCapture.ts +++ b/src/renderer/src/hooks/useFrameCapture.ts @@ -47,10 +47,8 @@ export default ({ appendFfmpegCommandLog, formatTimecode, treatOutputFileModifie if (!outputTimestamps) { const numDigits = getNumDigits(estimatedMaxNumFiles); - const nameTemplateSuffix = getSuffix(`%0${numDigits}d`); - const nameSuffix = getSuffix(`${'1'.padStart(numDigits, '0')}`); // mimic ffmpeg output - const outPathTemplate = getSuffixedOutPath({ customOutDir, filePath, nameSuffix: nameTemplateSuffix }); - const firstFileOutPath = getSuffixedOutPath({ customOutDir, filePath, nameSuffix }); + const outPathTemplate = getSuffixedOutPath({ customOutDir, filePath, nameSuffix: getSuffix(`%0${numDigits}d`) }); + const firstFileOutPath = getSuffixedOutPath({ customOutDir, filePath, nameSuffix: getSuffix(`${'1'.padStart(numDigits, '0')}`) }); // mimic ffmpeg output const args = await ffmpeg.captureFrames({ from: fromTime, to: toTime, videoPath: filePath, outPathTemplate, captureFormat, quality, filter, onProgress }); appendFfmpegCommandLog(args); @@ -58,7 +56,9 @@ export default ({ appendFfmpegCommandLog, formatTimecode, treatOutputFileModifie return firstFileOutPath; } + // capture frames with timestamps // see https://github.com/mifi/lossless-cut/issues/1139 + const tmpSuffix = 'llc-tmp-frame-capture-'; const outPathTemplate = getSuffixedOutPath({ customOutDir, filePath, nameSuffix: getSuffix(`${tmpSuffix}%d`) }); const args = await ffmpeg.captureFrames({ from: fromTime, to: toTime, videoPath: filePath, outPathTemplate, captureFormat, quality, filter, framePts: true, onProgress }); @@ -67,7 +67,6 @@ export default ({ appendFfmpegCommandLog, formatTimecode, treatOutputFileModifie const outDir = getOutDir(customOutDir, filePath); const files = await readdir(outDir); - // https://github.com/mifi/lossless-cut/issues/1139 const matches = files.flatMap((fileName) => { const escapedRegexp = escapeRegExp(getSuffixedFileName(filePath, tmpSuffix)); const regexp = `^${escapedRegexp}(\\d+)`; @@ -90,31 +89,40 @@ export default ({ appendFfmpegCommandLog, formatTimecode, treatOutputFileModifie return outPaths[0]; }, [appendFfmpegCommandLog, formatTimecode]); - const captureFrameFromFfmpeg = useCallback(async ({ customOutDir, filePath, fromTime, captureFormat, quality }: { - customOutDir?: string | undefined, filePath: string, fromTime: number, captureFormat: CaptureFormat, quality: number, + const captureFrameFromFfmpeg = useCallback(async ({ customOutDir, filePath, time, captureFormat, quality }: { + customOutDir?: string | undefined, + filePath: string, + time: number, + captureFormat: CaptureFormat, + quality: number, }) => { - const time = formatTimecode({ seconds: fromTime, fileNameFriendly: true }); - const nameSuffix = `${time}.${captureFormat}`; + const timecode = formatTimecode({ seconds: time, fileNameFriendly: true }); + const nameSuffix = `${timecode}.${captureFormat}`; const outPath = getSuffixedOutPath({ customOutDir, filePath, nameSuffix }); - const args = await ffmpeg.captureFrame({ timestamp: fromTime, videoPath: filePath, outPath, quality }); + const args = await ffmpeg.captureFrame({ timestamp: time, videoPath: filePath, outPath, quality }); appendFfmpegCommandLog(args); - await transferTimestamps({ inPath: filePath, outPath, cutFrom: fromTime, treatOutputFileModifiedTimeAsStart }); + await transferTimestamps({ inPath: filePath, outPath, cutFrom: time, treatOutputFileModifiedTimeAsStart }); return outPath; }, [appendFfmpegCommandLog, formatTimecode, treatOutputFileModifiedTimeAsStart]); - const captureFrameFromTag = useCallback(async ({ customOutDir, filePath, currentTime, captureFormat, video, quality }: { - customOutDir?: string | undefined, filePath: string, currentTime: number, captureFormat: CaptureFormat, video: HTMLVideoElement, quality: number, + const captureFrameFromTag = useCallback(async ({ customOutDir, filePath, time, captureFormat, quality, video }: { + customOutDir?: string | undefined, + filePath: string, + time: number, + captureFormat: CaptureFormat, + quality: number, + video: HTMLVideoElement, }) => { const buf = getFrameFromVideo(video, captureFormat, quality); const ext = mime.extension(buf.type); - const time = formatTimecode({ seconds: currentTime, fileNameFriendly: true }); + const timecode = formatTimecode({ seconds: time, fileNameFriendly: true }); - const outPath = getSuffixedOutPath({ customOutDir, filePath, nameSuffix: `${time}.${ext}` }); + const outPath = getSuffixedOutPath({ customOutDir, filePath, nameSuffix: `${timecode}.${ext}` }); await writeFile(outPath, buf); - await transferTimestamps({ inPath: filePath, outPath, cutFrom: currentTime, treatOutputFileModifiedTimeAsStart }); + await transferTimestamps({ inPath: filePath, outPath, cutFrom: time, treatOutputFileModifiedTimeAsStart }); return outPath; }, [formatTimecode, treatOutputFileModifiedTimeAsStart]); diff --git a/src/renderer/src/segments.ts b/src/renderer/src/segments.ts index 36b69738..f84f679f 100644 --- a/src/renderer/src/segments.ts +++ b/src/renderer/src/segments.ts @@ -259,7 +259,7 @@ export function playOnlyCurrentSegment({ playbackMode, currentTime, playingSegme return {}; } -export const getNumDigits = (value) => Math.floor(value > 0 ? Math.log10(value) : 0) + 1; +export const getNumDigits = (value: number) => Math.floor(value > 0 ? Math.log10(value) : 0) + 1; export function formatSegNum(segIndex: number, numSegments: number, minLength = 0) { const numDigits = getNumDigits(numSegments);