|
|
|
|
@ -185,7 +185,7 @@ const App = memo(() => {
|
|
|
|
|
const allUserSettings = useUserSettingsRoot();
|
|
|
|
|
|
|
|
|
|
const {
|
|
|
|
|
captureFormat, setCaptureFormat, customOutDir, setCustomOutDir, keyframeCut, setKeyframeCut, preserveMovData, setPreserveMovData, movFastStart, setMovFastStart, avoidNegativeTs, autoMerge, timecodeFormat, invertCutSegments, setInvertCutSegments, autoExportExtraStreams, askBeforeClose, enableAskForImportChapters, enableAskForFileOpenAction, playbackVolume, setPlaybackVolume, autoSaveProjectFile, wheelSensitivity, invertTimelineScroll, language, ffmpegExperimental, hideNotifications, autoLoadTimecode, autoDeleteMergedSegments, exportConfirmEnabled, setExportConfirmEnabled, segmentsToChapters, setSegmentsToChapters, preserveMetadataOnMerge, setPreserveMetadataOnMerge, setSimpleMode, outSegTemplate, setOutSegTemplate, keyboardSeekAccFactor, keyboardNormalSeekSpeed, enableTransferTimestamps, outFormatLocked, setOutFormatLocked, safeOutputFileName, setSafeOutputFileName, enableAutoHtml5ify, segmentsToChaptersOnly, keyBindings, setKeyBindings, resetKeyBindings, enableSmartCut, customFfPath, storeProjectInWorkingDir, setStoreProjectInWorkingDir, enableOverwriteOutput, mouseWheelZoomModifierKey, captureFrameMethod, captureFrameQuality, captureFrameFileNameFormat, enableNativeHevc, cleanupChoices, setCleanupChoices, darkMode, setDarkMode, preferStrongColors,
|
|
|
|
|
captureFormat, setCaptureFormat, customOutDir, setCustomOutDir, keyframeCut, setKeyframeCut, preserveMovData, setPreserveMovData, movFastStart, setMovFastStart, avoidNegativeTs, autoMerge, timecodeFormat, invertCutSegments, setInvertCutSegments, autoExportExtraStreams, askBeforeClose, enableAskForImportChapters, enableAskForFileOpenAction, playbackVolume, setPlaybackVolume, autoSaveProjectFile, wheelSensitivity, invertTimelineScroll, language, ffmpegExperimental, hideNotifications, autoLoadTimecode, autoDeleteMergedSegments, exportConfirmEnabled, setExportConfirmEnabled, segmentsToChapters, setSegmentsToChapters, preserveMetadataOnMerge, setPreserveMetadataOnMerge, setSimpleMode, outSegTemplate, setOutSegTemplate, keyboardSeekAccFactor, keyboardNormalSeekSpeed, treatInputFileModifiedTimeAsStart, treatOutputFileModifiedTimeAsStart, outFormatLocked, setOutFormatLocked, safeOutputFileName, setSafeOutputFileName, enableAutoHtml5ify, segmentsToChaptersOnly, keyBindings, setKeyBindings, resetKeyBindings, enableSmartCut, customFfPath, storeProjectInWorkingDir, setStoreProjectInWorkingDir, enableOverwriteOutput, mouseWheelZoomModifierKey, captureFrameMethod, captureFrameQuality, captureFrameFileNameFormat, enableNativeHevc, cleanupChoices, setCleanupChoices, darkMode, setDarkMode, preferStrongColors,
|
|
|
|
|
} = allUserSettings;
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
@ -378,7 +378,7 @@ const App = memo(() => {
|
|
|
|
|
return formatDuration({ seconds, shorten, fileNameFriendly });
|
|
|
|
|
}, [detectedFps, timecodeFormat, getFrameCount]);
|
|
|
|
|
|
|
|
|
|
const { captureFrameFromTag, captureFrameFromFfmpeg, captureFramesRange } = useFrameCapture({ formatTimecode });
|
|
|
|
|
const { captureFrameFromTag, captureFrameFromFfmpeg, captureFramesRange } = useFrameCapture({ formatTimecode, treatOutputFileModifiedTimeAsStart });
|
|
|
|
|
|
|
|
|
|
// const getSafeCutTime = useCallback((cutTime, next) => ffmpeg.getSafeCutTime(neighbouringFrames, cutTime, next), [neighbouringFrames]);
|
|
|
|
|
|
|
|
|
|
@ -733,7 +733,7 @@ const App = memo(() => {
|
|
|
|
|
|
|
|
|
|
const {
|
|
|
|
|
concatFiles, html5ifyDummy, cutMultiple, autoConcatCutSegments, html5ify, fixInvalidDuration,
|
|
|
|
|
} = useFfmpegOperations({ filePath, enableTransferTimestamps, needSmartCut, enableOverwriteOutput });
|
|
|
|
|
} = useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, treatOutputFileModifiedTimeAsStart, needSmartCut, enableOverwriteOutput });
|
|
|
|
|
|
|
|
|
|
const html5ifyAndLoad = useCallback(async (cod, fp, speed, hv, ha) => {
|
|
|
|
|
const usesDummyVideo = ['fastest-audio', 'fastest-audio-remux', 'fastest'].includes(speed);
|
|
|
|
|
@ -1251,15 +1251,15 @@ const App = memo(() => {
|
|
|
|
|
const video = videoRef.current;
|
|
|
|
|
const useFffmpeg = usingPreviewFile || captureFrameMethod === 'ffmpeg';
|
|
|
|
|
const outPath = useFffmpeg
|
|
|
|
|
? await captureFrameFromFfmpeg({ customOutDir, filePath, fromTime: currentTime, captureFormat, enableTransferTimestamps, quality: captureFrameQuality })
|
|
|
|
|
: await captureFrameFromTag({ customOutDir, filePath, currentTime, captureFormat, video, enableTransferTimestamps, quality: captureFrameQuality });
|
|
|
|
|
? await captureFrameFromFfmpeg({ customOutDir, filePath, fromTime: currentTime, captureFormat, quality: captureFrameQuality })
|
|
|
|
|
: await captureFrameFromTag({ customOutDir, filePath, currentTime, captureFormat, video, quality: captureFrameQuality });
|
|
|
|
|
|
|
|
|
|
if (!hideAllNotifications) openDirToast({ icon: 'success', filePath: outPath, text: `${i18n.t('Screenshot captured to:')} ${outPath}` });
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
errorToast(i18n.t('Failed to capture frame'));
|
|
|
|
|
}
|
|
|
|
|
}, [filePath, getRelevantTime, usingPreviewFile, captureFrameMethod, captureFrameFromFfmpeg, customOutDir, captureFormat, enableTransferTimestamps, captureFrameQuality, captureFrameFromTag, hideAllNotifications]);
|
|
|
|
|
}, [filePath, getRelevantTime, usingPreviewFile, captureFrameMethod, captureFrameFromFfmpeg, customOutDir, captureFormat, captureFrameQuality, captureFrameFromTag, hideAllNotifications]);
|
|
|
|
|
|
|
|
|
|
const extractSegmentFramesAsImages = useCallback(async (index) => {
|
|
|
|
|
if (!filePath || detectedFps == null || workingRef.current) return;
|
|
|
|
|
@ -1687,14 +1687,14 @@ const App = memo(() => {
|
|
|
|
|
if (!filePath) return;
|
|
|
|
|
try {
|
|
|
|
|
const currentTime = getRelevantTime();
|
|
|
|
|
const path = await captureFrameFromFfmpeg({ customOutDir, filePath, fromTime: currentTime, captureFormat, enableTransferTimestamps, quality: captureFrameQuality });
|
|
|
|
|
const path = await captureFrameFromFfmpeg({ customOutDir, filePath, fromTime: currentTime, captureFormat, quality: captureFrameQuality });
|
|
|
|
|
if (!(await addFileAsCoverArt(path))) return;
|
|
|
|
|
if (!hideAllNotifications) toast.fire({ text: i18n.t('Current frame has been set as cover art') });
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
errorToast(i18n.t('Failed to capture frame'));
|
|
|
|
|
}
|
|
|
|
|
}, [addFileAsCoverArt, captureFormat, captureFrameFromFfmpeg, captureFrameQuality, customOutDir, enableTransferTimestamps, filePath, getRelevantTime, hideAllNotifications]);
|
|
|
|
|
}, [addFileAsCoverArt, captureFormat, captureFrameFromFfmpeg, captureFrameQuality, customOutDir, filePath, getRelevantTime, hideAllNotifications]);
|
|
|
|
|
|
|
|
|
|
const batchLoadPaths = useCallback((newPaths, append) => {
|
|
|
|
|
setBatchFiles((existingFiles) => {
|
|
|
|
|
|