diff --git a/src/common/util.ts b/src/common/util.ts index 1d1849b6..687dee6b 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -5,3 +5,7 @@ export const parseFfprobeDuration = (durationStr: string | undefined) => ( ); export const getHwaccelArgs = (hwaccel: FfmpegHwAccel) => (hwaccel !== 'none' ? ['-hwaccel', hwaccel] : []); + +// Used to be 5, but we recently increased to 6 because https://github.com/mifi/lossless-cut/issues/2838 +// I don't remember why 5 was chosen initially, but if we don't truncate, ffmpeg can sometimes give an error when too many decimal places are used in the time argument, see: +export const formatFfmpegTime = (time: number) => time.toFixed(6); diff --git a/src/main/ffmpeg.ts b/src/main/ffmpeg.ts index 1487d1cc..eeab304f 100644 --- a/src/main/ffmpeg.ts +++ b/src/main/ffmpeg.ts @@ -14,7 +14,7 @@ import type { FFprobeFormat } from '../common/ffprobe.js'; import isDev from './isDev.js'; import logger from './logger.js'; import { parseFfmpegProgressLine } from './progress.js'; -import { getHwaccelArgs, parseFfprobeDuration } from '../common/util.js'; +import { formatFfmpegTime, getHwaccelArgs, parseFfprobeDuration } from '../common/util.js'; import { getFfmpegJpegQuality } from './ffmpegUtil.js'; @@ -260,9 +260,9 @@ export async function renderWaveformPng({ filePath, start, duration, resample, c } const getInputSeekArgs = ({ filePath, from, to }: { filePath: string, from?: number | undefined, to?: number | undefined }) => [ - ...(from != null ? ['-ss', from.toFixed(5)] : []), + ...(from != null ? ['-ss', formatFfmpegTime(from)] : []), '-i', filePath, - ...(from != null && to != null ? ['-t', (to - from).toFixed(5)] : []), + ...(from != null && to != null ? ['-t', formatFfmpegTime(to - from)] : []), ]; export function mapTimesToSegments(times: number[], includeLast: boolean) { diff --git a/src/renderer/src/hooks/useFfmpegOperations.ts b/src/renderer/src/hooks/useFfmpegOperations.ts index 8a054a7e..c524e946 100644 --- a/src/renderer/src/hooks/useFfmpegOperations.ts +++ b/src/renderer/src/hooks/useFfmpegOperations.ts @@ -16,7 +16,7 @@ import { deleteDispositionValue, type AllFilesMeta, type Chapter, type CopyfileS import type { LossyMode } from '../../../main'; import { UserFacingError } from '../../errors'; import mainApi from '../mainApi'; -import { getHwaccelArgs } from '../../../common/util'; +import { formatFfmpegTime, getHwaccelArgs } from '../../../common/util'; const { join, resolve, dirname } = window.require('path'); const { writeFile, mkdir, access, constants: { W_OK } } = window.require('fs/promises'); @@ -278,8 +278,8 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea if (detectedFps != null) cutDuration = Math.max(cutDuration, frameDuration); // ensure at least one frame duration // Don't cut if no need: https://github.com/mifi/lossless-cut/issues/50 - const cutFromArgs = cuttingStart ? ['-ss', cutFromWithAdjustment.toFixed(5)] : []; - const cutToArgs = cuttingEnd ? ['-t', cutDuration.toFixed(5)] : []; + const cutFromArgs = cuttingStart ? ['-ss', formatFfmpegTime(cutFromWithAdjustment)] : []; + const cutToArgs = cuttingEnd ? ['-t', formatFfmpegTime(cutDuration)] : []; const copyFileStreamsFiltered = copyFileStreams.filter(({ streamIds }) => streamIds.length > 0); @@ -480,10 +480,10 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea // No progress if we set loglevel warning :( // '-loglevel', 'warning', - '-ss', cutFrom.toFixed(5), // if we don't -ss before -i, seeking will be slow for long files, see https://github.com/mifi/lossless-cut/issues/126#issuecomment-1135451043 + '-ss', formatFfmpegTime(cutFrom), // if we don't -ss before -i, seeking will be slow for long files, see https://github.com/mifi/lossless-cut/issues/126#issuecomment-1135451043 '-i', filePath, '-ss', '0', // If we don't do this, the output seems to start with an empty black after merging with the encoded part - '-t', (cutTo - cutFrom).toFixed(5), + '-t', formatFfmpegTime(cutTo - cutFrom), ...mapStreamsArgs,