1
0
mirror of https://github.com/mifi/lossless-cut.git synced 2024-11-21 18:02:35 +01:00

add tests

This commit is contained in:
Mikael Finstad 2024-09-26 09:07:34 +03:00
parent b61456c71a
commit 4c00987db9
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26
4 changed files with 70 additions and 40 deletions

View File

@ -11,6 +11,7 @@ import { platform, arch, isWindows, isMac, isLinux } from './util.js';
import { CaptureFormat, Html5ifyMode, Waveform } from '../../types.js';
import isDev from './isDev.js';
import logger from './logger.js';
import { parseFfmpegProgressLine } from './progress.js';
const runningFfmpegs = new Set<ExecaChildProcess<Buffer>>();
@ -55,9 +56,9 @@ export function abortFfmpegs() {
function handleProgress(
process: { stderr: Readable | null },
durationIn: number | undefined,
duration: number | undefined,
onProgress: (a: number) => void,
customMatcher: (a: string) => void = () => undefined,
customMatcher?: (a: string) => void,
) {
if (!onProgress) return;
if (process.stderr == null) return;
@ -68,44 +69,10 @@ function handleProgress(
// console.log('progress', line);
try {
// eslint-disable-next-line unicorn/better-regex
let match = line.match(/frame=\s*[^\s]+\s+fps=\s*[^\s]+\s+q=\s*[^\s]+\s+(?:size|Lsize)=\s*[^\s]+\s+time=\s*([^\s]+)\s+/);
// Audio only looks like this: "line size= 233422kB time=01:45:50.68 bitrate= 301.1kbits/s speed= 353x "
// eslint-disable-next-line unicorn/better-regex
if (!match) match = line.match(/(?:size|Lsize)=\s*[^\s]+\s+time=\s*([^\s]+)\s+/);
if (!match) {
customMatcher(line);
return;
const progress = parseFfmpegProgressLine({ line, customMatcher, duration });
if (progress != null) {
onProgress(progress);
}
const timeStr = match[1];
// console.log(timeStr);
const match2 = timeStr!.match(/^(-?)(\d+):(\d+):(\d+)\.(\d+)$/);
if (!match2) throw new Error(`Invalid time from ffmpeg progress ${timeStr}`);
const sign = match2[1];
if (sign === '-') {
// For some reason, ffmpeg sometimes gives a negative progress, e.g. "-00:00:06.46"
// let's just ignore that
return;
}
const h = parseInt(match2[2]!, 10);
const m = parseInt(match2[3]!, 10);
const s = parseInt(match2[4]!, 10);
const cs = parseInt(match2[5]!, 10);
const time = (((h * 60) + m) * 60 + s) + cs / 100;
// console.log(time);
const progressTime = Math.max(0, time);
// console.log(progressTime);
if (durationIn == null) return;
const duration = Math.max(0, durationIn);
if (duration === 0) return;
const progress = Math.min(progressTime / duration, 1); // sometimes progressTime will be greater than cutDuration
onProgress(progress);
} catch (err) {
logger.error('Failed to parse ffmpeg progress line:', err instanceof Error ? err.message : err);
}

View File

@ -1,4 +1,3 @@
// eslint-disable-line unicorn/filename-case
// eslint-disable-next-line import/no-extraneous-dependencies
import { test, expect, describe } from 'vitest';

18
src/main/progress.test.ts Normal file
View File

@ -0,0 +1,18 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { describe, expect, test } from 'vitest';
import { parseFfmpegProgressLine } from './progress';
describe('parseFfmpegProgressLine', () => {
test('parse video', () => {
const str = 'frame= 2285 fps=135 q=4.0 Lsize=N/A time=00:01:31.36 bitrate=N/A speed=5.38x ';
expect(parseFfmpegProgressLine({ line: str, duration: 60 + 31.36 })).toBe(1);
});
test('parse audio 0', () => {
const str = 'size= 0kB time=00:00:00.00 bitrate=N/A speed=N/A ';
expect(parseFfmpegProgressLine({ line: str, duration: 1 })).toBe(0);
});
test('parse audio 32.02', () => {
const str = 'size= 501kB time=00:00:32.02 bitrate= 128.2kbits/s speed=2.29e+03x ';
expect(parseFfmpegProgressLine({ line: str, duration: 32.02 })).toBe(1);
});
});

46
src/main/progress.ts Normal file
View File

@ -0,0 +1,46 @@
// eslint-disable-next-line import/prefer-default-export
export function parseFfmpegProgressLine({ line, customMatcher, duration: durationIn }: {
line: string,
customMatcher?: ((a: string) => void) | undefined,
duration: number | undefined,
}) {
let match = line.match(/frame=\s*\S+\s+fps=\s*\S+\s+q=\s*\S+\s+(?:size|Lsize)=\s*\S+\s+time=\s*(\S+)\s+/);
if (!match) {
// Audio only looks like this: "size= 233422kB time=01:45:50.68 bitrate= 301.1kbits/s speed= 353x "
match = line.match(/(?:size|Lsize)=\s*\S+\s+time=\s*(\S+)\s+/);
}
if (!match) {
customMatcher?.(line);
return undefined;
}
if (durationIn == null) return undefined;
const duration = Math.max(0, durationIn);
if (duration === 0) return undefined;
const timeStr = match[1];
// console.log(timeStr);
const match2 = timeStr!.match(/^(-?)(\d+):(\d+):(\d+)\.(\d+)$/);
if (!match2) throw new Error(`Invalid time from ffmpeg progress ${timeStr}`);
const sign = match2[1];
if (sign === '-') {
// For some reason, ffmpeg sometimes gives a negative progress, e.g. "-00:00:06.46"
// let's just ignore those lines
return undefined;
}
const h = parseInt(match2[2]!, 10);
const m = parseInt(match2[3]!, 10);
const s = parseInt(match2[4]!, 10);
const cs = parseInt(match2[5]!, 10);
const time = (((h * 60) + m) * 60 + s) + cs / 100;
// console.log(time);
const progressTime = Math.max(0, time);
// console.log(progressTime);
const progress = Math.min(progressTime / duration, 1); // sometimes progressTime will be greater than cutDuration
return progress;
}