Replaced all emojis with text-based indicators:
- ✓ → [OK] (with GREEN color)
- ✗ → [ERROR] (with RED color)
- ⚠ → WARNING: (with YELLOW color)
Color coding is preserved for visual distinction while remaining
accessible in all terminals and avoiding encoding issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added support for installing Real-ESRGAN NCNN during setup:
**New Features:**
- Prompts user to install AI upscaling tools (Real-ESRGAN NCNN)
- Downloads and installs binary from GitHub releases
- Tries /usr/local/bin with sudo, falls back to ~/.local/bin
- Supports x86_64 architecture, warns for ARM
- Added --skip-ai flag to skip AI tools prompt
**Installation Flow:**
1. Ask: "Install DVD authoring tools?" (dvdauthor + xorriso)
2. Ask: "Install AI upscaling tools?" (Real-ESRGAN NCNN)
3. Auto-install all missing dependencies user requested
**Benefits:**
- Users get AI upscaling without manual download
- FFmpeg native upscaling still works without it
- Optional enhancement, not required
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previously, install.sh would:
1. Ask "Install DVD authoring tools?"
2. Then ask again "Install missing dependencies now?"
Now it automatically installs any missing dependencies after the
user confirms they want DVD tools, eliminating the redundant prompt.
Changes:
- Removed second confirmation prompt for dependency installation
- Automatically installs missing deps when detected
- Shows clear message: "Missing dependencies: ... Installing..."
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The dependency check was accepting any ISO tool (mkisofs, genisoimage,
or xorriso), but the install commands now specifically install xorriso.
Updated checks to require xorriso specifically since:
- It handles both ISO9660 and UDF formats
- Required for RIP module to extract UDF DVD ISOs
- Now installed by all package managers in the script
This ensures the install script will detect and install xorriso even
if older tools like genisoimage are already present.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
**Metadata Panel Fix:**
- Simplified makeRow layout to properly display values
- Changed from complex Border layout to simple HBox
- Metadata values now visible in Convert module
**RIP Module Improvements:**
- Added mount-based ISO extraction for UDF ISOs
- Added 7z extraction fallback
- Prioritizes xorriso > 7z > bsdtar for ISO extraction
- Handles both ISO9660 and UDF format DVDs
**Installation Script:**
- Updated all package managers to install xorriso
- Ensures proper UDF ISO support when disc modules enabled
- apt/dnf/zypper now install xorriso instead of genisoimage
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When authoring DVDs from multiple videos, chapters now display:
- Video metadata title if available
- Filename without extension as fallback
- Instead of generic "Chapter 1", "Chapter 2", etc.
This provides better navigation experience in DVD players.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Output hint now updates immediately when checking/unchecking suffix checkbox
- User can see "video.mp4" vs "video-convert.mp4" change live
- Improves UX by providing instant visual feedback
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Removed reference to HANDBRAKE_REPLACEMENT.md from docs/README.md
- Removed HandBrake references from docs/CHANGELOG.md
- Keep documentation focused on VideoTools features
- File was already deleted, this cleans up the references
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Critical fix for dvdauthor "Skipping sector at inoffset 0" errors:
- Add -f dvd format to initial MPEG encoding
- Add -muxrate 10080000 (10.08 Mbps DVD standard mux rate)
- Add -packetsize 2048 (DVD packet size requirement)
- Apply same parameters to remux and concat steps
- Ensures proper VOBU (Video Object Unit) boundaries
- Creates DVD-compliant MPEG-PS streams from encoding
This fixes the "dvdauthor structure creation failed" error when
authoring multi-scene DVDs. The MPEG files now have proper DVD
navigation structure that dvdauthor can process.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added AppendSuffix bool field to convertConfig (default: false)
- By default, output filename matches source filename exactly
- Added checkbox "Append \"-convert\" to filename" (unchecked by default)
- Checkbox appears in both Simple and Advanced modes
- Eliminates noise when doing batch conversions
- Auto-naming still works and respects the suffix setting
Before: video.mp4 → video-convert.mp4 (always)
After: video.mp4 → video.mp4 (or video-convert.mp4 if checked)
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Major improvements to DVD authoring for professional results:
- Always concatenate multiple videos into single title (not multiple titles)
- Automatically generate chapter markers from video clips
- Chapter markers created at each scene boundary regardless of checkbox
- One title with navigable chapters instead of separate titles
- Better logging showing chapter structure and timestamps
Before: 4 videos → 4 separate titles with no chapters
After: 4 videos → 1 title with 4 chapter markers
This creates a professional DVD that matches commercial disc structure
with proper chapter navigation.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Blue color now used as default selection/background
- Mid-grey now used as hover color
- Applied through MonoTheme Color() method override
- Affects all dropdowns, lists, and selectable UI elements
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Log all generated MPG files with sizes before dvdauthor
- Log complete DVD XML content for debugging
- Add specific error messages at each dvdauthor step
- Verify and log ISO file creation success
- Better error context for diagnosing 80% failure point
This will help diagnose the exit code 1 error when authoring
4-scene discs to ISO format.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replaced single-column Form widget with two-column grid layout
- Created makeRow helper for compact key-value pairs
- Left column: File, Format, Resolution, Aspect, Duration, FPS, etc.
- Right column: Codecs, Bitrates, Pixel Format, Channels, etc.
- More efficient use of space, matches modern UI design
- Text truncation prevents overflow
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Removed benchmark status display and apply button from top bar
- Cleaner UI matching mockup design
- Benchmark functionality still accessible via Settings menu
- Reduces visual clutter in Convert module
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Check if user has "slow" or "slower" preset before applying benchmark
- Upgrade benchmark preset to "slow" if user prefers quality
- Prevents benchmark from forcing fast presets on quality-focused users
- Logs quality preference detection for debugging
Fixes issue where benchmark kept switching to fast encoding despite
user preference for higher quality output.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Changed text wrapping from TextWrapWord to TextTruncate on desc/status labels
- Set fixed minimum height (140px) for job item cards
- Prevents height fluctuations when status text changes
- Resolves janky jumping behavior in job queue
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added ColorRemux (#06B6D4 cyan-glow) to semantic color system
- Remux formats now display with distinct color from regular MKV
- buildFormatBadge checks for "Remux" in label and applies special color
- Differentiates lossless remux from transcoded formats
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Changed badge layout from vertical stacking to horizontal inline display
- Badges now appear next to dropdowns using HBox containers
- Applied to format, video codec, and audio codec selections
- Added assets/mockup/ to .gitignore for design references
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Implemented buildVideoCodecBadge() and buildAudioCodecBadge() functions
- Added badge containers for format, video codec, and audio codec selections
- Badges use semantic color system from ui/colors.go
- Video codecs: AV1 (emerald), H.265 (lime), H.264 (sky blue), etc.
- Audio codecs: Opus (violet), AAC (purple), FLAC (magenta), etc.
- Format badges: MKV (teal), MP4 (blue), MOV (indigo), etc.
- Badges update dynamically when selection changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented semantic color-coded badges for format selection:
- Badge displays next to format dropdown showing container name
- Uses semantic color system (MKV=teal, MP4=blue, MOV=indigo, etc.)
- Updates dynamically when format selection changes
- Appears in both Simple and Advanced modes
Changes:
- Created buildFormatBadge() function to generate colored badges
- Added formatBadgeContainer with updateFormatBadge() callback
- Integrated badge into both Simple and Advanced mode layouts
- Badge provides visual recognition of container type at a glance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
User feedback: Benchmark indicator should disappear entirely once applied,
not just show "Applied" status.
Changes:
- Modified Apply Benchmark button callback to hide the entire indicator
- Removed code that changed text/color and disabled button
- Cleaner UI - indicator completely disappears after applying settings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When benchmark settings are already applied, benchmarkIndicator is nil but was
being added to the container unconditionally, causing a crash during UI layout.
Changes:
- Conditionally build back bar items array
- Only append benchmarkIndicator if it's not nil
- Prevents SIGSEGV when opening Convert module with applied benchmark
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added documentation for hiding benchmark indicator when settings are already applied.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
User feedback: Don't show benchmark status clutter when settings are already applied.
Changes:
- Only show benchmark indicator when settings are NOT applied
- Removes 'Benchmark: Applied' text + button from UI when active
- Cleaner Convert module interface when using benchmark settings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Documented that player is already fully internal (FFmpeg-based).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Investigation revealed:
- Player module is ALREADY fully internal and lightweight
- Uses FFmpeg directly to decode video frames and audio
- Uses Oto library (lightweight Go audio library) for audio output
- No external VLC/MPV/FFplay dependencies
Implementation:
- FFmpeg pipes raw video frames (rgb24) directly to UI
- FFmpeg pipes audio (s16le) to Oto for playback
- Frame-accurate seeking and A/V sync built-in
- Error handling: Falls back to video-only if audio fails
Previous crash was likely from:
- Oto audio initialization failing on your system
- OR unrelated issue (OOM, etc.)
- Code already handles audio failures gracefully
Player module is safe to re-enable - it follows VideoTools' core principles.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Documented disabling of Player module to prevent crashes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Issue:
- Player module was crashing when accessed
- Uses external tools (MPV, VLC, FFplay) which violates VideoTools' core principle
- Everything should be internal and lightweight, no external dependencies
Fix:
- Disabled Player module in main menu
- Module still exists in code but is not accessible to users
- Prevents crash by preventing access to broken functionality
Future work needed:
- Implement pure-Go internal player using FFmpeg libraries
- OR implement simple preview-only playback using existing preview system
- Must be self-contained and lightweight
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added documentation for benchmark result persistence and caching system.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes:
- Check for existing benchmark results when opening benchmark module
- If recent results exist for same hardware, show cached results instead of auto-running
- Display timestamp of cached results (e.g., "Showing cached results from December 28, 2025 at 2:45 PM")
- Add "Run New Benchmark" button at bottom of cached results view
- Only auto-run benchmark if no previous results exist or hardware has changed
Benefits:
- No more redundant benchmarks every time you open the module
- Results persist across app restarts (saved to ~/.config/VideoTools/benchmark.json)
- Clear indication when viewing cached vs fresh results
- Easy option to re-run if desired
Hardware detection:
- Compares GPU model to detect hardware changes
- If GPU changes, automatically runs new benchmark
- Keeps last 10 benchmark runs in history
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added documentation for:
- Merge module output path UX improvement (folder + filename split)
- Queue priority system for Convert Now
- Auto-cleanup for failed conversions
- Queue list jankiness reduction
All features completed in dev20+ release cycle (2025-12-28)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Queue Priority Changes:
- Added AddNext() method to queue package that inserts jobs after running jobs
- "Convert Now" now adds to top of queue when conversions are already running
- "Add to Queue" continues to add to end of queue
- User feedback message indicates when job was added to top vs started fresh
Auto-Cleanup for Failed Files:
- Convert jobs now automatically delete incomplete/broken output files on failure
- Prevents accumulation of partial files from failed conversions
- Success tracking ensures complete files are never removed
Benefits:
- Better workflow when adding files during active conversions
- "Convert Now" truly prioritizes the current file
- No more broken partial files cluttering output directories
- Cleaner error handling and disk space management
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed the merge output path from a single long entry field to two
separate fields for better usability:
UI Changes:
- Output Folder: Entry with "Browse Folder" button for directory selection
- Output Filename: Entry for just the filename (e.g., "merged.mkv")
- Users can now easily change the filename without navigating through
the entire path
Internal Changes:
- Split `mergeOutput` into `mergeOutputDir` and `mergeOutputFilename`
- Updated all merge logic to combine dir + filename when needed
- Extension correction now works on filename only
- Clear button resets both fields independently
- Auto-population sets dir and filename separately
Benefits:
- Much simpler to change output filename
- No need to scroll to end of long path
- Cleaner, more intuitive interface
- Follows common file dialog patterns
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented two key optimizations to smooth queue list updates:
1. Increased auto-refresh interval from 1000ms to 2000ms
- Reduces frequency of view rebuilds
- Gives UI more time to stabilize between updates
2. Reduced scroll restoration delay from 50ms to 10ms
- Minimizes visible jump during position restoration
- Saves offset to variable before goroutine to avoid race conditions
These changes work together to provide a smoother queue viewing
experience by reducing rebuild frequency while accelerating scroll
position recovery.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Issue:
- User reported batch settings text being cut off
- "Settings persist across videos. Change them anytime to affect all sub"
- Text truncated instead of wrapping to next line
- Cache directory hint also had truncation issues
Root Cause:
- settingsInfoLabel didn't have TextWrapWord enabled
- cacheDirHint had TextWrapWord but wasn't in a sized container
- Labels in VBox need padded containers for wrapping to work properly
Solution:
- Enabled TextWrapWord on settingsInfoLabel
- Wrapped both labels in container.NewPadded() containers:
* settingsInfoContainer: "Settings persist across videos..." text
* cacheDirHintContainer: "Use an SSD for best performance..." text
- Replaced direct label usage with containers in settingsContent VBox
Affected Labels:
- settingsInfoLabel: Batch settings persistence explanation
- cacheDirHint: Cache/temp directory usage guidance
Implementation:
- Added TextWrapWord to settingsInfoLabel
- Created padded containers for both labels
- Updated settingsContent VBox to use containers instead of labels
- Consistent with fix from commit 1051329
Impact:
- Batch settings text now wraps properly
- "Change them anytime to affect all subsequent videos" fully visible
- Better readability in narrow windows
- No more truncated guidance text
Files Changed:
- main.go: Batch settings label wrapping
Reported-by: User (screenshot showing batch settings truncation)
Related: Commit 1051329 (hint label wrapping fix)
Tested: Build successful (v0.1.0-dev20)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Issue:
- User reported hint text being cut off at window edge
- Example: "CBR mode: Constant bitrate - predictable file quality. Use for strict size requirements or s"
- Text truncated with "or s" visible, rest cut off
- Hint labels weren't wrapping properly in narrow windows
Root Cause:
- Hint labels had TextWrapWord enabled BUT
- Labels inside VBox containers don't wrap properly without width constraints
- Fyne requires labels to be in a sized container for wrapping to work
- VScroll container doesn't provide width hints to child labels
Solution:
- Wrap all hint labels in container.NewPadded() containers
- Padded containers provide proper sizing context for text wrapping
- Labels now wrap at available width instead of extending beyond bounds
Affected Hint Labels:
- encoderPresetHint: Encoder preset descriptions
- encodingHint: Bitrate mode (CRF/CBR/VBR/Target Size) hints
- frameRateHint: Frame rate change warnings
- outputHint: Output file path display
- targetAspectHint: Aspect ratio selection hint
- hwAccelHint: Hardware acceleration guidance
Implementation:
- Created *Container versions of each hint label
- Wrapped label in container.NewPadded(label)
- Replaced direct label usage with container in VBox layouts
- Maintains TextWrapWord setting on all labels
Impact:
- Hint text now wraps properly in narrow windows/panels
- No more truncated text
- Better readability across all window sizes
- Consistent behavior for all hint labels
Files Changed:
- main.go: Wrapped 6 hint labels in padded containers
Reported-by: User (screenshot showing "or s" truncation)
Tested: Build successful (v0.1.0-dev20)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Issue:
- Jake reported command prompts popping up during benchmark runs on Windows
- FFmpeg processes were showing console windows during tests
- Disruptive user experience, not discreet
Root Cause:
- exec.CommandContext on Windows shows command prompt by default
- Benchmark suite runs multiple FFmpeg processes (test video generation + encoder tests)
- No platform-specific window hiding applied
Solution:
- Apply utils.ApplyNoWindow() to all FFmpeg benchmark commands
- Uses SysProcAttr{HideWindow: true} on Windows
- No-op on Linux/macOS (cross-platform safe)
Implementation:
- Import internal/utils in benchmark package
- Call ApplyNoWindow() on test video generation command
- Call ApplyNoWindow() on each encoder benchmark test command
- Ensures all benchmark processes run hidden on Windows
Files Changed:
- internal/benchmark/benchmark.go: Added ApplyNoWindow() calls
Platform-Specific Code:
- internal/utils/proc_windows.go: HideWindow implementation (existing)
- internal/utils/proc_other.go: No-op implementation (existing)
Impact:
- Clean, discreet benchmarking on Windows
- No console windows popping up during tests
- Same behavior on all platforms
Reported-by: Jake (Windows command prompt popups)
Tested-on: Linux (build successful, no-op behavior verified)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Critical Fix:
- Goroutine dump showed hundreds of leaked animation goroutines
- Each queue refresh created NEW progress bars without stopping old ones
- Animation goroutines continued running forever, consuming resources
Root Cause:
- BuildQueueView() creates new StripedProgress widgets on every refresh
- StartAnimation() spawned goroutines for running jobs
- Old widgets were discarded but goroutines never stopped
- Fyne's Destroy() method not reliably called when rebuilding view
Solution:
- Track all active StripedProgress widgets in appState.queueActiveProgress
- Stop ALL animations before rebuilding queue view
- Stop ALL animations when leaving queue view (stopQueueAutoRefresh)
- BuildQueueView now returns list of active progress bars
- Prevents hundreds of leaked goroutines from accumulating
Implementation:
- Added queueActiveProgress []*ui.StripedProgress to appState
- Modified BuildQueueView signature to return progress list
- Stop old animations in refreshQueueView() before calling BuildQueueView
- Stop all animations in stopQueueAutoRefresh() when navigating away
- Track running job progress bars and append to activeProgress slice
Files Changed:
- main.go: appState field, refreshQueueView(), stopQueueAutoRefresh()
- internal/ui/queueview.go: BuildQueueView(), buildJobItem()
Impact:
- Eliminates goroutine leak that caused resource exhaustion
- Clean shutdown of animation goroutines on refresh and navigation
- Should dramatically reduce memory usage and CPU overhead
Reported-by: User (goroutine dump showing 900+ leaked goroutines)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed Issue:
- "Hide Batch Settings" button text was overflowing beyond button boundary
- Text was truncated and hard to read in narrow layouts
Solution:
- Created wrapped label overlay on button using container.NewStack
- Label has TextWrapWord enabled for automatic line breaking
- Maintains button click functionality while improving readability
- Text now wraps to multiple lines when space is constrained
Files Changed:
- main.go: Batch settings toggle button (lines 6858-6879)
Reported-by: User (screenshot showing text overflow)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>