A powerful, multi-threaded video transcoding tool built with Python and HandBrakeCLI. This script automatically processes video files in a directory structure, transcoding them to efficient formats while providing real-time progress tracking and intelligent pause/resume functionality.
Compatibility: Windows only. The pause menu and process control rely on Windows console APIs. Linux and macOS are not supported.
# Basic
python transcode_videos.py /path/to/video/directory
# Choose worker count
python transcode_videos.py /path/to/video/directory 8
# Reduce console noise or enable debug
python transcode_videos.py /path/to/video/directory --quiet
python transcode_videos.py /path/to/video/directory --verbose
# Windows path example
python transcode_videos.py "C:\\Videos\\Movies" 4 --quiet
- Automatic codec detection - Skips already efficient codecs (H.265, HEVC, AV1)
- Bitrate analysis - Avoids transcoding files that would likely become larger
- Resolution filtering - Configurable minimum resolution thresholds
- File size validation - Prevents transcoding when output would be larger than input
- Configurable worker threads - Process multiple videos simultaneously
- Real-time progress bars - Live HandBrake progress parsing for accurate completion estimates
- Ordered worker display - Workers always shown in numerical order (Worker_1, Worker_2, etc.)
- Thread-safe logging - Comprehensive CSV logging of all operations
- Keyboard interrupt support - Ctrl+C to pause/resume workers
- Process suspension - Actual HandBrake process suspension on Windows for true pause functionality
- Graceful shutdown options - Choose immediate shutdown or wait for current jobs to complete
- Resume from interruption - Automatically skips already processed files
- CSV progress tracking - Detailed logs of all processed files
- Status categorization - success, skipped_* categories, interrupted
- Separate failed log -
transcode_failed_log.csv
stores only failures; main log stays clean - Size comparison - Before/after file sizes and compression ratios
- Intelligent skip detection - Separate tracking for different skip reasons
- Windows process control - Full process suspension/resume support
- Tested environments - Windows 10/11, PowerShell and Windows Terminal
- PATH requirements -
HandBrakeCLI
andffprobe
must be available in PATH
- Supported OS - Windows 10/11 (64-bit)
- Python 3.6+ - Core runtime
- HandBrakeCLI - Video transcoding engine
- Download from: https://handbrake.fr/downloads2.php
- Must be accessible via
HandBrakeCLI
command in PATH
- FFprobe (part of FFmpeg) - Video analysis
- Download from: https://ffmpeg.org/download.html
- Must be accessible via
ffprobe
command in PATH
All dependencies are part of Python standard library:
threading
- Multi-threading supportsubprocess
- External process managementcsv
- Logging functionalitysignal
- Keyboard interrupt handlingos
,sys
,shutil
- File system operationstime
,json
- Utilities
- ctypes - For process suspension/resume functionality
- Requires Windows kernel32.dll access
- Clone or download this repository
- Install HandBrakeCLI and ensure it's in your system PATH
- Install FFmpeg and ensure
ffprobe
is in your system PATH - Configure the script by editing the configuration section
Edit the configuration variables at the top of transcode_videos.py
:
# === Configuration ===
MAX_WORKERS = 4 # Number of concurrent transcoding workers
CREATE_BACKUPS = False # Create backup copies of original files
BACKUP_SUBDIR = "backups" # Backup directory name
SHOW_PROGRESS = True # Enable real-time progress bars
# HandBrake settings
PRESET = "Fast 1080p30 Subs" # HandBrake encoding preset (by name)
PRESET_JSON = "fast1080p30subs.json" # Preset file path (imported at runtime)
python transcode_videos.py /path/to/video/directory
python transcode_videos.py /path/to/video/directory 4
python transcode_videos.py /path/to/video/directory --quiet
python transcode_videos.py /path/to/video/directory 8 --verbose
During execution, use Ctrl+C to access the pause menu:
⏸ WORKERS PAUSED - Choose an option:
(R) Resume workers
(Q) Quit immediately - stop all workers now
(S) Graceful shutdown - finish current jobs then stop
Choice:
- R - Resume all workers and continue processing
- Q - Immediately terminate all workers and exit
- S - Allow current jobs to finish, then gracefully exit
- Console clear around menu: toggle via
MENU_CLEAR_CONSOLE
(default: true) - Pre-menu settle delay:
MENU_SETTLE_MS
(default: 250 ms) - Quiet mode: add
--quiet
or-q
to reduce console noise - Verbose mode: add
--verbose
or-v
for extra debug output
[Worker_1 ] video1.mp4 [████████████░░░░░░░░░░░░░] 52.3% Transcoding
[Worker_2 ] video2.avi [██████░░░░░░░░░░░░░░░░░░░] 24.7% Transcoding
[Worker_3 ] video3.mkv [███████████████░░░░░░░░░] 65.1% Transcoding
Processing complete!
Successful: 145
Skipped (low resolution): 23
Skipped (likely larger): 8
Skipped (larger after transcode): 5
Failed: 2
Total: 183
The transcode_log.csv
file contains detailed processing information:
Column | Description |
---|---|
filepath | Full path to the processed file |
status | Processing result (success, failed, skipped_*) |
timestamp | ISO timestamp of completion |
before_size_mb | Original file size in MB |
after_size_mb | Transcoded file size in MB |
compression_ratio | Size ratio (after/before) |
The script intelligently skips files in several scenarios:
skipped_low_res_WIDTHxHEIGHT
- Video resolution below configured minimums
skipped_likely_larger_low_bitrate_X_Mbps_for_WIDTHxHEIGHT
- Already efficient encoding- Files already using H.265, HEVC, or AV1 codecs
skipped_larger_size_X.XXX
- Transcoded file would be larger than original
"HandBrakeCLI not found"
- Ensure HandBrakeCLI is installed and in your system PATH
- Test with:
HandBrakeCLI --version
"ffprobe not found"
- Ensure FFmpeg is installed and ffprobe is in your system PATH
- Test with:
ffprobe -version
Workers get stuck after pause/resume
- Check for HandBrake process suspension issues
- Review debug output for specific worker problems
- Consider restarting the script if workers remain unresponsive
High memory usage
- Reduce
MAX_WORKERS
if experiencing memory pressure - HandBrake processes can be memory-intensive for large files
For troubleshooting, disable progress bars to see detailed output:
SHOW_PROGRESS = False
This reveals:
- Detailed HandBrake command execution
- Process suspension/resume messages
- Worker state transitions
- Error details and return codes
- Separate failed runs into
transcode_failed_log.csv
- Added UNC network share wait/retry (configurable) to survive network adapter sleep
- Added network recovery constants (
NETWORK_CHECK_INTERVAL
,NETWORK_MAX_WAIT
,NETWORK_RETRY_ENABLED
) - Internal refactors / minor robustness fixes
- Adds optional console clear/redraw around the pause menu for a crisper UI
- Makes the pre-menu settle delay configurable via
MENU_SETTLE_MS
- Adds
--quiet
/--verbose
flags to control console noise
- Reliable Ctrl+C pause menu on Windows via console control handler
- HandBrakeCLI launched in a new process group so Ctrl+C doesn't kill it
- Optional Windows process suspension during pause for true pauses
- Interrupted jobs are logged as "interrupted" (they retry), not "failed"
- Fixed cancelled jobs being logged as 'failed' in CSV
- Improved worker display ordering (always numerical)
- Enhanced pause/resume reliability with better state validation
- Added comprehensive debugging and error handling
- Added graceful shutdown vs immediate shutdown options
- Improved worker thread naming (Worker_1, Worker_2, etc.)
- Fixed progress bar alignment issues
- Enhanced signal handling for better Ctrl+C behavior
- Added real-time HandBrake progress parsing
- Implemented cross-platform compatibility
- Added keyboard interrupt pause/resume functionality
- Initial release with basic transcoding functionality
- Multi-threaded processing
- CSV logging
- Created by: Claude Sonnet 4 (through version v0.4.0)
- Updated by: Chat GPT-5 (Preview) starting with v0.5.x
Feel free to submit issues, feature requests, or pull requests. When contributing:
- Test thoroughly with various video formats and scenarios
- Maintain Windows compatibility
- Update documentation for any new features
- Follow existing code style and commenting patterns
This project is provided as-is for personal and educational use. Please ensure you have appropriate rights to transcode any video files you process.
- HandBrake team - For the excellent HandBrakeCLI transcoding engine
- FFmpeg team - For the powerful ffprobe video analysis tool
- Python community - For the robust standard library that makes this possible