kopia lustrzana https://github.com/mifi/lossless-cut
refactor
rodzic
9cdd5edbfb
commit
7d306f7736
|
@ -122,7 +122,7 @@ function App() {
|
|||
const [previewFilePath, setPreviewFilePath] = useState<string>();
|
||||
const [usingDummyVideo, setUsingDummyVideo] = useState(false);
|
||||
const [rotation, setRotation] = useState(360);
|
||||
const [cutProgress, setCutProgress] = useState<number>();
|
||||
const [progress, setProgress] = useState<number>();
|
||||
const [startTimeOffset, setStartTimeOffset] = useState(0);
|
||||
const [filePath, setFilePath] = useState<string>();
|
||||
const [externalFilesMeta, setExternalFilesMeta] = useState<FilesMeta>({});
|
||||
|
@ -183,9 +183,9 @@ function App() {
|
|||
const zoom = Math.floor(zoomUnrounded);
|
||||
const zoomedDuration = isDurationValid(duration) ? duration / zoom : undefined;
|
||||
|
||||
useEffect(() => setDocumentTitle({ filePath, working: working?.text, cutProgress }), [cutProgress, filePath, working?.text]);
|
||||
useEffect(() => setDocumentTitle({ filePath, working: working?.text, progress }), [progress, filePath, working?.text]);
|
||||
|
||||
useEffect(() => setProgressBar(cutProgress ?? -1), [cutProgress]);
|
||||
useEffect(() => setProgressBar(progress ?? -1), [progress]);
|
||||
|
||||
useEffect(() => {
|
||||
ffmpegSetCustomFfPath(customFfPath);
|
||||
|
@ -330,7 +330,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, setCutProgress, 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 });
|
||||
|
||||
const { getEdlFilePath, getEdlFilePathOld, projectFileSavePath, getProjectFileSavePath } = useSegmentsAutoSave({ autoSaveProjectFile, storeProjectInWorkingDir, filePath, customOutDir, cutSegments });
|
||||
|
||||
|
@ -563,7 +563,7 @@ function App() {
|
|||
setFileFormat(undefined);
|
||||
setDetectedFileFormat(undefined);
|
||||
setRotation(360);
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
setStartTimeOffset(0);
|
||||
setFilePath(undefined);
|
||||
setExternalFilesMeta({});
|
||||
|
@ -614,19 +614,19 @@ function App() {
|
|||
if (speed === 'fastest') {
|
||||
const path = getSuffixedOutPath({ customOutDir: cod, filePath: fp, nameSuffix: `${html5ifiedPrefix}${html5dummySuffix}.mkv` });
|
||||
try {
|
||||
setCutProgress(0);
|
||||
await html5ifyDummy({ filePath: fp, outPath: path, onProgress: setCutProgress });
|
||||
setProgress(0);
|
||||
await html5ifyDummy({ filePath: fp, outPath: path, onProgress: setProgress });
|
||||
} finally {
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
try {
|
||||
const shouldIncludeVideo = !usesDummyVideo && hv;
|
||||
return await html5ify({ customOutDir: cod, filePath: fp, speed, hasAudio: ha, hasVideo: shouldIncludeVideo, onProgress: setCutProgress });
|
||||
return await html5ify({ customOutDir: cod, filePath: fp, speed, hasAudio: ha, hasVideo: shouldIncludeVideo, onProgress: setProgress });
|
||||
} finally {
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -643,14 +643,14 @@ function App() {
|
|||
|
||||
const failedFiles: string[] = [];
|
||||
let i = 0;
|
||||
const setTotalProgress = (fileProgress = 0) => setCutProgress((i + fileProgress) / filePaths.length);
|
||||
const setTotalProgress = (fileProgress = 0) => setProgress((i + fileProgress) / filePaths.length);
|
||||
|
||||
const { selectedOption: speed } = await askForHtml5ifySpeed({ allowedOptions: ['fast-audio-remux', 'fast-audio', 'fast', 'slow', 'slow-audio', 'slowest'] });
|
||||
if (!speed) return;
|
||||
|
||||
if (workingRef.current) return;
|
||||
setWorking({ text: i18n.t('Batch converting to supported format') });
|
||||
setCutProgress(0);
|
||||
setProgress(0);
|
||||
try {
|
||||
await withErrorHandling(async () => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
@ -676,7 +676,7 @@ function App() {
|
|||
}, i18n.t('Failed to batch convert to supported format'));
|
||||
} finally {
|
||||
setWorking(undefined);
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
}
|
||||
}, [batchFiles, customOutDir, ensureWritableOutDir, html5ify, setWorking, workingRef]);
|
||||
|
||||
|
@ -848,7 +848,7 @@ function App() {
|
|||
// console.log('merge', paths);
|
||||
const metadataFromPath = paths[0];
|
||||
invariant(metadataFromPath != null);
|
||||
const { haveExcludedStreams } = await concatFiles({ paths, outPath, outDir, outFormat, metadataFromPath, includeAllStreams, streams, ffmpegExperimental, onProgress: setCutProgress, preserveMovData, movFastStart, preserveMetadataOnMerge, chapters: chaptersFromSegments });
|
||||
const { haveExcludedStreams } = await concatFiles({ paths, outPath, outDir, outFormat, metadataFromPath, includeAllStreams, streams, ffmpegExperimental, onProgress: setProgress, preserveMovData, movFastStart, preserveMetadataOnMerge, chapters: chaptersFromSegments });
|
||||
|
||||
const warnings: string[] = [];
|
||||
const notices: string[] = [];
|
||||
|
@ -892,7 +892,7 @@ function App() {
|
|||
handleConcatFailed(err, reportState);
|
||||
} finally {
|
||||
setWorking(undefined);
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
}
|
||||
}, [workingRef, setWorking, ensureWritableOutDir, customOutDir, segmentsToChapters, concatFiles, ffmpegExperimental, preserveMovData, movFastStart, preserveMetadataOnMerge, closeBatch, hideAllNotifications, showOsNotification, handleConcatFailed]);
|
||||
|
||||
|
@ -1018,7 +1018,7 @@ function App() {
|
|||
keyframeCut,
|
||||
segments: segmentsToExport,
|
||||
outSegFileNames,
|
||||
onProgress: setCutProgress,
|
||||
onProgress: setProgress,
|
||||
shortestFlag,
|
||||
ffmpegExperimental,
|
||||
preserveMovData,
|
||||
|
@ -1036,7 +1036,7 @@ function App() {
|
|||
if (willMerge) {
|
||||
console.log('mergedFileTemplateOrDefault', mergedFileTemplateOrDefault);
|
||||
|
||||
setCutProgress(0);
|
||||
setProgress(0);
|
||||
setWorking({ text: i18n.t('Merging') });
|
||||
|
||||
const chapterNames = segmentsToChapters && !invertCutSegments ? segmentsToExport.map((s) => s.name) : undefined;
|
||||
|
@ -1057,7 +1057,7 @@ function App() {
|
|||
ffmpegExperimental,
|
||||
preserveMovData,
|
||||
movFastStart,
|
||||
onProgress: setCutProgress,
|
||||
onProgress: setProgress,
|
||||
chapterNames,
|
||||
autoDeleteMergedSegments,
|
||||
preserveMetadataOnMerge,
|
||||
|
@ -1081,7 +1081,7 @@ function App() {
|
|||
|
||||
if (exportExtraStreams) {
|
||||
try {
|
||||
setCutProgress(undefined); // If extracting extra streams takes a long time, prevent loader from being stuck at 100%
|
||||
setProgress(undefined); // If extracting extra streams takes a long time, prevent loader from being stuck at 100%
|
||||
setWorking({ text: i18n.t('Extracting {{count}} unprocessable tracks', { count: nonCopiedExtraStreams.length }) });
|
||||
await extractStreams({ filePath, customOutDir, streams: nonCopiedExtraStreams, enableOverwriteOutput });
|
||||
notices.push(i18n.t('Unprocessable streams were exported as separate files.'));
|
||||
|
@ -1128,7 +1128,7 @@ function App() {
|
|||
handleExportFailed(err);
|
||||
} finally {
|
||||
setWorking(undefined);
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
}
|
||||
}, [filePath, numStreamsToCopy, segmentsToExport, haveInvalidSegs, workingRef, setWorking, segmentsToChaptersOnly, outSegTemplateOrDefault, generateOutSegFileNames, cutMultiple, outputDir, customOutDir, fileFormat, duration, isRotationSet, effectiveRotation, copyFileStreams, allFilesMeta, keyframeCut, shortestFlag, ffmpegExperimental, preserveMovData, preserveMetadataOnMerge, movFastStart, avoidNegativeTs, customTagsByFile, paramsByStreamId, detectedFps, willMerge, enableOverwriteOutput, exportConfirmEnabled, mainFileFormatData, mainStreams, exportExtraStreams, areWeCutting, hideAllNotifications, cleanupChoices.cleanupAfterExport, cleanupFilesWithDialog, selectedSegmentsOrInverse, mergedFileTemplateOrDefault, segmentsToChapters, invertCutSegments, generateMergedFileNames, autoConcatCutSegments, autoDeleteMergedSegments, nonCopiedExtraStreams, showOsNotification, handleExportFailed]);
|
||||
|
||||
|
@ -1170,15 +1170,15 @@ function App() {
|
|||
setWorking({ text: i18n.t('Extracting frames') });
|
||||
console.log('Extracting frames as images', { segIds, captureFramesResponse });
|
||||
|
||||
setCutProgress(0);
|
||||
setProgress(0);
|
||||
|
||||
let lastOutPath: string | undefined;
|
||||
|
||||
const segmentProgresses: Record<number, number> = {};
|
||||
const handleSegmentProgress = (segIndex: number, progress: number) => {
|
||||
segmentProgresses[segIndex] = progress;
|
||||
const handleSegmentProgress = (segIndex: number, segmentProgress: number) => {
|
||||
segmentProgresses[segIndex] = segmentProgress;
|
||||
const totalProgress = segments.reduce((acc, _ignored, index) => acc + (segmentProgresses[index] ?? 0), 0);
|
||||
setCutProgress(totalProgress / segments.length);
|
||||
setProgress(totalProgress / segments.length);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
@ -1186,7 +1186,7 @@ function App() {
|
|||
const { start, end } = segment;
|
||||
if (filePath == null) throw new Error();
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
lastOutPath = await captureFramesRange({ customOutDir, filePath, fps: detectedFps, fromTime: start, toTime: end, estimatedMaxNumFiles: captureFramesResponse.estimatedMaxNumFiles, captureFormat, quality: captureFrameQuality, filter: captureFramesResponse.filter, outputTimestamps: captureFrameFileNameFormat === 'timestamp', onProgress: (progress) => handleSegmentProgress(index, progress) });
|
||||
lastOutPath = await captureFramesRange({ customOutDir, filePath, fps: detectedFps, fromTime: start, toTime: end, estimatedMaxNumFiles: captureFramesResponse.estimatedMaxNumFiles, captureFormat, quality: captureFrameQuality, filter: captureFramesResponse.filter, outputTimestamps: captureFrameFileNameFormat === 'timestamp', onProgress: (segmentProgress) => handleSegmentProgress(index, segmentProgress) });
|
||||
}
|
||||
if (!hideAllNotifications && lastOutPath != null) {
|
||||
showOsNotification(i18n.t('Frames have been extracted'));
|
||||
|
@ -1197,7 +1197,7 @@ function App() {
|
|||
handleError(err);
|
||||
} finally {
|
||||
setWorking(undefined);
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
}
|
||||
}, [apparentCutSegments, captureFormat, captureFrameFileNameFormat, captureFrameQuality, captureFramesRange, customOutDir, detectedFps, filePath, getFrameCount, hideAllNotifications, outputDir, setWorking, showOsNotification, workingRef]);
|
||||
|
||||
|
@ -1600,16 +1600,16 @@ function App() {
|
|||
try {
|
||||
await withErrorHandling(async () => {
|
||||
setWorking({ text: i18n.t('Fixing file duration') });
|
||||
setCutProgress(0);
|
||||
setProgress(0);
|
||||
invariant(fileFormat != null);
|
||||
const path = await fixInvalidDuration({ fileFormat, customOutDir, onProgress: setCutProgress });
|
||||
const path = await fixInvalidDuration({ fileFormat, customOutDir, onProgress: setProgress });
|
||||
showNotification({ icon: 'info', text: i18n.t('Duration has been fixed') });
|
||||
|
||||
await loadMedia({ filePath: path });
|
||||
}, i18n.t('Failed to fix file duration'));
|
||||
} finally {
|
||||
setWorking(undefined);
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
}
|
||||
}, [checkFileOpened, customOutDir, fileFormat, fixInvalidDuration, loadMedia, setWorking, showNotification, workingRef]);
|
||||
|
||||
|
@ -2438,7 +2438,7 @@ function App() {
|
|||
)}
|
||||
|
||||
<AnimatePresence>
|
||||
{working && <Working text={working.text} cutProgress={cutProgress} onAbortClick={abortWorking} />}
|
||||
{working && <Working text={working.text} progress={progress} onAbortClick={abortWorking} />}
|
||||
</AnimatePresence>
|
||||
|
||||
{tunerVisible && <ValueTuners type={tunerVisible} onFinished={() => setTunerVisible(undefined)} />}
|
||||
|
|
|
@ -8,8 +8,8 @@ import { primaryColor } from '../colors';
|
|||
import loadingLottie from '../7077-magic-flow.json';
|
||||
|
||||
|
||||
function Working({ text, cutProgress, onAbortClick }: {
|
||||
text: string, cutProgress?: number | undefined, onAbortClick: () => void
|
||||
function Working({ text, progress, onAbortClick }: {
|
||||
text: string, progress?: number | undefined, onAbortClick: () => void
|
||||
}) {
|
||||
return (
|
||||
<div style={{ position: 'absolute', bottom: 0, top: 0, left: 0, right: 0, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
|
@ -32,9 +32,9 @@ function Working({ text, cutProgress, onAbortClick }: {
|
|||
{text}...
|
||||
</div>
|
||||
|
||||
{(cutProgress != null) && (
|
||||
{(progress != null) && (
|
||||
<div style={{ marginTop: 5 }}>
|
||||
{`${(cutProgress * 100).toFixed(1)} %`}
|
||||
{`${(progress * 100).toFixed(1)} %`}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
@ -459,7 +459,7 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea
|
|||
|
||||
console.log('Smart cut on video stream', videoStreamIndex);
|
||||
|
||||
const onCutProgress = (progress: number) => onSingleProgress(i, progress / 2);
|
||||
const onProgress = (progress: number) => onSingleProgress(i, progress / 2);
|
||||
const onConcatProgress = (progress: number) => onSingleProgress(i, (1 + progress) / 2);
|
||||
|
||||
const copyFileStreamsFiltered = [{
|
||||
|
@ -501,7 +501,7 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea
|
|||
|
||||
// for smart cut we need to use keyframe cut here, and no avoid_negative_ts
|
||||
await losslessCutSingle({
|
||||
cutFrom: losslessCutFrom, cutTo, chaptersPath, outPath: losslessPartOutPath, copyFileStreams: copyFileStreamsFiltered, keyframeCut: true, avoidNegativeTs: undefined, videoDuration, rotation, allFilesMeta, outFormat, shortestFlag, ffmpegExperimental, preserveMovData, movFastStart, customTagsByFile, paramsByStreamId, videoTimebase, onProgress: onCutProgress,
|
||||
cutFrom: losslessCutFrom, cutTo, chaptersPath, outPath: losslessPartOutPath, copyFileStreams: copyFileStreamsFiltered, keyframeCut: true, avoidNegativeTs: undefined, videoDuration, rotation, allFilesMeta, outFormat, shortestFlag, ffmpegExperimental, preserveMovData, movFastStart, customTagsByFile, paramsByStreamId, videoTimebase, onProgress,
|
||||
});
|
||||
|
||||
// OK, just return the single cut file (we may need smart cut in other segments though)
|
||||
|
|
|
@ -21,11 +21,11 @@ import { FFprobeStream } from '../../../../ffprobe';
|
|||
const { ffmpeg: { blackDetect, silenceDetect } } = window.require('@electron/remote').require('./index.js');
|
||||
|
||||
|
||||
function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly, timecodePlaceholder, parseTimecode }: {
|
||||
function useSegments({ filePath, workingRef, setWorking, setProgress, videoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly, timecodePlaceholder, parseTimecode }: {
|
||||
filePath?: string | undefined,
|
||||
workingRef: MutableRefObject<boolean>,
|
||||
setWorking: (w: { text: string, abortController?: AbortController } | undefined) => void,
|
||||
setCutProgress: (a: number | undefined) => void,
|
||||
setProgress: (a: number | undefined) => void,
|
||||
videoStream: FFprobeStream | undefined,
|
||||
duration?: number | undefined,
|
||||
getRelevantTime: () => number,
|
||||
|
@ -100,7 +100,7 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
|
|||
if (workingRef.current) return;
|
||||
try {
|
||||
setWorking({ text: workingText });
|
||||
setCutProgress(0);
|
||||
setProgress(0);
|
||||
|
||||
const newSegments = await fn();
|
||||
console.log(name, newSegments);
|
||||
|
@ -109,9 +109,9 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
|
|||
if (!(err instanceof Error && err.name === 'AbortError')) handleError(errorText, err);
|
||||
} finally {
|
||||
setWorking(undefined);
|
||||
setCutProgress(undefined);
|
||||
setProgress(undefined);
|
||||
}
|
||||
}, [filePath, workingRef, setWorking, setCutProgress, loadCutSegments]);
|
||||
}, [filePath, workingRef, setWorking, setProgress, loadCutSegments]);
|
||||
|
||||
const getSegApparentEnd = useCallback((seg: SegmentBase) => getSegApparentEnd2(seg, duration), [duration]);
|
||||
|
||||
|
@ -148,8 +148,8 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
|
|||
const { mode, ...filterOptions } = parameters;
|
||||
invariant(mode === '1' || mode === '2');
|
||||
invariant(filePath != null);
|
||||
await detectSegments({ name: 'blackScenes', workingText: i18n.t('Detecting black scenes'), errorText: i18n.t('Failed to detect black scenes'), fn: async () => blackDetect({ filePath, filterOptions, boundingMode: mode === '1', onProgress: setCutProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
|
||||
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setCutProgress]);
|
||||
await detectSegments({ name: 'blackScenes', workingText: i18n.t('Detecting black scenes'), errorText: i18n.t('Failed to detect black scenes'), fn: async () => blackDetect({ filePath, filterOptions, boundingMode: mode === '1', onProgress: setProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
|
||||
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setProgress]);
|
||||
|
||||
const detectSilentScenes = useCallback(async () => {
|
||||
const parameters = await showParametersDialog({ title: i18n.t('Enter parameters'), parameters: ffmpegParameters.silencedetect(), docUrl: 'https://ffmpeg.org/ffmpeg-filters.html#silencedetect' });
|
||||
|
@ -157,8 +157,8 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
|
|||
const { mode, ...filterOptions } = parameters;
|
||||
invariant(mode === '1' || mode === '2');
|
||||
invariant(filePath != null);
|
||||
await detectSegments({ name: 'silentScenes', workingText: i18n.t('Detecting silent scenes'), errorText: i18n.t('Failed to detect silent scenes'), fn: async () => silenceDetect({ filePath, filterOptions, boundingMode: mode === '1', onProgress: setCutProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
|
||||
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setCutProgress]);
|
||||
await detectSegments({ name: 'silentScenes', workingText: i18n.t('Detecting silent scenes'), errorText: i18n.t('Failed to detect silent scenes'), fn: async () => silenceDetect({ filePath, filterOptions, boundingMode: mode === '1', onProgress: setProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
|
||||
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setProgress]);
|
||||
|
||||
const detectSceneChanges = useCallback(async () => {
|
||||
const filterOptions = await showParametersDialog({ title: i18n.t('Enter parameters'), parameters: ffmpegParameters.sceneChange() });
|
||||
|
@ -167,8 +167,8 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
|
|||
// eslint-disable-next-line prefer-destructuring
|
||||
const minChange = filterOptions['minChange'];
|
||||
invariant(minChange != null);
|
||||
await detectSegments({ name: 'sceneChanges', workingText: i18n.t('Detecting scene changes'), errorText: i18n.t('Failed to detect scene changes'), fn: async () => ffmpegDetectSceneChanges({ filePath, minChange, onProgress: setCutProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
|
||||
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setCutProgress]);
|
||||
await detectSegments({ name: 'sceneChanges', workingText: i18n.t('Detecting scene changes'), errorText: i18n.t('Failed to detect scene changes'), fn: async () => ffmpegDetectSceneChanges({ filePath, minChange, onProgress: setProgress, from: currentApparentCutSeg.start, to: currentApparentCutSeg.end }) });
|
||||
}, [currentApparentCutSeg.end, currentApparentCutSeg.start, detectSegments, filePath, setProgress]);
|
||||
|
||||
const createSegmentsFromKeyframes = useCallback(async () => {
|
||||
if (!videoStream) return;
|
||||
|
|
|
@ -432,11 +432,14 @@ export function checkFileSizes(inputSize: number, outputSize: number) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
export function setDocumentTitle({ filePath, working, cutProgress }: { filePath?: string | undefined, working?: string | undefined, cutProgress?: number | undefined }) {
|
||||
export function setDocumentTitle({ filePath, working, progress }: {
|
||||
filePath?: string | undefined,
|
||||
working?: string | undefined,
|
||||
progress?: number | undefined }) {
|
||||
const parts: string[] = [];
|
||||
|
||||
if (working) {
|
||||
if (cutProgress != null) parts.push(`${(cutProgress * 100).toFixed(1)}%`);
|
||||
if (progress != null) parts.push(`${(progress * 100).toFixed(1)}%`);
|
||||
parts.push(working);
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue