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