@@ -586,6 +599,7 @@ function SegmentList({
onSelectAllMarkers={onSelectAllMarkers}
onInvertSelectedSegments={onInvertSelectedSegments}
onDuplicateSegmentClick={onDuplicateSegmentClick}
+ getSegEstimatedSize={getSegEstimatedSize}
/>
);
}
diff --git a/src/renderer/src/components/FileNameTemplateEditor.tsx b/src/renderer/src/components/FileNameTemplateEditor.tsx
index 4ad374fa..7570c701 100644
--- a/src/renderer/src/components/FileNameTemplateEditor.tsx
+++ b/src/renderer/src/components/FileNameTemplateEditor.tsx
@@ -197,7 +197,7 @@ function FileNameTemplateEditor(opts: {
>
+
{generated != null && generated.fileNames.length > 1 && (
@@ -221,7 +221,7 @@ function FileNameTemplateEditor(opts: {
)}
-
+
diff --git a/src/renderer/src/hooks/useSegments.tsx b/src/renderer/src/hooks/useSegments.tsx
index 01ed8034..ae37c268 100644
--- a/src/renderer/src/hooks/useSegments.tsx
+++ b/src/renderer/src/hooks/useSegments.tsx
@@ -8,7 +8,7 @@ import { Trans, useTranslation } from 'react-i18next';
import { FaLink } from 'react-icons/fa';
import { detectSceneChanges as ffmpegDetectSceneChanges, readFrames, mapTimesToSegments, findKeyframeNearTime } from '../ffmpeg';
-import { shuffleArray } from '../util';
+import { getFileSize, shuffleArray } from '../util';
import { errorToast } from '../swal';
import { createNumSegments as createNumSegmentsDialog, createFixedByteSixedSegments as createFixedByteSixedSegmentsDialog, createRandomSegments as createRandomSegmentsDialog, labelSegmentDialog, askForShiftSegments, askForAlignSegments, selectSegmentsByLabelDialog, askForSegmentDuration, toastError } from '../dialogs';
import { createSegment, sortSegments, invertSegments, combineOverlappingSegments as combineOverlappingSegments2, combineSelectedSegments as combineSelectedSegments2, isDurationValid, addSegmentColorIndex, filterNonMarkers, makeDurationSegments, isInitialSegment } from '../segments';
@@ -754,13 +754,22 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea
const createFixedByteSizedSegments = useCallback(async () => {
if (!checkFileOpened() || !isDurationValid(fileDuration)) return;
- const fileSize = mainFileMeta && parseInt(mainFileMeta.formatData.size, 10);
- invariant(fileSize != null && !Number.isNaN(fileSize));
+ invariant(mainFileMeta != null);
+ const fileSize = getFileSize(mainFileMeta.formatData);
+ invariant(fileSize != null);
const segmentDuration = await createFixedByteSixedSegmentsDialog({ fileDuration, fileSize });
if (segmentDuration == null) return;
loadCutSegments({ segments: makeDurationSegments(segmentDuration, fileDuration), append: true, clampDuration: fileDuration });
}, [checkFileOpened, fileDuration, loadCutSegments, mainFileMeta]);
+ const getSegEstimatedSize = useCallback((segment: Pick) => {
+ if (mainFileMeta == null || !isDurationValid(fileDuration) || segment.end == null) return undefined;
+ const fileSize = getFileSize(mainFileMeta.formatData);
+ if (fileSize == null) return undefined;
+ const segDuration = segment.end - segment.start;
+ return Math.round((segDuration / fileDuration) * fileSize);
+ }, [fileDuration, mainFileMeta]);
+
const createRandomSegments = useCallback(async () => {
if (!checkFileOpened() || currentCutSegOrWholeTimeline.duration <= 0) return;
const segments = await createRandomSegmentsDialog(currentCutSegOrWholeTimeline.duration);
@@ -1007,6 +1016,7 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea
createFixedDurationSegments,
createFixedByteSizedSegments,
createRandomSegments,
+ getSegEstimatedSize,
haveInvalidSegs,
currentSegIndexSafe,
currentCutSeg,
diff --git a/src/renderer/src/util.ts b/src/renderer/src/util.ts
index 9b3bf73b..568de531 100644
--- a/src/renderer/src/util.ts
+++ b/src/renderer/src/util.ts
@@ -11,6 +11,7 @@ import { ffmpegExtractWindow } from './util/constants';
import { appName } from '../../main/common';
import { Html5ifyMode } from '../../common/types';
import { UserFacingError } from '../errors';
+import { FFprobeFormat } from '../../common/ffprobe';
const { dirname, parse: parsePath, join, extname, isAbsolute, resolve, basename } = window.require('path');
const fsExtra = window.require('fs-extra');
@@ -398,6 +399,12 @@ export function getImportProjectType(filePath: string) {
return edlFormatForExtension[matchingExt];
}
+export function getFileSize(formatData: FFprobeFormat) {
+ const fileSize = parseInt(formatData.size, 10);
+ if (Number.isNaN(fileSize)) return undefined;
+ return fileSize;
+}
+
export const calcShouldShowWaveform = (zoomedDuration: number | undefined) => (zoomedDuration != null && zoomedDuration < ffmpegExtractWindow * 8);
export const calcShouldShowKeyframes = (zoomedDuration: number | undefined) => (zoomedDuration != null && zoomedDuration < ffmpegExtractWindow * 8);
diff --git a/yarn.lock b/yarn.lock
index d0799d70..4e0fbcc8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9152,7 +9152,7 @@ __metadata:
nanoid: "npm:^5.0.9"
p-map: "npm:^5.5.0"
p-retry: "npm:^6.2.0"
- pretty-bytes: "npm:^6.0.0"
+ pretty-bytes: "npm:^7.1.0"
react: "npm:^18.2.0"
react-dom: "npm:^18.2.0"
react-i18next: "npm:^16.2.4"
@@ -10815,10 +10815,10 @@ __metadata:
languageName: node
linkType: hard
-"pretty-bytes@npm:^6.0.0":
- version: 6.0.0
- resolution: "pretty-bytes@npm:6.0.0"
- checksum: 10/0bb9f95e617236404b29a8392c6efd82d65805f622f5e809ecd70068102be857d4e3276c86d2a32fa2ef851cc29472e380945dab7bec83ec79bd57a19a10faf7
+"pretty-bytes@npm:^7.1.0":
+ version: 7.1.0
+ resolution: "pretty-bytes@npm:7.1.0"
+ checksum: 10/75fb34fba44596dc69983039fce9288f3b247b513aba2d6dfe74727505fe43199fcd7a1cee95dbd5be56a431d30fbdb4d24d3a62b9cf22bb63fa706b81c2e540
languageName: node
linkType: hard