fix(downloads): improve ffmpeg logging

This commit is contained in:
Daniel 2026-03-31 10:23:03 -05:00
parent 286a123e02
commit 88ec8feb6b
4 changed files with 22 additions and 5 deletions

View file

@ -238,6 +238,10 @@ export function updateDownloadProgress(trackId, progress) {
progressFill.style.background = '#3b82f6'; // Blue for encoding
statusEl.textContent = `Converting: ${percent}%`;
} else if (progress instanceof ProgressMessage || progress.message) {
if (progress instanceof FfmpegProgress && (progress.stage == 'parsing' || progress.stage == 'stdout')) {
return;
}
progressFill.style.width = '100%';
progressFill.style.background = '#3b82f6';
statusEl.textContent = progress.message;
@ -961,7 +965,7 @@ function updateBulkDownloadProgress(notifEl, current, total, currentItem, progre
}
if (progress instanceof FfmpegProgress) {
if (progress.stage == 'stdout') {
if (progress.stage == 'stdout' || progress.stage == 'parsing') {
return;
}

View file

@ -55,11 +55,13 @@ async function ffmpegWorker(
const assets = loadFfmpeg();
return new Promise((resolve, reject) => {
let endCategory = null;
const worker = new FfmpegWorker();
// Handle abort signal
const abortHandler = () => {
worker.terminate();
endCategory?.();
reject(new FfmpegError('FFMPEG aborted'));
};
@ -72,20 +74,30 @@ async function ffmpegWorker(
}
worker.onmessage = (e) => {
const { type, blob, message, stage, progress } = e.data;
const { type, blob, message, stage, progress, command } = e.data;
if (type === 'complete') {
if (signal) signal.removeEventListener('abort', abortHandler);
worker.terminate();
endCategory?.();
resolve(blob);
} else if (type === 'error') {
if (signal) signal.removeEventListener('abort', abortHandler);
worker.terminate();
endCategory?.();
reject(new FfmpegError(message));
} else if (type === 'progress' && message) {
onProgress?.(new FfmpegProgress(stage, progress || 0, message));
} else if (type === 'progress' && stage != 'loading' && progress !== null) {
onProgress?.(new FfmpegProgress(stage, progress || 0, message));
} else if (type === 'command') {
if (logConsole) {
const consoleCategory = `ffmpeg ${command?.join(' ')}`;
// eslint-disable-next-line no-console
console.groupCollapsed(consoleCategory);
// eslint-disable-next-line no-console
endCategory = () => console.groupEnd();
}
} else if (type === 'log') {
onProgress?.(new FfmpegProgress('stdout', 0, message));
if (logConsole) {
@ -97,6 +109,7 @@ async function ffmpegWorker(
worker.onerror = (error) => {
if (signal) signal.removeEventListener('abort', abortHandler);
worker.terminate();
endCategory?.();
reject(new FfmpegError('Worker failed: ' + error.message));
};

View file

@ -1,6 +1,6 @@
export class FfmpegProgress implements MonochromeProgress {
constructor(
public readonly stage: 'loading' | 'encoding' | 'finalizing' | 'stdout',
public readonly stage: 'loading' | 'parsing' | 'encoding' | 'finalizing' | 'stdout',
public readonly progress: number,
public readonly message?: string
) {}

View file

@ -40,7 +40,7 @@ async function loadFFmpeg(loadOptions = {}) {
ffmpeg = new FFmpeg();
ffmpeg.on('log', ({ message }) => {
self.postMessage({ type: 'log', message });
self.postMessage({ type: 'log', stage: 'stdout', message });
// Try to extract total duration from input log
if (totalDurationSeconds === null) {
@ -124,7 +124,7 @@ self.onmessage = async (e) => {
}
const ffmpegArgs = ['-i', 'input', ...args, ...(output.name ? [output.name] : [])];
self.postMessage({ type: 'log', message: `FFmpeg command: ffmpeg ${ffmpegArgs.join(' ')}` });
self.postMessage({ type: 'command', command: ffmpegArgs });
const exitCode = await ffmpeg.exec(ffmpegArgs);