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>
Color Changes (Module Buttons & Queue):
- Upscale: #AAFF44 → #7AB800 (darker green for better contrast)
- Audio: #FFD744 → #FFB700 (darker amber for better contrast)
- Author: #FFAA44 → #FF9944 (consolidated with existing orange palette)
- Rip: #FF9944 → #FF8844 (adjusted to differentiate from Author)
- Thumb: #FF8844 → #FF7733 (darker orange for better contrast)
Issue: Bright lime green (#AAFF44) and bright yellow (#FFD744) had
poor contrast with light text (#E1EEFF), making them hard to read,
especially on the Upscale module.
Solution: Darkened problematic colors while maintaining visual
distinction between modules. New colors meet WCAG contrast guidelines
for better accessibility.
Files Updated:
- main.go: Module color definitions
- internal/ui/queueview.go: Queue job type colors
- internal/ui/components.go: Badge colors for consistency
Reported-by: Stu
Tested-on: Linux
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Queue View Improvements:
- Fix Windows-specific button lag after conversion completion
- Remove redundant refreshQueueView() calls in button handlers
- Queue onChange callback now handles all refreshes automatically
- Add stopQueueAutoRefresh() before navigation to prevent conflicts
- Reduce auto-refresh interval from 500ms to 1000ms
- Result: Instant button response (was 1-3 second lag on Windows)
Main Menu Performance:
- Implement 300ms throttling for main menu rebuilds
- Cache jobQueue.List() to eliminate multiple expensive copies
- Smart conditional refresh: only update when history actually changes
- Add refreshMainMenuThrottled() and refreshMainMenuSidebar()
- Result: 3-5x improvement in responsiveness, especially on Windows
Queue Position Display:
- Fix confusing priority labeling in queue view
- Change from internal priority (3,2,1) to user-friendly positions (1,2,3)
- Display "Queue Position: 1" for first job, "Position: 2" for second, etc.
- Apply to both Pending and Paused jobs
Remux Safety System:
- Add comprehensive codec compatibility validation before remux
- Validate container/codec compatibility (MP4, MKV, WebM, MOV)
- Auto-detect and block incompatible combinations (VP9→MP4, etc.)
- Automatic fallback to re-encoding for WMV/ASF and legacy FLV
- Auto-fix timestamp issues for AVI, MPEG-TS, VOB with genpts
- Add enhanced FFmpeg safety flags for all remux operations:
* -fflags +genpts (regenerate timestamps)
* -avoid_negative_ts make_zero (fix negative timestamps)
* -map 0 (preserve all streams)
* -map_chapters 0 (preserve chapters)
- Add codec name normalization for accurate validation
- Result: Fool-proof remuxing with zero risk of corruption
Technical Changes:
- Add validateRemuxCompatibility() function
- Add normalizeCodecName() function
- Add mainMenuLastRefresh throttling field
- Optimize queue list caching in showMainMenu()
- Windows-optimized rendering pipeline
Reported-by: Jake (Windows button lag)
Reported-by: Stu (main menu lag)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Reset authorTitle when loading new file via file browser
- Reset authorTitle when clearing all clips
- Rebuild author view to refresh title entry UI
- Ensures title field visually resets for fresh content
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit introduces several enhancements to the Author module:
- **Real-time Progress Reporting:** Implemented granular, real-time progress updates for FFmpeg encoding steps during DVD authoring. The progress bar now updates smoothly, reflecting the actual video processing. Progress calculation is weighted by video durations for accuracy.
- **Add to Queue Functionality:** Added an 'Add to Queue' button to the Author module, allowing users to queue authoring jobs for later execution without immediate start. The authoring workflow was refactored to accept a 'startNow' parameter for this purpose.
- **Clear Output Title:** Modified the 'Clear All' functionality to also reset the DVD Output Title, preventing accidental naming conflicts for new projects.
Additionally, this commit includes a UI enhancement:
- **Main Menu Categorization:** Relocated 'Author', 'Rip', and 'Blu-Ray' modules to a new 'Disc' category on the main menu, improving logical grouping.
Fixes:
- Corrected a missing argument error in a call to .
- Added missing import in .
Updates:
- and have been updated to reflect these changes.
- Wrap left and right panels separately in droppables for better drop coverage
- Add extensive debug logging to trace drop events and state changes
- Log when handleDrop and handleSubtitlesModuleDrop are called
- Log file identification (video vs subtitle) and state updates
- Log videoEntry creation with current subtitleVideoPath value
This will help diagnose why video path isn't populating on drop
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Changed handleSubtitlesModuleDrop to call showModule("subtitles")
- Previously only refreshed if already in subtitles view (s.active == "subtitles")
- When dropping from main menu, s.active was "mainmenu", so view never switched
- Now matches behavior of compare and inspect modules
- Video path will now properly populate when dragging from main menu
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove individual droppable wrappers from entry widgets and list area
- Keep only the top-level content droppable wrapper
- Fixes video file path not populating when dragging files
- Nested droppables were interfering with drop event handling
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Wrap entire subtitle module content in droppable container for drag and drop anywhere
- Remove all emojis from build scripts (build-linux.sh, build.sh, build-windows.sh, alias.sh)
- Subtitle module now accepts video/subtitle file drops on any part of the view
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Created AUTHOR_MODULE.md covering all features in detail:
Chapter Detection:
- How scene detection works (FFmpeg filter threshold)
- Sensitivity slider guide (0.1-0.9 range explained)
- Visual preview feature with thumbnails
- Use cases for different video types
- Technical implementation details
DVD Timestamp Correction:
- SCR backwards error explanation
- Automatic remux solution (-fflags +genpts)
- Why it's needed and how it works
- Performance impact (negligible)
Authoring Log Viewer:
- Tail behavior (last 100 lines)
- Performance optimizations explained
- Copy Log and View Full Log buttons
- Memory usage improvements (O(1) vs O(n))
Complete Workflows:
- Single movie to DVD
- TV series multi-title disc
- Concert with manual chapters
Troubleshooting:
- SCR errors
- Too many/few chapters detected
- UI lag issues (now fixed)
- ISO burning problems
- Playback stuttering
Technical Details:
- Full encoding pipeline with commands
- Chapter XML format
- Temporary file locations
- Dependencies and installation
- File size estimates for NTSC/PAL
Also updated DVD_USER_GUIDE.md:
- Removed branding footer
- Added reference to AUTHOR_MODULE.md for technical details
Allows visual verification of detected scene changes before accepting.
Features:
- Extracts thumbnail at each detected chapter timestamp
- Displays first 24 chapters in scrollable grid (4 columns)
- Shows timestamp below each thumbnail (160x90px previews)
- Accept/Reject buttons to confirm or discard detection
- Progress indicator during thumbnail generation
Implementation:
- showChapterPreview() function creates preview dialog
- extractChapterThumbnail() uses FFmpeg to extract frame
- Scales to 320x180, saves as JPEG in temp dir
- Thumbnails generated in background, dialog updated when ready
Performance:
- Limits to 24 chapters for UI responsiveness
- Shows "(showing first 24)" if more detected
- Temp files stored in videotools-chapter-thumbs/
User workflow:
1. Adjust sensitivity slider
2. Click "Detect Scenes"
3. Review thumbnails to verify detection quality
4. Accept to use chapters, or Reject to try different sensitivity
Problem: Author log was causing severe UI lag and memory issues
- Unbounded string growth (entire log kept in RAM)
- Full widget rebuild on every line append
- O(n²) string concatenation performance
Solutions implemented:
1. Tail behavior - Keep only last 100 lines in UI
- Uses circular buffer (authorLogLines slice)
- Prevents unbounded memory growth
- Rebuilds text from buffer on each append
2. Copy Log button
- Copies full log from file (accurate)
- Falls back to in-memory log if file unavailable
3. View Full Log button
- Opens full log in dedicated log viewer
- No UI lag from large logs
4. Track log file path
- authorLogFilePath stored when log created
- Used by copy and view buttons
Performance improvements:
- Memory: O(1) instead of O(n) - fixed 100 line buffer
- CPU: One SetText() per line instead of concatenation
- UI responsiveness: Dramatically improved with tail behavior
UI changes:
- Label shows "Authoring Log (last 100 lines)"
- Copy/View buttons for accessing full log
DVD Authoring Fix:
- Add remultiplex step after MPEG encoding for DVD compliance
- Use ffmpeg -fflags +genpts -c copy -f dvd to fix timestamps
- Resolves "ERR: SCR moves backwards" error from dvdauthor
- FFmpeg direct encoding doesn't always create DVD-compliant streams
- Remux regenerates presentation timestamps correctly
Queue Animation Fix:
- Stop stripe animation on completed jobs
- Bug: Refresh() was always incrementing offset regardless of state
- Now only increments offset when animStop != nil (animation running)
- Completed/failed/cancelled jobs no longer show animated stripes
Testing:
- DVD authoring should now succeed on AVI files
- Completed queue jobs should show static progress bar
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Improvements:
1. Track audio active state with atomic.Bool flag
2. Handle videos without audio track gracefully
- If audio fails to start, video plays at natural frame rate
- Clear error messages indicate "video-only playback"
3. Better A/V sync logging for debugging
- Log when video ahead/behind and actions taken
- Log good sync status periodically (every ~6 seconds at 30fps)
- More granular logging for different sync states
4. Proper cleanup when audio stream ends or fails
How it works:
- audioActive flag set to true when audio starts successfully
- Set to false when audio fails to start or ends
- Video checks audioActive before syncing to audio clock
- If no audio: video just paces at natural frame rate (no sync)
- If audio active: full A/V sync with adaptive timing
Expected improvements:
- Video-only files (GIFs, silent videos) play smoothly
- Better debugging info for sync quality
- Graceful degradation when audio missing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>