change SEG_NUM and SESG_NUM_INT variables

they will now correspond to the original index of the segment
as shown in the number on the segment list
new variables SELECTED_SEG_NUM and SELECTED_SEG_NUM_INT
can be used for previous behavior (where the numbering is based on the segment's number in the list of *selected* segments).

also minor change: most operations will no longer take place if no segments selected

closes #2335
pull/2233/head
Mikael Finstad 1 year ago
parent e81d70a0ca
commit d84f31fd72
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26

@ -69,6 +69,8 @@ The following variables are available in the template to customize the filenames
| | `${FILE_EXPORT_COUNT}` | `number` | Number of exports done since last file was opened (starts at 1).
| | `${SEG_NUM}` | `string` | Segment index, padded string (e.g. `01`, `02` or `42`).
| | `${SEG_NUM_INT}` | `number` | Segment index, as an integer (e.g. `1`, `2` or `42`). Can be used with numeric arithmetics, e.g. `${SEG_NUM_INT+100}`.
| | `${SELECTED_SEG_NUM}` | `string` | Same as `SEG_NUM`, but it counts only selected segments.
| | `${SELECTED_SEG_NUM_INT}` | `number` | Same as `SEG_NUM_INT`, but it counts only selected segments.
| | `${SEG_LABEL}` | `string` | The label of the segment (e.g. `Getting Lunch`).
| | `${SEG_SUFFIX}` | `string` | If a label exists for this segment, the label will be used, prepended by `-`. Otherwise, the segment index prepended by `-seg` will be used (e.g. `-Getting_Lunch`, `-seg1`).
| | `${CUT_FROM}` | `string` | The timestamp for the beginning of the segment in `hh.mm.ss.sss` format (e.g. `00.00.27.184`).

@ -88,7 +88,7 @@ import { rightBarWidth, leftBarWidth, ffmpegExtractWindow, zoomMax } from './uti
import BigWaveform from './components/BigWaveform';
import isDev from './isDev';
import { BatchFile, Chapter, CustomTagsByFile, EdlExportType, EdlFileType, EdlImportType, FfmpegCommandLog, FilesMeta, goToTimecodeDirectArgsSchema, openFilesActionArgsSchema, ParamsByStreamId, PlaybackMode, SegmentBase, SegmentColorIndex, SegmentTags, SegmentToExport, StateSegment, TunerType } from './types';
import { BatchFile, Chapter, CustomTagsByFile, EdlExportType, EdlFileType, EdlImportType, FfmpegCommandLog, FilesMeta, goToTimecodeDirectArgsSchema, openFilesActionArgsSchema, ParamsByStreamId, PlaybackMode, SegmentBase, SegmentColorIndex, SegmentTags, StateSegment, TunerType } from './types';
import { CaptureFormat, KeyboardAction, Html5ifyMode, WaveformMode, ApiActionRequest, KeyBinding } from '../../../types';
import { FFprobeChapter, FFprobeFormat, FFprobeStream } from '../../../ffprobe';
import useLoading from './hooks/useLoading';
@ -767,7 +767,7 @@ function App() {
if (playbackModeRef.current === 'loop-selected-segments') {
const firstSelectedSegment = selectedSegments[0];
if (firstSelectedSegment != null) {
const index = cutSegments.indexOf(firstSelectedSegment);
const index = cutSegments.findIndex((segment) => segment.segId === firstSelectedSegment.segId);
if (index >= 0) setCurrentSegIndex(index);
seekAbs(firstSelectedSegment.start);
}
@ -797,7 +797,7 @@ function App() {
if (nextAction != null) {
console.log(nextAction);
if (nextAction.nextSegment) {
const index = selectedSegments.indexOf(playingSegment);
const index = selectedSegments.findIndex((selectedSegment) => selectedSegment.segId === playingSegment.segId);
let newIndex = getNewJumpIndex(index >= 0 ? index : 0, 1);
if (newIndex > selectedSegments.length - 1) newIndex = 0; // have reached end of last segment, start over
const nextSelectedSegment = selectedSegments[newIndex];
@ -1021,12 +1021,12 @@ function App() {
}
}, [cleanupFilesWithDialog, isFileOpened, setWorking, workingRef]);
const generateOutSegFileNames = useCallback(async ({ segments = segmentsToExport, template }: { segments?: SegmentToExport[], template: string }) => {
const generateOutSegFileNames = useCallback(async (template: string) => {
invariant(fileFormat != null && outputDir != null && filePath != null);
return generateOutSegFileNamesRaw({ fileDuration, exportCount, currentFileExportCount, segments, template, formatTimecode, isCustomFormatSelected, fileFormat, filePath, outputDir, safeOutputFileName, maxLabelLength, outputFileNameMinZeroPadding });
return generateOutSegFileNamesRaw({ fileDuration, exportCount, currentFileExportCount, segmentsToExport, template, formatTimecode, isCustomFormatSelected, fileFormat, filePath, outputDir, safeOutputFileName, maxLabelLength, outputFileNameMinZeroPadding });
}, [currentFileExportCount, exportCount, fileDuration, fileFormat, filePath, formatTimecode, isCustomFormatSelected, maxLabelLength, outputDir, outputFileNameMinZeroPadding, safeOutputFileName, segmentsToExport]);
const generateMergedFileNames = useCallback(async ({ template }: { template: string }) => {
const generateMergedFileNames = useCallback(async (template: string) => {
invariant(fileFormat != null && filePath != null);
return generateMergedFileNamesRaw({ template, isCustomFormatSelected, fileFormat, filePath, outputDir, safeOutputFileName, exportCount, currentFileExportCount });
}, [currentFileExportCount, exportCount, fileFormat, filePath, isCustomFormatSelected, outputDir, safeOutputFileName]);
@ -1071,7 +1071,7 @@ function App() {
const notices: string[] = [];
const warnings: string[] = [];
const { fileNames: outSegFileNames, problems: outSegProblems } = await generateOutSegFileNames({ segments: segmentsToExport, template: outSegTemplateOrDefault });
const { fileNames: outSegFileNames, problems: outSegProblems } = await generateOutSegFileNames(outSegTemplateOrDefault);
if (outSegProblems.error != null) {
console.warn('Output segments file name invalid, using default instead', outSegFileNames);
warnings.push(t('Fell back to default output file name'), outSegProblems.error);
@ -1114,7 +1114,7 @@ function App() {
const chapterNames = segmentsToChapters && !invertCutSegments ? segmentsToExport.map((s) => s.name) : undefined;
const { fileNames, problems } = await generateMergedFileNames({ template: mergedFileTemplateOrDefault });
const { fileNames, problems } = await generateMergedFileNames(mergedFileTemplateOrDefault);
if (problems.error != null) {
console.warn('Merged file name invalid, using default instead', fileNames[0]);
warnings.push(t('Fell back to default output file name'), problems.error);
@ -1234,7 +1234,7 @@ function App() {
}, [filePath, getRelevantTime, videoRef, usingPreviewFile, captureFrameMethod, captureFrameFromFfmpeg, customOutDir, captureFormat, captureFrameQuality, captureFrameFromTag, hideAllNotifications]);
const extractSegmentsFramesAsImages = useCallback(async (segments: SegmentBase[]) => {
if (!filePath || detectedFps == null || workingRef.current) return;
if (!filePath || detectedFps == null || workingRef.current || segments.length === 0) return;
const segmentsNumFrames = segments.reduce((acc, { start, end }) => acc + (end == null ? 1 : (getFrameCount(end - start) ?? 0)), 0);
const areAllSegmentsMarkers = segments.every((seg) => seg.end == null);
const captureFramesResponse = areAllSegmentsMarkers
@ -1901,7 +1901,7 @@ function App() {
const toggleLoopSelectedSegments = useCallback(() => togglePlay({ resetPlaybackRate: true, requestPlaybackMode: 'loop-selected-segments' }), [togglePlay]);
const copySegmentsToClipboard = useCallback(async () => {
if (!isFileOpened) return;
if (!isFileOpened || selectedSegments.length === 0) return;
electron.clipboard.writeText(await formatTsv(selectedSegments));
}, [isFileOpened, selectedSegments]);
@ -2255,7 +2255,7 @@ function App() {
const onVideoClick = useCallback(() => togglePlay(), [togglePlay]);
const tryExportEdlFile = useCallback(async (type: EdlExportType) => {
if (!checkFileOpened()) return;
if (!checkFileOpened() || selectedSegments.length === 0) return;
await withErrorHandling(async () => {
await exportEdlFile({ type, cutSegments: selectedSegments, customOutDir, filePath, getFrameCount });
}, i18n.t('Failed to export project'));

@ -324,7 +324,6 @@ function SegmentList({
const segmentsTotal = useMemo(() => selectedSegments.reduce((acc, seg) => (seg.end == null ? 0 : seg.end - seg.start) + acc, 0), [selectedSegments]);
const segmentsOrInverse: (InverseCutSegment | StateSegment)[] = invertCutSegments ? inverseCutSegments : cutSegments;
const sortableList = useMemo(() => segmentsOrInverse.map((seg) => ({ id: seg.segId, seg })), [segmentsOrInverse]);

@ -9,7 +9,7 @@ import { FaEdit } from 'react-icons/fa';
import { ReactSwal } from '../swal';
import HighlightedText from './HighlightedText';
import { segNumVariable, segSuffixVariable, GenerateOutFileNames, extVariable, segTagsVariable, segNumIntVariable } from '../util/outputNameTemplate';
import { segNumVariable, segSuffixVariable, GenerateOutFileNames, extVariable, segTagsVariable, segNumIntVariable, selectedSegNumVariable, selectedSegNumIntVariable } from '../util/outputNameTemplate';
import useUserSettings from '../hooks/useUserSettings';
import Switch from './Switch';
import Select from './Select';
@ -48,7 +48,7 @@ function FileNameTemplateEditor(opts: {
const { t } = useTranslation();
const hasTextNumericPaddedValue = useMemo(() => [segNumVariable, segSuffixVariable].some((v) => debouncedText.includes(formatVariable(v))), [debouncedText]);
const hasTextNumericPaddedValue = useMemo(() => [segNumVariable, selectedSegNumVariable, segSuffixVariable].some((v) => debouncedText.includes(formatVariable(v))), [debouncedText]);
useEffect(() => {
if (debouncedText == null) {
@ -60,7 +60,7 @@ function FileNameTemplateEditor(opts: {
(async () => {
try {
// console.time('generateFileNames')
const outSegs = await generateFileNames({ template: debouncedText });
const outSegs = await generateFileNames(debouncedText);
// console.timeEnd('generateOutSegFileNames')
if (abortController.signal.aborted) return;
setFileNames(outSegs.fileNames);
@ -78,7 +78,7 @@ function FileNameTemplateEditor(opts: {
const availableVariables = useMemo(() => (mergeMode
? ['FILENAME', extVariable, 'EPOCH_MS', 'EXPORT_COUNT']
: ['FILENAME', 'CUT_FROM', 'CUT_TO', segNumVariable, segNumIntVariable, 'SEG_LABEL', segSuffixVariable, extVariable, segTagsExample, 'EPOCH_MS', 'EXPORT_COUNT', 'FILE_EXPORT_COUNT']
: ['FILENAME', 'CUT_FROM', 'CUT_TO', segNumVariable, segNumIntVariable, selectedSegNumVariable, selectedSegNumIntVariable, 'SEG_LABEL', segSuffixVariable, extVariable, segTagsExample, 'EPOCH_MS', 'EXPORT_COUNT', 'FILE_EXPORT_COUNT']
), [mergeMode]);
// eslint-disable-next-line no-template-curly-in-string

@ -8,7 +8,7 @@ import { getSuffixedOutPath, transferTimestamps, getOutFileExtension, getOutDir,
import { isCuttingStart, isCuttingEnd, runFfmpegWithProgress, getFfCommandLine, getDuration, createChaptersFromSegments, readFileMeta, getExperimentalArgs, getVideoTimescaleArgs, logStdoutStderr, runFfmpegConcat, RefuseOverwriteError, runFfmpeg } from '../ffmpeg';
import { getMapStreamsArgs, getStreamIdsToCopy } from '../util/streams';
import { getSmartCutParams } from '../smartcut';
import { isDurationValid } from '../segments';
import { getGuaranteedSegments, isDurationValid } from '../segments';
import { FFprobeStream } from '../../../../ffprobe';
import { AvoidNegativeTs, Html5ifyMode, PreserveMetadata } from '../../../../types';
import { AllFilesMeta, Chapter, CopyfileStreams, CustomTagsByFile, LiteFFprobeStream, ParamsByStreamId, SegmentToExport } from '../types';
@ -503,7 +503,7 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea
console.log('customTagsByFile', customTagsByFile);
console.log('paramsByStreamId', paramsByStreamId);
const segments = segmentsIn.length > 0 ? segmentsIn : [{ start: 0, end: fileDuration ?? 0, name: '' }];
const segments = getGuaranteedSegments(segmentsIn, fileDuration);
const singleProgresses: Record<number, number> = {};
function onSingleProgress(id: number, singleProgress: number) {

@ -173,7 +173,7 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea
return { start, end };
}, [currentCutSeg, fileDurationNonZero]);
const selectedSegmentsRaw = useMemo(() => cutSegments.filter((segment) => segment.selected), [cutSegments]);
const selectedSegments = useMemo(() => cutSegments.flatMap((segment, i) => (segment.selected ? [{ ...segment, originalIndex: i }] : [])), [cutSegments]);
const getFfmpegParameters = useCallback((key: FfmpegDialog) => {
const parameters = ffmpegParameters[key];
@ -272,9 +272,6 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea
});
}, [cutSegments, fileDuration, haveInvalidSegs]);
// If user has selected none, default to all instead.
const selectedSegments = useMemo(() => (selectedSegmentsRaw.length > 0 ? selectedSegmentsRaw : cutSegments), [cutSegments, selectedSegmentsRaw]);
const invertAllSegments = useCallback(() => {
// treat markers as 0 length
const sortedSegments = sortSegments(selectedSegments.map(({ end, ...rest }) => ({ ...rest, end: end ?? rest.start })));
@ -690,16 +687,16 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea
}, [cutSegments, getScopeSegment, safeSetCutSegments]);
const labelSelectedSegments = useCallback(async () => {
const firstSelectedSegment = selectedSegmentsRaw[0];
const firstSelectedSegment = selectedSegments[0];
if (firstSelectedSegment == null) return;
const { name } = firstSelectedSegment;
const value = await labelSegmentDialog({ currentName: name, maxLength: maxLabelLength });
if (value == null) return;
safeSetCutSegments((existingSegments) => existingSegments.map((existingSegment) => {
if (selectedSegmentsRaw.some((seg) => seg.segId === existingSegment.segId)) return { ...existingSegment, name: value };
if (selectedSegments.some((seg) => seg.segId === existingSegment.segId)) return { ...existingSegment, name: value };
return existingSegment;
}));
}, [maxLabelLength, selectedSegmentsRaw, safeSetCutSegments]);
}, [maxLabelLength, selectedSegments, safeSetCutSegments]);
const maybeCreateFullLengthSegment = useCallback((newFileDuration: number) => {
// don't use safeSetCutSegments because we want to set initial: true
@ -711,32 +708,37 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea
});
}, [createIndexedSegment, setCutSegments]);
const segmentsOrInverse = useMemo<{ selected: DefiniteSegmentBase[], all: DefiniteSegmentBase[] }>(() => {
const segmentsOrInverse = useMemo<{ selected: SegmentToExport[], all: DefiniteSegmentBase[] }>(() => {
// For invertCutSegments we do not support filtering (selecting) segments
if (invertCutSegments) {
return {
selected: inverseCutSegments,
selected: inverseCutSegments.map((seg, i) => ({ ...seg, originalIndex: i })),
all: inverseCutSegments,
};
}
// If user has selected no segments, default to all instead.
const selectedSegmentsWithFallback = selectedSegments.length > 0 ? selectedSegments : cutSegments.map((seg, i) => ({ ...seg, originalIndex: i }));
return {
// exclude markers (segments without any end)
// and exclude the initial segment, to prevent cutting when not really needed (if duration changes after the segment was created)
selected: filterNonMarkers(selectedSegments).filter((seg) => !seg.initial),
selected: filterNonMarkers(selectedSegmentsWithFallback).filter((seg) => !seg.initial),
// `all` includes also all non selected segments:
all: filterNonMarkers(cutSegments).filter((seg) => !seg.initial),
};
}, [cutSegments, inverseCutSegments, invertCutSegments, selectedSegments]);
const segmentsToExport = useMemo<SegmentToExport[]>(() => {
// segmentsToChaptersOnly is a special mode where all segments will be simply written out as chapters to one file: https://github.com/mifi/lossless-cut/issues/993#issuecomment-1037927595
// Chapters export mode: Emulate a single segment with no cuts (full timeline)
// 'segmentsToChaptersOnly' is a special mode where all segments will be simply written out as chapters to one file: https://github.com/mifi/lossless-cut/issues/993#issuecomment-1037927595
// Chapters export mode: Emulate no cuts (full timeline)
if (segmentsToChaptersOnly) return [];
// in other modes, return all selected segments
return segmentsOrInverse.selected;
}, [segmentsOrInverse.selected, segmentsToChaptersOnly]);
const removeSelectedSegments = useCallback(() => removeSegments(selectedSegmentsRaw.map((seg) => seg.segId)), [removeSegments, selectedSegmentsRaw]);
const removeSelectedSegments = useCallback(() => removeSegments(selectedSegments.map((seg) => seg.segId)), [removeSegments, selectedSegments]);
const selectOnlySegment = useCallback((seg: Pick<StateSegment, 'segId'>) => setCutSegments((existing) => existing.map((segment) => ({
...segment, selected: segment.segId === seg.segId,

@ -4,7 +4,7 @@ import minBy from 'lodash/minBy';
import maxBy from 'lodash/maxBy';
import invariant from 'tiny-invariant';
import { PlaybackMode, SegmentBase, SegmentTags, StateSegment } from './types';
import { PlaybackMode, SegmentBase, SegmentTags, SegmentToExport, StateSegment } from './types';
export const isDurationValid = (duration?: number): duration is number => duration != null && Number.isFinite(duration) && duration > 0;
@ -285,3 +285,5 @@ export function makeDurationSegments(segmentDuration: number, fileDuration: numb
}
export const isInitialSegment = (segments: StateSegment[]) => segments.length === 0 || (segments.length === 1 && segments[0]!.initial);
export const getGuaranteedSegments = <T extends SegmentToExport>(segments: T[], fileDuration: number | undefined) => (segments.length > 0 ? segments : [{ start: 0, end: fileDuration ?? 0, name: '', originalIndex: 0 }]);

@ -72,6 +72,7 @@ export interface StateSegment extends SegmentBase, SegmentColorIndex {
}
export interface SegmentToExport extends DefiniteSegmentBase {
originalIndex: number,
name?: string | undefined;
tags?: SegmentTags | undefined;
}

@ -1,16 +1,19 @@
import i18n from 'i18next';
import { PlatformPath } from 'node:path';
import pMap from 'p-map';
import max from 'lodash/max';
import { isMac, isWindows, hasDuplicates, filenamify, getOutFileExtension } from '../util';
import isDev from '../isDev';
import { getSegmentTags, formatSegNum } from '../segments';
import { getSegmentTags, formatSegNum, getGuaranteedSegments } from '../segments';
import { FormatTimecode, SegmentToExport } from '../types';
import safeishEval from '../worker/eval';
export const segNumVariable = 'SEG_NUM';
export const segNumIntVariable = 'SEG_NUM_INT';
export const selectedSegNumVariable = 'SELECTED_SEG_NUM';
export const selectedSegNumIntVariable = 'SELECTED_SEG_NUM_INT';
export const segSuffixVariable = 'SEG_SUFFIX';
export const extVariable = 'EXT';
export const segTagsVariable = 'SEG_TAGS';
@ -111,7 +114,7 @@ export const defaultCutMergedFileTemplate = '${FILENAME}-cut-merged-${EPOCH_MS}$
// eslint-disable-next-line no-template-curly-in-string
export const defaultMergedFileTemplate = '${FILENAME}-merged-${EPOCH_MS}${EXT}';
async function interpolateOutFileName(template: string, { epochMs, inputFileNameWithoutExt, ext, segSuffix, segNum, segNumPadded, segLabel, cutFrom, cutTo, tags, exportCount, currentFileExportCount }: {
async function interpolateOutFileName(template: string, { epochMs, inputFileNameWithoutExt, ext, segSuffix, segNum, segNumPadded, selectedSegNum, selectedSegNumPadded, segLabel, cutFrom, cutTo, tags, exportCount, currentFileExportCount }: {
epochMs: number,
inputFileNameWithoutExt: string,
ext: string,
@ -121,6 +124,8 @@ async function interpolateOutFileName(template: string, { epochMs, inputFileName
segSuffix: string,
segNum: number,
segNumPadded: string,
selectedSegNum: number,
selectedSegNumPadded: string,
segLabel: string,
cutFrom: string,
cutTo: string,
@ -131,7 +136,9 @@ async function interpolateOutFileName(template: string, { epochMs, inputFileName
[segSuffixVariable]: segSuffix,
[extVariable]: ext,
[segNumIntVariable]: segNum,
[segNumVariable]: segNumPadded, // todo rename this (breaking change)
[segNumVariable]: segNumPadded,
[selectedSegNumIntVariable]: selectedSegNum,
[selectedSegNumVariable]: selectedSegNumPadded,
SEG_LABEL: segLabel,
EPOCH_MS: epochMs,
CUT_FROM: cutFrom,
@ -164,9 +171,9 @@ function maybeTruncatePath(fileName: string, truncate: boolean) {
].join(pathSep);
}
export async function generateOutSegFileNames({ fileDuration, segments: segmentsIn, template: desiredTemplate, formatTimecode, isCustomFormatSelected, fileFormat, filePath, outputDir, safeOutputFileName, maxLabelLength, outputFileNameMinZeroPadding, exportCount, currentFileExportCount }: {
export async function generateOutSegFileNames({ fileDuration, segmentsToExport: segmentsToExportIn, template: desiredTemplate, formatTimecode, isCustomFormatSelected, fileFormat, filePath, outputDir, safeOutputFileName, maxLabelLength, outputFileNameMinZeroPadding, exportCount, currentFileExportCount }: {
fileDuration: number | undefined,
segments: SegmentToExport[],
segmentsToExport: SegmentToExport[],
template: string,
formatTimecode: FormatTimecode,
isCustomFormatSelected: boolean,
@ -179,15 +186,19 @@ export async function generateOutSegFileNames({ fileDuration, segments: segments
exportCount: number,
currentFileExportCount: number,
}) {
const segmentsToExport = getGuaranteedSegments(segmentsToExportIn, fileDuration);
async function generate({ template, forceSafeOutputFileName }: { template: string, forceSafeOutputFileName: boolean }) {
const epochMs = Date.now();
const segments = segmentsIn.length > 0 ? segmentsIn : [{ start: 0, end: fileDuration ?? 0, name: '' }];
const maxOriginalIndex = max(segmentsToExport.map((s) => s.originalIndex)) ?? 0;
return pMap(segments, async (segment, i) => {
return pMap(segmentsToExport, async (segment, i) => {
const { start, end, name = '' } = segment;
const segNum = i + 1;
const segNumPadded = formatSegNum(i, segments.length, outputFileNameMinZeroPadding);
const selectedSegNum = i + 1;
const selectedSegNumPadded = formatSegNum(i, segmentsToExport.length, outputFileNameMinZeroPadding);
const segNum = segment.originalIndex + 1;
const segNumPadded = formatSegNum(segment.originalIndex, maxOriginalIndex + 1, outputFileNameMinZeroPadding);
// Fields that did not come from the source file's name must be sanitized, because they may contain characters that are not supported by the target operating/file system
// however we disable this when the user has chosen to (safeOutputFileName === false)
@ -196,7 +207,7 @@ export async function generateOutSegFileNames({ fileDuration, segments: segments
function getSegSuffix() {
if (name) return `-${filenamifyOrNot(name)}`;
// https://github.com/mifi/lossless-cut/issues/583
if (segments.length > 1) return `-seg${segNumPadded}`;
if (segmentsToExport.length > 1) return `-seg${segNumPadded}`;
return '';
}
@ -206,8 +217,10 @@ export async function generateOutSegFileNames({ fileDuration, segments: segments
epochMs,
segNum,
segNumPadded,
inputFileNameWithoutExt,
selectedSegNum,
selectedSegNumPadded,
segSuffix: getSegSuffix(),
inputFileNameWithoutExt,
ext: getOutFileExtension({ isCustomFormatSelected, outFormat: fileFormat, filePath }),
segLabel: filenamifyOrNot(name),
cutFrom: formatTimecode({ seconds: start, fileNameFriendly: true }),
@ -231,7 +244,7 @@ export async function generateOutSegFileNames({ fileDuration, segments: segments
return { fileNames, problems };
}
export type GenerateOutFileNames = (a: { template: string }) => Promise<{
export type GenerateOutFileNames = (template: string) => Promise<{
fileNames: string[],
problems: {
error: string | undefined;

Loading…
Cancel
Save