Fix video progress: parse each chunk, -progress pipe:2, out_time support

- Parse time= from each stderr chunk (not accumulated buffer)
- Add -progress pipe:2 flag for frequent progress output
- Support both time= and out_time= formats
- Progress only increases (no jumps back)
This commit is contained in:
treamz 2026-03-22 00:22:48 +03:00
parent 6aca7e9e47
commit 3353253cef

View File

@ -33,24 +33,26 @@ const jobs = new Map();
function runFFmpeg(args, jobId) {
return new Promise((resolve, reject) => {
const proc = spawn('ffmpeg', args, { timeout: 600000 }); // 10 min timeout
let stderr = '';
let stderrBuf = '';
proc.stderr.on('data', (d) => {
stderr += d.toString();
// Parse progress
const timeMatch = stderr.match(/time=(\d{2}):(\d{2}):(\d{2})/);
const chunk = d.toString();
stderrBuf += chunk;
// Parse progress — look for time= or out_time= in chunk
const timeMatch = chunk.match(/(?:out_time|time)=\s*(\d{2}):(\d{2}):(\d{2})[\.\d]*/);
if (timeMatch && jobs.has(jobId)) {
const secs = parseInt(timeMatch[1]) * 3600 + parseInt(timeMatch[2]) * 60 + parseInt(timeMatch[3]);
const job = jobs.get(jobId);
if (job.duration > 0) {
job.progress = Math.min(99, Math.round((secs / job.duration) * 100));
const pct = Math.min(99, Math.round((secs / job.duration) * 100));
if (pct > job.progress) job.progress = pct; // only increase
}
}
});
proc.on('close', (code) => {
if (code === 0) resolve();
else reject(new Error(`ffmpeg exited with code ${code}: ${stderr.slice(-500)}`));
else reject(new Error(`ffmpeg exited with code ${code}: ${stderrBuf.slice(-500)}`));
});
proc.on('error', reject);
@ -144,7 +146,7 @@ router.post('/convert', express.json(), async (req, res) => {
job.outputPath = outFile;
try {
let args = ['-y', '-i', job.inputPath];
let args = ['-y', '-progress', 'pipe:2', '-i', job.inputPath];
// Time range (for GIF or trim)
if (startTime !== undefined && startTime > 0) args.push('-ss', String(startTime));