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:
parent
b61456c71a
commit
4c00987db9
@ -11,6 +11,7 @@ import { platform, arch, isWindows, isMac, isLinux } from './util.js';
|
|||||||
import { CaptureFormat, Html5ifyMode, Waveform } from '../../types.js';
|
import { CaptureFormat, Html5ifyMode, Waveform } from '../../types.js';
|
||||||
import isDev from './isDev.js';
|
import isDev from './isDev.js';
|
||||||
import logger from './logger.js';
|
import logger from './logger.js';
|
||||||
|
import { parseFfmpegProgressLine } from './progress.js';
|
||||||
|
|
||||||
|
|
||||||
const runningFfmpegs = new Set<ExecaChildProcess<Buffer>>();
|
const runningFfmpegs = new Set<ExecaChildProcess<Buffer>>();
|
||||||
@ -55,9 +56,9 @@ export function abortFfmpegs() {
|
|||||||
|
|
||||||
function handleProgress(
|
function handleProgress(
|
||||||
process: { stderr: Readable | null },
|
process: { stderr: Readable | null },
|
||||||
durationIn: number | undefined,
|
duration: number | undefined,
|
||||||
onProgress: (a: number) => void,
|
onProgress: (a: number) => void,
|
||||||
customMatcher: (a: string) => void = () => undefined,
|
customMatcher?: (a: string) => void,
|
||||||
) {
|
) {
|
||||||
if (!onProgress) return;
|
if (!onProgress) return;
|
||||||
if (process.stderr == null) return;
|
if (process.stderr == null) return;
|
||||||
@ -68,44 +69,10 @@ function handleProgress(
|
|||||||
// console.log('progress', line);
|
// console.log('progress', line);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line unicorn/better-regex
|
const progress = parseFfmpegProgressLine({ line, customMatcher, duration });
|
||||||
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 (progress != null) {
|
||||||
// Audio only looks like this: "line size= 233422kB time=01:45:50.68 bitrate= 301.1kbits/s speed= 353x "
|
onProgress(progress);
|
||||||
// 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 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) {
|
} catch (err) {
|
||||||
logger.error('Failed to parse ffmpeg progress line:', err instanceof Error ? err.message : err);
|
logger.error('Failed to parse ffmpeg progress line:', err instanceof Error ? err.message : err);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// eslint-disable-line unicorn/filename-case
|
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
import { test, expect, describe } from 'vitest';
|
import { test, expect, describe } from 'vitest';
|
||||||
|
|
||||||
|
18
src/main/progress.test.ts
Normal file
18
src/main/progress.test.ts
Normal 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
46
src/main/progress.ts
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user