Video compress: add output format selector (MP4/AVI/MKV)

- Compress panel now has format buttons before quality
- Backend uses selected format for compress output
- Format sent in API body for compress mode
- User can compress + convert format in one step
This commit is contained in:
treamz 2026-03-22 12:10:01 +03:00
parent dcf5717154
commit 8bec976d3c
2 changed files with 16 additions and 3 deletions

View File

@ -509,6 +509,16 @@
<!-- Mode panel: Сжатие --> <!-- Mode panel: Сжатие -->
<div id="panel-compress" class="mode-panel" style="margin-bottom:24px;"> <div id="panel-compress" class="mode-panel" style="margin-bottom:24px;">
<div class="wa-card" style="margin-bottom:12px;">
<div class="option-group">
<span class="option-label">Выходной формат</span>
<div class="btn-group" id="compressFormats">
<button class="btn-option selected" data-value="mp4">MP4</button>
<button class="btn-option" data-value="avi">AVI</button>
<button class="btn-option" data-value="mkv">MKV</button>
</div>
</div>
</div>
<div class="wa-card"> <div class="wa-card">
<div class="option-group"> <div class="option-group">
<span class="option-label">Качество</span> <span class="option-label">Качество</span>
@ -900,6 +910,7 @@
initBtnGroup('convertFormats', val => { state.format = val; }); initBtnGroup('convertFormats', val => { state.format = val; });
initBtnGroup('audioFormats', val => { state.audioFormat = val; }); initBtnGroup('audioFormats', val => { state.audioFormat = val; });
initBtnGroup('compressFormats', val => { state.compressFormat = val; });
// ─── Quality options ─────────────────────────────────────────────────────── // ─── Quality options ───────────────────────────────────────────────────────
document.querySelectorAll('.quality-option').forEach(label => { document.querySelectorAll('.quality-option').forEach(label => {
@ -926,7 +937,8 @@
const body = { const body = {
jobId: state.jobId, jobId: state.jobId,
mode: state.mode, mode: state.mode,
format: state.mode === 'convert' ? state.format format: state.mode === 'compress' ? (state.compressFormat || 'mp4')
: state.mode === 'convert' ? state.format
: state.mode === 'audio' ? state.audioFormat : state.mode === 'audio' ? state.audioFormat
: state.mode === 'gif' ? 'gif' : state.mode === 'gif' ? 'gif'
: 'mp4', : 'mp4',

View File

@ -169,9 +169,10 @@ router.post('/convert', express.json(), async (req, res) => {
break; break;
} }
case 'compress': { case 'compress': {
// Quality via mpeg4 q:v (1=best, 31=worst) // Quality via mpeg4 q:v (1=best, 31=worst) + format selection
const qv = quality === 'high' ? '3' : quality === 'low' ? '15' : '8'; const qv = quality === 'high' ? '3' : quality === 'low' ? '15' : '8';
args.push('-c:v', 'mpeg4', '-q:v', qv, '-c:a', 'aac', '-b:a', '128k', '-movflags', '+faststart'); args.push('-c:v', 'mpeg4', '-q:v', qv, '-c:a', 'aac', '-b:a', '128k');
if (format === 'mp4' || !format) args.push('-movflags', '+faststart');
break; break;
} }
case 'audio': { case 'audio': {