finally fix race conditions for file progress

uses sse to deliver updates
This commit is contained in:
WaveringAna 2025-01-19 22:24:23 -05:00
parent 19613e1bb3
commit 6be6d3b15f
9 changed files with 492 additions and 483 deletions

View file

@ -0,0 +1,56 @@
import ffmpeg from 'fluent-ffmpeg';
import { progressManager } from './ProgressManager';
import { EncodingType, currentEncoding } from '../lib/ffmpeg';
export class MediaProcessor {
static async processVideo(
inputPath: string,
filename: string,
extension: string
): Promise<void> {
console.log("Starting video processing:", filename); // Debug log
const outputPath = `uploads/720p-${filename}${extension}`;
const outputOptions = [
'-vf', 'scale=-2:720',
'-c:v', currentEncoding,
'-c:a', 'copy',
'-pix_fmt', 'yuv420p'
];
return new Promise((resolve, reject) => {
ffmpeg()
.input(inputPath)
.outputOptions(outputOptions)
.output(outputPath)
.on('progress', (progress) => {
console.log("Progress:", progress.percent); // Debug log
progressManager.updateProgress({
filename: `${filename}${extension}`,
progress: progress.percent / 100,
status: 'processing'
});
})
.on('end', () => {
console.log("Processing complete:", filename); // Debug log
progressManager.updateProgress({
filename: `${filename}${extension}`,
progress: 1,
status: 'complete'
});
resolve();
})
.on('error', (err) => {
console.error("Processing error:", err); // Debug log
progressManager.updateProgress({
filename: `${filename}${extension}`,
progress: 0,
status: 'error',
message: err.message
});
reject(err);
})
.run();
});
}
}

View file

@ -0,0 +1,45 @@
import { EventEmitter } from 'events';
export interface ProgressUpdate {
filename: string;
progress: number;
status: 'processing' | 'complete' | 'error';
message?: string;
}
class ProgressManager {
private static instance: ProgressManager;
private emitter: EventEmitter;
private activeJobs: Map<string, ProgressUpdate>;
private constructor() {
this.emitter = new EventEmitter();
this.activeJobs = new Map();
}
static getInstance(): ProgressManager {
if (!ProgressManager.instance) {
ProgressManager.instance = new ProgressManager();
}
return ProgressManager.instance;
}
updateProgress(update: ProgressUpdate) {
this.activeJobs.set(update.filename, update);
this.emitter.emit('progress', update);
}
subscribeToUpdates(callback: (update: ProgressUpdate) => void) {
this.emitter.on('progress', callback);
}
unsubscribeFromUpdates(callback: (update: ProgressUpdate) => void) {
this.emitter.off('progress', callback);
}
getJobStatus(filename: string): ProgressUpdate | undefined {
return this.activeJobs.get(filename);
}
}
export const progressManager = ProgressManager.getInstance();