add compression slider

This commit is contained in:
2026-02-09 21:08:44 -05:00
parent cc11b35160
commit fcc777ae7c
2 changed files with 64 additions and 3 deletions

7
app.py
View File

@@ -157,11 +157,16 @@ def process_video():
if mute_audio: if mute_audio:
cmd.extend(['-an']) # Remove audio cmd.extend(['-an']) # Remove audio
# Get quality (CRF value)
quality = data.get('quality', 23)
# Ensure quality is within valid range (18-32)
quality = max(18, min(32, int(quality)))
# Output settings for H.264 MP4 # Output settings for H.264 MP4
cmd.extend([ cmd.extend([
'-c:v', 'libx264', '-c:v', 'libx264',
'-preset', 'medium', '-preset', 'medium',
'-crf', '23', '-crf', str(quality),
'-c:a', 'aac', '-c:a', 'aac',
'-b:a', '128k', '-b:a', '128k',
'-movflags', '+faststart', '-movflags', '+faststart',

View File

@@ -588,6 +588,28 @@
</div> </div>
</div> </div>
<!-- Compression Quality Controls -->
<div class="form-group">
<label>💾 Compression Quality</label>
<div class="scale-slider-container">
<div class="scale-display">
<span>Quality: <span class="scale-value" id="quality-value-display">High</span></span>
<span style="color: #6c757d;">CRF: <strong id="crf-value-display">23</strong></span>
</div>
<input type="range" class="scale-slider" id="quality-slider" min="18" max="32" value="23" step="1">
<div class="resolution-preview">
<p style="margin: 0;">💡 <strong>Lower CRF</strong> = Better quality, larger file. <strong>Higher CRF</strong> = More compressed, smaller file.</p>
</div>
<div class="preset-resolutions" style="margin-top: 15px;">
<button class="preset-btn" data-quality="18">Best Quality</button>
<button class="preset-btn" data-quality="21">High</button>
<button class="preset-btn" data-quality="23">Balanced</button>
<button class="preset-btn" data-quality="26">Low</button>
<button class="preset-btn" data-quality="30">Smallest File</button>
</div>
</div>
</div>
<!-- Quick Actions --> <!-- Quick Actions -->
<div class="form-group"> <div class="form-group">
<label>⚡ Quick Actions</label> <label>⚡ Quick Actions</label>
@@ -632,6 +654,7 @@
let scalePercentage = 100; let scalePercentage = 100;
let rotationDegrees = 0; let rotationDegrees = 0;
let muteAudio = false; let muteAudio = false;
let compressionQuality = 23;
// Upload area handling // Upload area handling
const uploadArea = document.getElementById('upload-area'); const uploadArea = document.getElementById('upload-area');
@@ -935,6 +958,9 @@
const scaleSlider = document.getElementById('scale-slider'); const scaleSlider = document.getElementById('scale-slider');
const scaleValueDisplay = document.getElementById('scale-value-display'); const scaleValueDisplay = document.getElementById('scale-value-display');
const outputResolution = document.getElementById('output-resolution'); const outputResolution = document.getElementById('output-resolution');
const qualitySlider = document.getElementById('quality-slider');
const qualityValueDisplay = document.getElementById('quality-value-display');
const crfValueDisplay = document.getElementById('crf-value-display');
function updateScaleDisplay() { function updateScaleDisplay() {
scalePercentage = parseInt(scaleSlider.value); scalePercentage = parseInt(scaleSlider.value);
@@ -953,14 +979,40 @@
scaleSlider.addEventListener('input', updateScaleDisplay); scaleSlider.addEventListener('input', updateScaleDisplay);
// Quality slider
function updateQualityDisplay() {
compressionQuality = parseInt(qualitySlider.value);
crfValueDisplay.textContent = compressionQuality;
// Update quality label
let qualityLabel = 'Balanced';
if (compressionQuality <= 19) qualityLabel = 'Best Quality';
else if (compressionQuality <= 22) qualityLabel = 'High';
else if (compressionQuality <= 25) qualityLabel = 'Balanced';
else if (compressionQuality <= 28) qualityLabel = 'Low';
else qualityLabel = 'Smallest File';
qualityValueDisplay.textContent = qualityLabel;
}
qualitySlider.addEventListener('input', updateQualityDisplay);
updateQualityDisplay();
// Scale presets // Scale presets
document.querySelectorAll('.preset-btn').forEach(btn => { document.querySelectorAll('.preset-btn').forEach(btn => {
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
const scale = btn.dataset.scale; const scale = btn.dataset.scale;
const quality = btn.dataset.quality;
if (scale) { if (scale) {
scaleSlider.value = scale; scaleSlider.value = scale;
updateScaleDisplay(); updateScaleDisplay();
} }
if (quality) {
qualitySlider.value = quality;
updateQualityDisplay();
}
}); });
}); });
@@ -984,7 +1036,8 @@
end_time: endTime, end_time: endTime,
scale_percentage: scalePercentage, scale_percentage: scalePercentage,
rotation: rotationDegrees, rotation: rotationDegrees,
mute_audio: muteAudio mute_audio: muteAudio,
quality: compressionQuality
}; };
if (cropWidth > 0 && cropHeight > 0) { if (cropWidth > 0 && cropHeight > 0) {
@@ -1048,8 +1101,9 @@
rotationDegrees = 0; rotationDegrees = 0;
muteAudio = false; muteAudio = false;
scalePercentage = 100; scalePercentage = 100;
compressionQuality = 23;
videoPreview.src = ''; videoPreview.src = '';;
videoInput.value = ''; videoInput.value = '';
clearCropCanvas(); clearCropCanvas();
cropCanvas.classList.remove('active'); cropCanvas.classList.remove('active');
@@ -1065,6 +1119,8 @@
document.getElementById('scale-value-display').textContent = '100%'; document.getElementById('scale-value-display').textContent = '100%';
document.getElementById('output-resolution').textContent = '--'; document.getElementById('output-resolution').textContent = '--';
document.getElementById('current-time-display').textContent = '0:00'; document.getElementById('current-time-display').textContent = '0:00';
document.getElementById('quality-slider').value = '23';
updateQualityDisplay();
// Reset quick actions // Reset quick actions
document.getElementById('mute-audio-btn').classList.remove('active'); document.getElementById('mute-audio-btn').classList.remove('active');