diff --git a/public/video.html b/public/video.html
index a37437e..444ae72 100644
--- a/public/video.html
+++ b/public/video.html
@@ -939,15 +939,8 @@
throw new Error(err.error || 'Ошибка запуска');
}
- const data = await res.json();
-
- // Server may return immediately (sync) or poll (async)
- if (data.status === 'done' || data.downloadUrl) {
- setProgressUI(100, 'Готово!');
- onConversionDone(data);
- } else {
- startPolling();
- }
+ // Server starts processing in background, poll for progress
+ startPolling();
} catch (err) {
showConversionError(err.message || 'Ошибка конвертации');
}
diff --git a/routes/video.js b/routes/video.js
index a5a8594..23c93f5 100644
--- a/routes/video.js
+++ b/routes/video.js
@@ -184,20 +184,21 @@ router.post('/convert', express.json(), async (req, res) => {
args.push(outFile);
- await runFFmpeg(args, jobId);
- job.status = 'done';
- job.progress = 100;
+ // Start ffmpeg in background — respond immediately
+ res.json({ status: 'processing' });
- const outStat = fs.statSync(outFile);
- const savings = job.size > 0 ? Math.round((1 - outStat.size / job.size) * 100) : 0;
-
- log.info(`Video ${mode}: ${job.originalName} → ${format} (${(outStat.size / 1024 / 1024).toFixed(1)}MB, ${savings}% saved)`);
-
- res.json({
- status: 'done',
- downloadUrl: `/video/download/${jobId}${outExt}`,
- outputSize: outStat.size,
- savings,
+ runFFmpeg(args, jobId).then(() => {
+ job.status = 'done';
+ job.progress = 100;
+ const outStat = fs.statSync(outFile);
+ job.outputSize = outStat.size;
+ job.savings = job.size > 0 ? Math.round((1 - outStat.size / job.size) * 100) : 0;
+ job.downloadUrl = `/video/download/${jobId}${outExt}`;
+ log.info(`Video ${mode}: ${job.originalName} → ${format} (${(outStat.size / 1024 / 1024).toFixed(1)}MB, ${job.savings}% saved)`);
+ }).catch(err => {
+ job.status = 'error';
+ job.error = err.message.slice(0, 200);
+ log.error('Video convert error', { error: err.message });
});
} catch (err) {
job.status = 'error';
@@ -206,11 +207,20 @@ router.post('/convert', express.json(), async (req, res) => {
}
});
-// Progress
+// Progress (returns downloadUrl when done)
router.get('/progress/:jobId', (req, res) => {
const job = jobs.get(req.params.jobId);
if (!job) return res.status(404).json({ error: 'Not found' });
- res.json({ status: job.status, progress: job.progress });
+ const result = { status: job.status, progress: job.progress };
+ if (job.status === 'done') {
+ result.downloadUrl = job.downloadUrl;
+ result.outputSize = job.outputSize;
+ result.savings = job.savings;
+ }
+ if (job.status === 'error') {
+ result.error = job.error || 'Ошибка обработки';
+ }
+ res.json(result);
});
// Download result