In Progress Tab Enhancements:
- Added animated striped progress bars to in-progress jobs
- Exported ModuleColor function for reuse across modules
- Shows real-time progress (0-100%) with module-specific colors
- Progress updates automatically as jobs run
- Maintains consistent visual style with queue view
Lossless Quality Preset Improvements:
- H.265 and AV1 now support all bitrate modes with lossless quality
- Lossless with Target Size mode now works for H.265/AV1
- H.264 and MPEG-2 no longer show "Lossless" option (codec limitation)
- Dynamic quality dropdown updates based on selected codec
- Automatic fallback to "Near-Lossless" when switching from lossless-capable
codec to non-lossless codec
Quality Options Logic:
- Base options: Draft, Standard, Balanced, High, Near-Lossless
- "Lossless" only appears for H.265 and AV1
- codecSupportsLossless() helper function checks compatibility
- updateQualityOptions() refreshes dropdown when codec changes
Lossless + Bitrate Mode Combinations:
- Lossless + CRF: Forces CRF 0 for perfect quality
- Lossless + CBR: Constant bitrate with lossless quality
- Lossless + VBR: Variable bitrate with lossless quality
- Lossless + Target Size: Calculates bitrate for exact file size with
best possible quality (now allowed for H.265/AV1)
Technical Implementation:
- Added Progress field to ui.HistoryEntry struct
- Exported StripedProgress widget and ModuleColor function
- updateQualityOptions() function dynamically filters quality presets
- updateEncodingControls() handles lossless modes per codec
- Descriptive hints explain each lossless+bitrate combination
This allows professional workflows where lossless quality is desired
but file size constraints still need to be met using Target Size mode.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Features:
- New "In Progress" tab shows running/pending jobs
- Displays active jobs without opening full queue
- Tab positioned first for quick visibility
- Shows "Running..." or "Pending" status
- No delete button on active jobs (only completed/failed)
Implementation:
- Updated BuildHistorySidebar to accept activeJobs parameter
- Converts queue.Job to ui.HistoryEntry for display
- Filters running/pending jobs from queue
- Conditional delete button (nil check)
- Dynamic status text based on job state
UX Improvements:
- Quick glance at current activity without queue view
- Three-tab layout: In Progress → Completed → Failed
- Consistent styling with existing history entries
- Tappable entries to view full job details
This allows users to monitor active conversions directly
from the history sidebar, reducing the need to constantly
check the full job queue view.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Bitrate Mode Options Now Show:
- CRF (Constant Rate Factor)
- CBR (Constant Bitrate)
- VBR (Variable Bitrate)
- Target Size (Calculate from file size)
Implementation:
- Added bidirectional mapping between short codes and full labels
- Internally still uses short codes (CRF, CBR, VBR, Target Size)
- Preserves compatibility with existing config files
- Maps display label to internal code on selection
- Maps internal code to display label when loading
Makes it immediately clear what each bitrate mode does without
needing to reference documentation or tooltips.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Command Preview Button:
- Disabled when no video source is loaded
- Shows "Show Preview" when preview is hidden
- Shows "Hide Preview" when preview is visible
- Makes it clear when and why the button can be used
Format Options Reorganization:
- Grouped formats by codec family for better readability
- Order: H.264 → H.265 → AV1 → VP9 → ProRes → MPEG-2
- Added comments explaining each codec family
- Makes it easier to find and compare similar codecs
This improves discoverability and reduces user confusion about
when the command preview is available and which format to choose.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Features:
- Add "×" delete button to each history entry in sidebar
- Click to remove individual entries from history
- Automatically saves and refreshes sidebar after deletion
Bug Fixes:
- Fix nil pointer crash when opening Convert module
- Fixed widget initialization order: bitrateContainer now created
AFTER bitratePresetSelect is initialized
- Prevented "invalid memory address" panic in tabs layout
Technical Details:
- Added deleteHistoryEntry() method to remove entries by ID
- Updated BuildHistorySidebar signature to accept onEntryDelete callback
- Moved bitrateContainer creation from line 5742 to 5794
- All Select widgets now properly initialized before container creation
The crash was caused by bitrateContainer containing a nil
bitratePresetSelect widget, which crashed when Fyne's layout system
called .Visible() during tab initialization.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix panic when closing log viewer (duplicate channel close)
- Improve CBR: Set bufsize to 2x bitrate for better encoder handling
- Improve VBR: Increase maxrate cap from 1.5x to 2x target bitrate
- Add bufsize to VBR at 4x target (2x maxrate) to enforce caps
- Update VBR hint to reflect 2x peak cap and 2-pass encoding
This eliminates runaway bitrates while maintaining quality peaks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Restructured bitrate controls to hide unused options based on mode,
and improved VBR encoding to use 2-pass for accurate bitrate targeting.
UI Improvements:
- Wrapped CRF, bitrate, and target size controls in hideable containers
- Only show relevant controls based on selected bitrate mode:
* CRF mode: Show only CRF entry
* CBR mode: Show only bitrate entry and presets
* VBR mode: Show only bitrate entry and presets
* Target Size mode: Show only target size controls
- Added descriptive hints for each mode explaining behavior
- Updated DVD mode to work with new container structure
- Made command preview update when bitrate settings change
Encoding Improvements:
- VBR now uses maxrate at 1.5x target for quality peaks
- VBR automatically enables 2-pass encoding for accuracy
- CBR remains strict (minrate=maxrate=target) for guaranteed bitrate
- Target Size mode continues to calculate exact bitrate from duration
This addresses runaway bitrate issues by:
1. Making it clear which mode is active
2. Hiding confusing unused controls
3. Ensuring VBR hits target average bitrate with 2-pass
4. Keeping CBR strict for exact constant bitrate
Pros of manual bitrate targeting:
- Predictable file sizes
- Meets strict size requirements
- Good for streaming with bandwidth constraints
Cons of manual bitrate targeting:
- Variable quality (simple scenes waste bits, complex scenes starve)
- Less efficient than CRF overall
- Requires 2-pass for VBR accuracy (slower)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added support for modern video codecs and containers, and made the
FFmpeg command preview update in real-time as settings change.
Format additions:
- MP4 (AV1) - AV1 codec in MP4 container
- MKV (AV1) - AV1 codec in Matroska container
- WebM (VP9) - VP9 codec for web video
- WebM (AV1) - AV1 codec for web video
- MOV (H.264) - H.264 in QuickTime for Apple compatibility
- MOV (H.265) - H.265 in QuickTime for Apple compatibility
Command preview improvements:
- Added forward declaration for buildCommandPreview function
- Command preview now updates live when changing:
* Format selection
* Video codec
* Quality presets (Simple and Advanced)
* Encoder speed presets
- Preview stays synchronized with current settings
- Users can now see exactly what command will be generated
This gives professionals comprehensive format options while keeping
the preview accurate and up-to-date.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Made the FFmpeg command preview less intrusive by adding a toggle button
and showing actual file paths instead of placeholders.
Changes:
- Added convertCommandPreviewShow state field to track preview visibility
- Added "Command Preview" toggle button next to "View Queue" button
- Command preview now hidden by default to save screen space
- Preview shows actual input/output file paths instead of INPUT/OUTPUT
- Cover art paths also shown with real file path when present
This makes the interface cleaner while providing more useful information
when the preview is needed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Integrated history sidebar into main menu with toggle button and split
view layout. Added history details dialog with FFmpeg command copy.
Changes:
- internal/ui/mainmenu.go:
* Updated BuildMainMenu() signature to accept sidebar parameters
* Added "☰ History" toggle button to header
* Implemented HSplit layout (20% sidebar, 80% main) when sidebar visible
- main.go:
* Added "sort" import for showHistoryDetails
* Added showHistoryDetails() method to display job details dialog
* Shows timestamps, config, error messages, FFmpeg command
* "Show in Folder" button (only if output file exists)
* "View Log" button (only if log file exists)
* Updated showMainMenu() to build and pass sidebar
* Implemented sidebar toggle that refreshes main menu
The sidebar can be toggled on/off from the main menu, shows history
entries with filtering by status (Completed vs Failed/Cancelled), and
clicking an entry opens a detailed view with all job information and
the ability to copy the FFmpeg command for manual execution.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added history sidebar UI with tabs for completed and failed jobs.
Created reusable UI components and helpers for displaying history entries.
Changes:
- internal/ui/mainmenu.go:
* Added HistoryEntry type definition
* Added BuildHistorySidebar() for main sidebar UI with tabs
* Added buildHistoryList() and buildHistoryItem() helpers
* Added imports for queue and utils packages
- internal/ui/components.go:
* Moved GetStatusColor() and BuildModuleBadge() here as shared functions
* Added queue and utils imports for shared helpers
- internal/ui/queueview.go:
* Updated to use shared GetStatusColor() and BuildModuleBadge()
* Removed duplicate function definitions
- main.go:
* Updated to use ui.HistoryEntry type throughout
* Updated historyConfig, appState, and all methods to use ui.HistoryEntry
The sidebar displays history entries with:
- Status-colored indicators (green/red/orange)
- Module type badges with colors
- Shortened titles and formatted timestamps
- Separate tabs for "Completed" and "Failed" (includes cancelled)
- Empty state messages when no entries exist
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added conversion history tracking with persistence to disk. Jobs are
automatically added to history when they complete, fail, or are cancelled.
Changes:
- Added HistoryEntry struct to represent completed jobs
- Added historyConfig for JSON persistence
- Added historyConfigPath(), loadHistoryConfig(), saveHistoryConfig() functions
- Added historyEntries and sidebarVisible fields to appState
- Added addToHistory() method to save completed jobs
- Initialize history loading on app startup
- Hook into queue change callback to automatically save finished jobs
- Store FFmpeg command in history for each job
- Limit history to 20 most recent entries
History is saved to ~/.config/VideoTools/history.json and includes job
details, timestamps, error messages, and the FFmpeg command for manual
reproduction.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added "Copy Command" button to queue view for running and pending jobs,
allowing users to copy the FFmpeg command to clipboard for manual execution.
Changes:
- internal/ui/queueview.go: Add onCopyCommand parameter and buttons
- main.go: Implement onCopyCommand handler in showQueue()
The handler retrieves the job, generates the FFmpeg command with
INPUT/OUTPUT placeholders using buildFFmpegCommandFromJob(), and copies
it to the clipboard with a confirmation dialog.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Integrated the FFmpegCommandWidget into the Convert module:
1. Added command preview section in buildConvertView():
- Creates FFmpegCommandWidget displaying current settings as FFmpeg command
- Uses INPUT/OUTPUT placeholders for portability
- Positioned above action bar, after snippet section
- Only shows when video is loaded
2. Command building logic:
- Builds config map from current convertConfig state
- Passes to buildFFmpegCommandFromJob() for command generation
- Updates preview dynamically (foundation for real-time updates)
- Includes all conversion settings (codecs, filters, quality, audio)
3. UI layout improvements:
- Added labeled "FFmpeg Command Preview:" header
- Scrollable monospace command display (80px min height)
- Copy button with clipboard integration
- Clean separation from other sections
Users can now see and copy the exact FFmpeg command that will be used
for their conversion before starting it. This makes it easy to reproduce
VideoTools' output in external tools or verify settings.
Next: Add Copy Command button to queue view for active/pending jobs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented the foundation for FFmpeg command copy functionality:
1. Created FFmpegCommandWidget (components.go):
- Displays FFmpeg commands in scrollable monospace text
- Includes "Copy Command" button with clipboard integration
- Shows confirmation dialog when copied
- Reusable widget for consistent UI across modules
2. Created buildFFmpegCommandFromJob() function (main.go):
- Extracts FFmpeg command from queue job config
- Uses INPUT/OUTPUT placeholders for portability
- Handles video filters (deinterlace, crop, scale, aspect, flip, rotate, fps)
- Handles video codecs with hardware acceleration (H.264, H.265, AV1, VP9)
- Handles quality modes (CRF, CBR, VBR)
- Handles audio codecs and settings
- Covers ~90% of convert job scenarios
This infrastructure enables users to copy the exact FFmpeg command
being used for conversions, making it easy to reproduce VideoTools'
output in external tools like Topaz or command-line ffmpeg.
Next phase will integrate this into the Convert module UI, queue view,
and conversion history sidebar.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The queue Stats() method was grouping cancelled and failed jobs together,
causing cancelled jobs to be displayed as "failed" in the status bar.
Updated Stats() to return a separate cancelled count and modified all
callers (updateStatsBar, queueProgressCounts, showMainMenu) to handle
the new return value. Also updated ConversionStatsBar to display
cancelled jobs separately in the status bar.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add navigationHistory and navigationHistoryPosition to appState
- Add navigationHistorySuppress flag to prevent recursive history tracking
- Implement pushNavigationHistory to track module navigation
- Implement navigateBack and navigateForward for mouse button navigation
- Create mouseButtonHandler widget to capture mouse button events
- Wrap all content with mouseButtonHandler in setContent
- Track history in showModule and showMainMenu
- Handle mouse button 4 (back) and mouse button 5 (forward)
- Maintain history of up to 50 module navigations
Mouse back/forward buttons now work like a web browser - press the back button
to return to previous modules, press forward to go back to where you were.
History is maintained across all module transitions for seamless navigation.
- Add check in loadPersistedConvertConfig to default FrameRate to "Source" if empty
- Add check after loading persisted config to ensure FrameRate is "Source" if not set
- Prevents unwanted frame rate conversions from persisted config overriding safe defaults
This ensures that frame rate always defaults to "Source" and users won't
accidentally convert all their videos to 23.976fps or another frame rate
if they had previously saved a config with a specific frame rate set.
- Add upscaleFrameRate and upscaleMotionInterpolation fields to appState
- Add Frame Rate section to upscale UI with dropdown and motion interpolation checkbox
- Pass frame rate settings through upscale job config
- Implement frame rate conversion in executeUpscaleJob using minterpolate or fps filter
- Frame rate section appears after resolution selection in upscale settings
Frame rate control is now available in both convert and upscale modules,
allowing users to standardize content from different regions with optional
motion interpolation for smooth conversion.
- Add UseMotionInterpolation field to convertConfig struct
- Implement minterpolate filter for smooth frame rate changes when enabled
- Add UI checkbox in advanced settings for motion interpolation option
- Use minterpolate with high-quality settings (mci mode, aobmc, bidir ME, vsbmc)
- Falls back to simple fps filter when motion interpolation is disabled
- Fix pre-existing statusBar function calls (renamed to moduleFooter)
Motion interpolation provides smooth frame rate conversion (e.g., 24fps→60fps)
using motion-compensated interpolation instead of simple frame duplication.
This is useful for standardizing content from different regions.
Removed confirmation dialog popups when converting files with
chapters to DVD format. Instead, show a non-intrusive inline
warning label that appears/disappears based on format selection.
Warning label:
- Shows only when file has chapters AND DVD format is selected
- Displays inline below format selector in both simple and advanced modes
- No user action required - just informational
- Text: "Chapters will be lost - DVD format doesn't support embedded chapters. Use MKV/MP4 to preserve chapters."
When converting a file with chapters to DVD/MPEG format, show
a confirmation dialog warning the user that chapters will be lost.
MPEG format does not support embedded chapters - they require
full DVD authoring with IFO files. Users are warned and given
the option to cancel or continue.
Warning appears for both 'Convert Now' and 'Add to Queue' buttons.
Added -show_chapters flag to ffprobe command to retrieve chapter
information. Parse chapters from JSON output and set HasChapters
field when chapters are present.
Files with chapters will now correctly show 'Chapters: Yes' in
the file information display.
Added explicit stream mapping to preserve all streams:
- Map video, audio, and subtitle streams (subtitles optional)
- Added -map_chapters to preserve chapter information
- Added -map_metadata to preserve all file metadata
- Copy subtitle streams without re-encoding
Applies to both conversions with and without cover art.
Works for all output formats that support these features.
Removed -target ntsc-dvd and -target pal-dvd preset flags which
strip metadata including chapters. Instead, manually specify all
DVD parameters (bitrate, maxrate, bufsize, format) to maintain
full control and preserve chapter metadata.
Chapters now retained in both new 'dvd' format and legacy DVD formats.
When 'Clear Completed' empties the queue, return to the previous
module instead of staying in an empty queue view. If jobs remain
after clearing, stay in queue view and refresh.
Changed 'Clear All' behavior to return to the last active module
instead of always going to main menu. Falls back to main menu
if no previous module is tracked or if coming from queue itself.
Added clearer format descriptions:
- "Fast Merge (No Re-encoding)" instead of "MKV (Copy streams)"
- "Lossless MKV (Best Quality)" - new option with slow preset, CRF 18, FLAC audio
- "High Quality MP4 (H.264/H.265)" instead of technical codec names
- "DVD Format" with conditional region/aspect selectors
- "Blu-ray Format" instead of "Blu-ray (H.264)"
DVD Format improvements:
- When "DVD Format" is selected, shows Region (NTSC/PAL) and Aspect (16:9/4:3) options
- Options hidden for other formats
- Stored in state and passed to merge job config
- Updated execution to use DVD region/aspect settings
Maintains backward compatibility with legacy DVD format codes.
WMV Encoder Fix:
- WMV files now use wmv2 encoder (ffmpeg compatible) instead of wmv3
- Audio uses wmav2 for WMV files
- High quality bitrate (2000k) for WMV video
- Fallback handling for unsupported source codecs
UI Simplification:
- Changed "High Quality (source format/codecs)" to "Match Source Format"
- Simplified hint text to just "Unchecked = Use Conversion Settings"
- More concise and less confusing labels
Snippet Quality Improvements:
- High Quality mode now detects and uses source codecs (WMV stays WMV)
- Uses conversion panel's encoder preset (e.g., 'slow') instead of hardcoded 'ultrafast'
- Uses conversion panel's CRF setting for quality control
- Outputs to source file extension in High Quality mode
- Updated UI label to "High Quality (source format/codecs)"
Workflow Streamlining:
- Removed popup dialog when loading multiple videos
- Showing convert view is sufficient feedback
- Failed files logged instead of shown in dialog
UI Fixes:
- Status label no longer wraps to new line on action bar
- Set text truncation to keep status on single line
Changed snippet "Default Format" mode from stream copy to re-encoding with
high quality settings (libx264, CRF 17, ultrafast preset). Stream copy
cannot provide precise durations as it can only cut at keyframe boundaries.
Both snippet modes now output MP4 and re-encode. The difference is quality:
- High Quality mode: CRF 17, ultrafast preset
- Conversion Settings mode: Uses configured output settings
Updated UI labels to reflect "Snippet Quality" instead of output format.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Reverts the problematic -accurate_seek and -to flags that caused wildly incorrect durations (9:40 instead of 10s). Returns to the standard, reliable FFmpeg pattern for stream copy:
ffmpeg -ss START -i input -t DURATION -c copy output
This places -ss before -i for fast keyframe seeking and uses -t for duration (not -to which is an absolute timestamp causing incorrect extraction). Should now correctly extract the configured snippet length centered on video midpoint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Improves snippet timing accuracy for Default Format mode by:
- Adding -accurate_seek flag for precise keyframe seeking
- Changing from -t (duration) to -to (end time) for better accuracy
- Adding -avoid_negative_ts make_zero to fix timestamp issues with problematic containers like WMV
This should resolve issues where snippets were 1:20 or 0:21 instead of the configured length (e.g., 10s). Stream copy still uses keyframe-level precision but should now be much closer to target duration.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes multi-video drag-and-drop behavior to load videos into memory instead of automatically adding them to conversion queue. This allows users to:
- Adjust conversion settings before queuing
- Generate snippets instead of converting
- Navigate through videos before deciding to convert
Creates new loadMultipleVideos() function that loads all videos into loadedVideos array and shows informative dialog. Users can now use Convert or Snippet buttons to manually process videos as needed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes checkbox label from "Use Source Format (stream copy)" to "Snippet to Default Format (preserves source quality)". Unchecked state is now "Snippet to Output Format (uses conversion settings)". This clarifies that default format preserves the source file's quality, bitrate, codec, and container without any conversion artifacts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Updates snippet conversion mode to use configured video/audio codecs, presets, CRF, and bitrates from the Convert tab instead of hardcoded h264/AAC. Output extension now matches selected format (e.g., .mkv, .webm, .mp4). This allows true comparison between source format snippets and conversion preview snippets using user's exact conversion settings.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements configurable snippet output mode with two options:
1. Source Format (default): Uses stream copy to preserve exact video/audio quality with source container format. Duration uses keyframe-level precision (may not be frame-perfect).
2. Conversion Format: Re-encodes to h264/AAC MP4 with frame-perfect duration control.
Adds checkbox control in snippet settings UI. Users can now compare source format snippets for merge testing and conversion format snippets for output preview.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes snippet generation to always output .mp4 files instead of preserving source extension. This fixes duration accuracy issues caused by container/codec mismatch (e.g., h264 video in .wmv container). MP4 is the proper container for h264-encoded video and ensures FFmpeg respects the -t duration parameter correctly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Updates application version constant, documentation, and completion tracking to reflect dev18 release. Build output now correctly shows v0.1.0-dev18.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enhances screenshot module with comprehensive technical metadata display including audio bitrate, adds 8px padding between thumbnails for professional contact sheets. Implements new Player module for video playback access. Adds complete Filters and Upscale modules with traditional FFmpeg scaling methods (Lanczos, Bicubic, Spline, Bilinear) and resolution presets (720p-8K). Introduces configurable snippet length (5-60s, default 20s) with batch generation capability for all loaded videos. Fixes snippet duration precision by re-encoding instead of stream copy to ensure frame-accurate cutting at configured length.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed thumbnail module to match convert module behavior with two
action buttons:
GENERATE NOW (High Importance):
- Adds job to queue and starts it immediately
- Runs right away if queue is idle
- Queues for later if jobs are running
- Shows "Thumbnail generation started!" message
Add to Queue (Medium Importance):
- Adds job to queue without starting
- Allows queuing multiple jobs
- Shows "Thumbnail job added to queue!" message
Implementation:
- Refactored job creation into createThumbJob() helper function
- Both buttons use same job creation logic
- Generate Now auto-starts queue if not running
- Follows same pattern as convert module
Benefits:
- Immediate generation when queue is idle
- Queue multiple jobs without starting
- Consistent UX with convert module
- Clear user feedback on action taken
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed the exit 234 error when generating individual thumbnails by
disabling the timestamp overlay feature which was causing FFmpeg
font-related failures on some systems.
Changes:
- ShowTimestamp: false (was true)
- ShowMetadata: only true for contact sheets (was always true)
The timestamp overlay was causing issues because:
1. DejaVu Sans Mono font might not be available on all systems
2. FFmpeg exits with code 234 when drawtext filter fails
3. Individual thumbnails don't need timestamp overlays anyway
Contact sheets still get metadata headers, which is the main use case
for showing video information on thumbnails.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed Thumbnail Count Issue:
- Changed frame selection from hardcoded 30fps to timestamp-based
- Now uses gte(t,timestamp) filter for accurate frame selection
- This fixes the issue where 5x8 grid only generated 34 instead of 40 thumbnails
Improved Contact Sheet Display:
- Reduced thumbnail width from 320px to 200px for better window fit
- Changed background color from black to app theme (#0B0F1A)
- Contact sheets now match the VideoTools dark blue theme
Added Viewing Capability:
- New "View Results" button in thumbnail module
- Contact sheet mode: Shows image in full-screen dialog (900x700)
- Individual mode: Opens thumbnail folder in file manager
- Button checks if output exists before showing
- Provides user-friendly messages when no results found
Benefits:
- Correct number of thumbnails generated for any grid size
- Contact sheets fit better in display window
- Visual consistency with app theme
- Easy access to view generated results within the app
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added full job queue integration for thumbnail generation:
Job Queue Integration:
- Implemented executeThumbJob() to handle thumbnail generation in queue
- Changed "Generate Thumbnails" to "Add to Queue" button
- Added "View Queue" button to thumbnail module
- Removed direct generation code in favor of queue system
Progress Tracking:
- Jobs now show in queue with progress bar
- Contact sheet mode: shows grid dimensions in description
- Individual mode: shows count and width in description
- Job title: "Thumbnails: {filename}"
Benefits:
- Real-time progress tracking via queue progress bar
- Can queue multiple thumbnail jobs
- Access queue from thumbnail screen
- Consistent with other modules (convert, merge, snippet)
- Background processing without blocking UI
The thumbnail module now uses the same job queue system as other
modules, providing progress tracking and background processing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed the total thumbnails label to update in real-time when adjusting
columns or rows sliders in contact sheet mode.
Changes:
- Created totalLabel before sliders so both callbacks can access it
- Both column and row slider OnChanged callbacks now update the total
- Total recalculates as: columns × rows on each slider change
The total now updates immediately as you adjust the grid dimensions,
providing instant feedback on how many thumbnails will be generated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed Issues:
- Exit 234 error: Added font parameter to drawtext filter for individual
thumbnails (was missing, causing FFmpeg to fail)
- Output directory: Changed from temp to video's directory, creating a
folder named "{video}_thumbnails" next to the source file
New Features:
- Added video preview window to thumbnail module (640x360)
- Split layout: preview on left (55%), settings on right (45%)
- Preview uses same buildVideoPane as other modules for consistency
The thumbnail module now has a proper preview window for reviewing
the loaded video before generating thumbnails, and outputs are saved
in a logical location next to the source file.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed snippet extraction to use stream copy instead of re-encoding:
- Removed all convert config and encoding logic
- Now uses `-c copy` to copy all streams without re-encoding
- Uses same file extension as source for container compatibility
- Much faster extraction with no quality loss
- Updated job description to indicate "source settings"
This makes snippet generation instant instead of requiring full re-encode.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented metadata header rendering on contact sheets showing:
- Filename and file size
- Video resolution and duration
Uses FFmpeg pad and drawtext filters to create an 80px header area
with white text on black background.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
New Features:
- Thumbnail extraction package with FFmpeg integration
- Individual thumbnails or contact sheet generation
- Configurable thumbnail count (3-50 thumbnails)
- Adjustable thumbnail width (160-640 pixels)
- Contact sheet mode with customizable grid (2-10 columns/rows)
- Timestamp overlay on thumbnails
- Auto-open generated thumbnails folder
Technical Implementation:
- internal/thumbnail package with generator
- FFmpeg-based frame extraction
- Video duration and dimension detection
- Aspect ratio preservation
- JPEG quality control
- PNG lossless option support
UI Features:
- Thumbnail module in main menu (Orange tile)
- Load video via file picker
- Real-time configuration sliders
- Contact sheet toggle with grid controls
- Generate button with progress feedback
- Success dialog with folder open option
Integration:
- Added to module routing system
- State management for thumb module
- Proper Fyne threading with DoFromGoroutine
- Cross-platform folder opening support
Module is fully functional and ready for testing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Features added:
- Auto-detection in Inspect module: runs QuickAnalyze automatically when video is loaded
- Interlacing results display in Inspect metadata panel
- Deinterlace preview generation: side-by-side comparison button in Convert view
- Analyze button integration in Simple menu deinterlacing section
- Auto-apply deinterlacing settings when recommended
The Inspect module now automatically analyzes videos for interlacing when loaded via:
- Load button
- Drag-and-drop to main menu tile
- Drag-and-drop within Inspect view
Results appear directly in the metadata panel with full detection details.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Major features in this release:
1. Fixed merge job progress reporting
- Progress counter was jumping to 100% immediately due to incorrect
time unit conversion (microseconds vs milliseconds)
- Now shows accurate real-time progress throughout merge operations
2. Hardware encoder benchmarking system
- Automatic test video generation (30s 1080p test pattern)
- Detects available hardware encoders (NVENC, QSV, AMF, VideoToolbox)
- Tests all available encoders with multiple presets
- Measures FPS performance and ranks results
- Provides optimal encoder recommendation for user's hardware
- Real-time progress tracking with live results display
3. Benchmark history tracking
- Stores up to 10 most recent benchmark runs
- Browse past benchmark results with detailed comparisons
- View all encoder/preset combinations tested in each run
- Compare performance across different presets and encoders
- Apply recommendations from any past benchmark
- Persistent storage in ~/.config/VideoTools/benchmark.json
UI improvements:
- "Run Benchmark" button in main menu
- "View Results" button to browse benchmark history
- Live progress view showing current test and results
- Comprehensive results view with all encoder data
- Fixed merge module file list to use full vertical space
Bug fixes:
- Fixed merge progress calculation (microseconds issue)
- Fixed Fyne threading errors in benchmark UI updates
- Fixed progress bar percentage display (0-100 range)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extended the benchmark system to maintain a complete history of all
benchmark runs (up to last 10) with full results for each encoder/preset
combination tested.
Features:
- Stores complete benchmark run data including all test results
- History browser UI to view past benchmark runs
- Click any run to see detailed results for all encoders tested
- Compare performance across different presets and encoders
- Apply recommendations from past benchmarks
- Automatic history limit (keeps last 10 runs)
UI Changes:
- Renamed "Benchmark" button to "Run Benchmark"
- Added "View Results" button to main menu
- New benchmark history view showing all past runs
- Each run displays timestamp, recommended encoder, and test count
- Clicking a run shows full results with all encoder/preset combinations
Data Structure:
- benchmarkRun: stores single test run with all results
- benchmarkConfig: maintains array of benchmark runs
- Saves to ~/.config/VideoTools/benchmark.json
This allows users to review past benchmark results and make informed
decisions about which encoder settings to use by comparing FPS across
all available options on their hardware.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented a full benchmark system that automatically detects available
hardware encoders, tests them with different presets, measures FPS
performance, and recommends optimal settings for the user's system.
Features:
- Automatic test video generation (30s 1080p test pattern)
- Hardware encoder detection (NVENC, QSV, AMF, VideoToolbox)
- Comprehensive encoder testing across multiple presets
- Real-time progress UI with live results
- Performance scoring based on FPS metrics
- Top 10 results display with recommendation
- Config persistence for benchmark results
- One-click apply to use recommended settings
UI Components:
- Benchmark button in main menu header
- Progress view showing current test and results
- Final results view with ranked encoders
- Apply/Close actions for recommendation
Integration:
- Added to main menu between "Benchmark" and "Logs" buttons
- Saves results to ~/.config/VideoTools/benchmark.json
- Comprehensive debug logging for troubleshooting
This allows users to optimize their encoding settings based on their
specific hardware capabilities rather than guessing which encoder
will work best.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The issue was that FFmpeg's out_time_ms field is actually in microseconds
(not milliseconds despite the name). We were dividing by 1,000 when we
should have been dividing by 1,000,000 to convert to seconds.
This caused the progress calculation to be off by 1000x, making it
immediately jump to 100% even though the job was just starting.
Also added comprehensive debug logging to track progress samples and
identify calculation issues in the future.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Issue: File list only used half the vertical space, wasting screen real estate.
Changed left panel from VBox to Border layout:
- Top: "Clips to Merge" label and Add/Clear buttons (fixed size)
- Center: File list scroll area (expands to fill remaining space)
The border layout gives the scroll area priority to expand vertically,
maximizing the visible file list area. This is especially important
when merging many clips.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
User reports progress jumps to 100% within 10 seconds but merge continues for 45s total.
Added comprehensive debug logging to track:
- Individual clip durations as they're summed
- Total expected duration for the merge
- Exact moment when progress hits 100% with actual vs expected times
- Only update progress when it changes by ≥0.1% (reduces callback spam)
This will help diagnose whether:
- Clip durations are being calculated incorrectly
- FFmpeg's out_time_ms doesn't match expected total duration
- Concat demuxer reports different output duration than sum of inputs
Logging appears in logs/videotools.log with CatFFMPEG category.
To view: tail -f logs/videotools.log | grep FFMPEG
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Issues fixed:
- Missing file extensions caused FFmpeg errors (user's job 234 failure)
- Limited codec options (only copy or H.265)
- Manual codec mode selector was redundant
Changes:
1. Auto file extension handling:
- Automatically adds/corrects extension based on selected format
- .mkv for MKV/Blu-ray formats
- .mpg for DVD formats
- .mp4 for MP4 formats
- Validates and fixes extension in addMergeToQueue
2. Expanded format options:
- MKV (Copy streams) - stream copy, no re-encoding
- MKV (H.264) - re-encode with H.264, CRF 23
- MKV (H.265) - re-encode with H.265, CRF 28
- MP4 (H.264) - H.264 + AAC audio, web-optimized
- MP4 (H.265) - H.265 + AAC audio, web-optimized
- DVD NTSC/PAL (16:9 and 4:3)
- Blu-ray (H.264)
3. Removed redundant codec mode selector:
- Format dropdown now explicitly includes codec choice
- Cleaner, more intuitive UI
- Backward compatible with old queue jobs
Extension is auto-updated when:
- User selects a different format (updates existing path extension)
- User adds merge to queue (validates/fixes before encoding)
- Prevents errors from missing or wrong file extensions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The -progress flag was being added AFTER the output path in the FFmpeg command,
causing FFmpeg to not recognize it and therefore not output progress information.
Moved -progress pipe:1 -nostats to appear BEFORE the output path.
Now merge jobs will correctly report progress as they encode:
- Progress starts at 0%
- Updates based on out_time_ms from FFmpeg progress output
- Calculates percentage based on total duration of all clips
- Shows accurate real-time progress in queue view and stats bar
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The Merge module's ui.NewDroppable wrappers weren't receiving drop events
because the window-level handleDrop function was intercepting them first.
Added merge module handling to handleDrop function:
- Accepts individual video files and adds them sequentially to merge clips
- Accepts multiple files at once and processes all in order
- Accepts folders and recursively finds all video files
- Probes each video to get duration and metadata
- Sets chapter names defaulting to filename
- Auto-sets output path to "merged.mkv" once 2+ clips are added
- Refreshes UI after each clip is added
Now drag-and-drop works consistently across all modules (Convert, Compare, Inspect, Merge).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>