From ca6c303b56cddf39dd6055a22258494d66e451e7 Mon Sep 17 00:00:00 2001 From: Stu Leak Date: Wed, 3 Dec 2025 21:36:30 -0500 Subject: [PATCH] Add encoder preset descriptions with speed/quality trade-offs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit enhances the encoder preset selector with detailed information about speed vs quality trade-offs for each preset option. Preset Information: - Ultrafast: ~10x faster than slow, ~30% larger files - Superfast: ~7x faster than slow, ~20% larger files - Very Fast: ~5x faster than slow, ~15% larger files - Faster: ~3x faster than slow, ~10% larger files - Fast: ~2x faster than slow, ~5% larger files - Medium: Balanced baseline (default) - Slow: ~2x slower than medium, ~5-10% smaller (recommended) - Slower: ~3x slower than medium, ~10-15% smaller - Very Slow: ~5x slower than medium, ~15-20% smaller UI Enhancements: - Dynamic hint label below encoder preset dropdown - Updates automatically when preset changes - Visual icons for different speed categories: - ⚡ Ultrafast/Superfast/Very Fast (prioritize speed) - ⏩ Faster/Fast (good balance) - ⚖️ Medium (baseline) - 🎯 Slow/Slower (recommended for quality) - 🐌 Very Slow (maximum compression) Implementation: - updateEncoderPresetHint() function provides preset details - Called on preset selection change - Initialized with current preset on view load - Positioned directly under preset dropdown for visibility Benefits: - Helps users understand encoding time implications - Shows file size impact of each preset - Recommends "slow" as best quality/size ratio - Prevents confusion about preset differences - Enables informed decisions about encoding settings Technical: - All presets already supported by FFmpeg - No changes to command generation needed - Works with all video codecs (H.264, H.265, VP9, etc.) - Preset names match FFmpeg standards --- DONE.md | 10 ++++++++++ TODO.md | 6 +++--- main.go | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/DONE.md b/DONE.md index cc13c56..e7feff5 100644 --- a/DONE.md +++ b/DONE.md @@ -17,6 +17,16 @@ This file tracks completed features, fixes, and milestones. - Proper handling for videos without black bars - 30-second timeout protection for detection process +- ✅ **Frame Rate Conversion UI with Size Estimates** + - Comprehensive frame rate options: Source, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60 + - Intelligent file size reduction estimates (40-50% for 60→30 fps) + - Real-time hints showing "Converting X → Y fps: ~Z% smaller file" + - Warning for upscaling attempts with judder notice + - Automatic calculation based on source and target frame rates + - Dynamic updates when video or frame rate changes + - Supports both film (24 fps) and broadcast standards (25/29.97/30) + - Uses FFmpeg fps filter for frame rate conversion + - ✅ **Compare Module** - Side-by-side video comparison interface - Load two videos and compare detailed metadata diff --git a/TODO.md b/TODO.md index 80d0c71..35a1d14 100644 --- a/TODO.md +++ b/TODO.md @@ -11,10 +11,10 @@ This file tracks upcoming features, improvements, and known issues. - 15-30% file size reduction with zero quality loss - Add manual crop override option -- [ ] **Frame rate conversion UI** - - Dropdown: Source, 24, 25, 29.97, 30, 50, 59.94, 60 fps +- [x] **Frame rate conversion UI** (v0.1.0-dev13 - COMPLETED) + - Dropdown: Source, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60 fps - Auto-suggest 60→30fps conversion with size estimate - - Show file size impact (40-45% reduction for 60→30) + - Show file size impact (40-50% reduction for 60→30) - [ ] **HEVC/H.265 preset options** - Add preset dropdown: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow diff --git a/main.go b/main.go index ff471c3..a2b7ec5 100644 --- a/main.go +++ b/main.go @@ -1999,12 +1999,44 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject { }) videoCodecSelect.SetSelected(state.convert.VideoCodec) - // Encoder Preset + // Encoder Preset with hint + encoderPresetHint := widget.NewLabel("") + encoderPresetHint.Wrapping = fyne.TextWrapWord + + updateEncoderPresetHint := func(preset string) { + var hint string + switch preset { + case "ultrafast": + hint = "⚡ Ultrafast: Fastest encoding, largest files (~10x faster than slow, ~30% larger files)" + case "superfast": + hint = "⚡ Superfast: Very fast encoding, large files (~7x faster than slow, ~20% larger files)" + case "veryfast": + hint = "⚡ Very Fast: Fast encoding, moderately large files (~5x faster than slow, ~15% larger files)" + case "faster": + hint = "⏩ Faster: Quick encoding, slightly large files (~3x faster than slow, ~10% larger files)" + case "fast": + hint = "⏩ Fast: Good speed, slightly large files (~2x faster than slow, ~5% larger files)" + case "medium": + hint = "⚖️ Medium (default): Balanced speed and quality (baseline for comparison)" + case "slow": + hint = "🎯 Slow (recommended): Best quality/size ratio (~2x slower than medium, ~5-10% smaller)" + case "slower": + hint = "🎯 Slower: Excellent compression (~3x slower than medium, ~10-15% smaller files)" + case "veryslow": + hint = "🐌 Very Slow: Maximum compression (~5x slower than medium, ~15-20% smaller files)" + default: + hint = "" + } + encoderPresetHint.SetText(hint) + } + encoderPresetSelect := widget.NewSelect([]string{"ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow"}, func(value string) { state.convert.EncoderPreset = value logging.Debug(logging.CatUI, "encoder preset set to %s", value) + updateEncoderPresetHint(value) }) encoderPresetSelect.SetSelected(state.convert.EncoderPreset) + updateEncoderPresetHint(state.convert.EncoderPreset) // Bitrate Mode bitrateModeSelect := widget.NewSelect([]string{"CRF", "CBR", "VBR", "Target Size"}, func(value string) { @@ -2198,6 +2230,7 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject { videoCodecSelect, widget.NewLabelWithStyle("Encoder Preset (speed vs quality)", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), encoderPresetSelect, + encoderPresetHint, widget.NewLabelWithStyle("Quality Preset", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), qualitySelect, widget.NewLabelWithStyle("Bitrate Mode", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),