{"id":30749446,"url":"https://github.com/e2m32/handbrake-batch-transcoder-win","last_synced_at":"2026-04-18T01:31:58.429Z","repository":{"id":311336469,"uuid":"1040181168","full_name":"e2m32/handbrake-batch-transcoder-win","owner":"e2m32","description":"Batch transcode directories on Windows with HandBrakeCLI; multi-threaded workers, interactive pause menu, intelligent skipping, and detailed logging.","archived":false,"fork":false,"pushed_at":"2025-08-27T14:50:38.000Z","size":82,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-09T00:08:21.451Z","etag":null,"topics":["batch-processing","ffmpeg","handbrake","handbrake-cli","handbrake-script","handbrakecli","multithreading","python","python3","transcoding","video","windows","windows-10","windows-11"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/e2m32.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-18T15:20:32.000Z","updated_at":"2025-08-27T14:50:42.000Z","dependencies_parsed_at":"2025-08-24T08:56:08.677Z","dependency_job_id":"d4801933-3ff1-48a7-a2b3-8c68addc79cf","html_url":"https://github.com/e2m32/handbrake-batch-transcoder-win","commit_stats":null,"previous_names":["e2m32/handbrake-batch-transcoder-win"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/e2m32/handbrake-batch-transcoder-win","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e2m32%2Fhandbrake-batch-transcoder-win","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e2m32%2Fhandbrake-batch-transcoder-win/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e2m32%2Fhandbrake-batch-transcoder-win/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e2m32%2Fhandbrake-batch-transcoder-win/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/e2m32","download_url":"https://codeload.github.com/e2m32/handbrake-batch-transcoder-win/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e2m32%2Fhandbrake-batch-transcoder-win/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31953511,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"ssl_error","status_checked_at":"2026-04-18T00:39:20.671Z","response_time":62,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["batch-processing","ffmpeg","handbrake","handbrake-cli","handbrake-script","handbrakecli","multithreading","python","python3","transcoding","video","windows","windows-10","windows-11"],"created_at":"2025-09-04T06:04:48.448Z","updated_at":"2026-04-18T01:31:58.402Z","avatar_url":"https://github.com/e2m32.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Video Transcoding Script\n\nA 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.\n\n\u003e Compatibility: Windows only. The pause menu and process control rely on Windows console APIs. Linux and macOS are not supported.\n\n## Quick start\n\n```bash\n# Basic\npython transcode_videos.py /path/to/video/directory\n\n# Choose worker count\npython transcode_videos.py /path/to/video/directory 8\n\n# Reduce console noise or enable debug\npython transcode_videos.py /path/to/video/directory --quiet\npython transcode_videos.py /path/to/video/directory --verbose\n\n# Windows path example\npython transcode_videos.py \"C:\\\\Videos\\\\Movies\" 4 --quiet\n```\n\n## Features\n\n### 🎥 Smart Video Processing\n- **Automatic codec detection** - Skips already efficient codecs (H.265, HEVC, AV1)\n- **Bitrate analysis** - Avoids transcoding files that would likely become larger\n- **Resolution filtering** - Configurable minimum resolution thresholds\n- **File size validation** - Prevents transcoding when output would be larger than input\n\n### 🚀 Multi-threaded Performance\n- **Configurable worker threads** - Process multiple videos simultaneously\n- **Real-time progress bars** - Live HandBrake progress parsing for accurate completion estimates\n- **Ordered worker display** - Workers always shown in numerical order (Worker_1, Worker_2, etc.)\n- **Thread-safe logging** - Comprehensive CSV logging of all operations\n\n### ⏸️ Interactive Control\n- **Keyboard interrupt support** - Ctrl+C to pause/resume workers\n- **Process suspension** - Actual HandBrake process suspension on Windows for true pause functionality\n- **Graceful shutdown options** - Choose immediate shutdown or wait for current jobs to complete\n- **Resume from interruption** - Automatically skips already processed files\n\n### 📊 Comprehensive Logging\n- **CSV progress tracking** - Detailed logs of all processed files\n- **Status categorization** - success, skipped_* categories, interrupted\n- **Separate failed log** - `transcode_failed_log.csv` stores only failures; main log stays clean\n- **Size comparison** - Before/after file sizes and compression ratios\n- **Intelligent skip detection** - Separate tracking for different skip reasons\n- **Final move retry** - Automatically retries placing the final transcoded file (helps with transient network hiccups)\n\n### 🔧 Windows-only Support\n- **Windows process control** - Full process suspension/resume support\n- **Tested environments** - Windows 10/11, PowerShell and Windows Terminal\n- **PATH requirements** - `HandBrakeCLI` and `ffprobe` must be available in PATH\n\n## Prerequisites\n\n### Required Software\n- **Supported OS** - Windows 10/11 (64-bit)\n- **Python 3.6+** - Core runtime\n- **HandBrakeCLI** - Video transcoding engine\n  - Download from: https://handbrake.fr/downloads2.php\n  - Must be accessible via `HandBrakeCLI` command in PATH\n- **FFprobe** (part of FFmpeg) - Video analysis\n  - Download from: https://ffmpeg.org/download.html\n  - Must be accessible via `ffprobe` command in PATH\n\n### Python Dependencies\nAll dependencies are part of Python standard library:\n- `threading` - Multi-threading support\n- `subprocess` - External process management\n- `csv` - Logging functionality\n- `signal` - Keyboard interrupt handling\n- `os`, `sys`, `shutil` - File system operations\n- `time`, `json` - Utilities\n\n### Windows-specific (Optional)\n- **ctypes** - For process suspension/resume functionality\n- Requires Windows kernel32.dll access\n\n## Installation\n\n1. **Clone or download** this repository\n2. **Install HandBrakeCLI** and ensure it's in your system PATH\n3. **Install FFmpeg** and ensure `ffprobe` is in your system PATH\n4. **Configure the script** by editing the configuration section\n\n## Configuration\n\nEdit the configuration variables at the top of `transcode_videos.py`:\n\n```python\n# === Configuration ===\nMAX_WORKERS = 4               # Number of concurrent transcoding workers\nCREATE_BACKUPS = False        # Create backup copies of original files\nBACKUP_SUBDIR = \"backups\"     # Backup directory name\nSHOW_PROGRESS = True          # Enable real-time progress bars\n\n# HandBrake settings\nPRESET = \"Fast 1080p30 Subs\"           # HandBrake encoding preset (by name)\nPRESET_JSON = \"fast1080p30subs.json\"   # Preset file path (imported at runtime)\n```\n\n### Network \u0026 Finalization Reliability\n\n```python\n# Network share resilience\nNETWORK_CHECK_INTERVAL = 10        # seconds between network availability checks\nNETWORK_MAX_WAIT = 5 * 60 * 60     # max seconds to wait (5 hours)\nNETWORK_RETRY_ENABLED = True       # enable waiting instead of failing fast\n\n# Final move (rename) retry\nFINAL_MOVE_RETRIES = 5             # attempts to move temp file into place\nFINAL_MOVE_RETRY_DELAY = 15        # initial delay before first retry (seconds)\nFINAL_MOVE_BACKOFF_FACTOR = 2      # exponential backoff multiplier\n```\n\nThese help the script survive Wi-Fi adapter sleep, NAS spin-up delays, and transient SMB hiccups.\n\n## Usage\n\n### Basic Usage\n```bash\npython transcode_videos.py /path/to/video/directory\n```\n\n### With Custom Worker Count\n```bash\npython transcode_videos.py /path/to/video/directory 4\n```\n\n### With Flags (quiet/verbose)\n```bash\npython transcode_videos.py /path/to/video/directory --quiet\npython transcode_videos.py /path/to/video/directory 8 --verbose\n```\n\n### Interactive Controls\n\nDuring execution, use **Ctrl+C** to access the pause menu:\n\n```\n⏸ WORKERS PAUSED - Choose an option:\n(R) Resume workers\n(Q) Quit immediately - stop all workers now\n(S) Graceful shutdown - finish current jobs then stop\nChoice: \n```\n\n- **R** - Resume all workers and continue processing\n- **Q** - Immediately terminate all workers and exit\n- **S** - Allow current jobs to finish, then gracefully exit\n\n#### UI options\n- Console clear around menu: toggle via `MENU_CLEAR_CONSOLE` (default: true)\n- Pre-menu settle delay: `MENU_SETTLE_MS` (default: 250 ms)\n- Quiet mode: add `--quiet` or `-q` to reduce console noise\n- Verbose mode: add `--verbose` or `-v` for extra debug output\n\n## Output\n\n### Progress Display\n```\n[Worker_1 ] video1.mp4                        [████████████░░░░░░░░░░░░░]  52.3% Transcoding\n[Worker_2 ] video2.avi                        [██████░░░░░░░░░░░░░░░░░░░]  24.7% Transcoding\n[Worker_3 ] video3.mkv                        [███████████████░░░░░░░░░]  65.1% Transcoding\n```\n\n### Processing Summary\n```\nProcessing complete!\nSuccessful: 145\nSkipped (low resolution): 23\nSkipped (likely larger): 8\nSkipped (larger after transcode): 5\nFailed: 2\nTotal: 183\n```\n\n### CSV Log Format\nThe `transcode_log.csv` file contains detailed processing information:\n\n| Column | Description |\n|--------|-------------|\n| filepath | Full path to the processed file |\n| status | Processing result (success, failed, skipped_*) |\n| timestamp | ISO timestamp of completion |\n| before_size_mb | Original file size in MB |\n| after_size_mb | Transcoded file size in MB |\n| compression_ratio | Size ratio (after/before) |\n\n## Skip Conditions\n\nThe script intelligently skips files in several scenarios:\n\n### Resolution-based Skips\n- `skipped_low_res_WIDTHxHEIGHT` - Video resolution below configured minimums\n\n### Codec-based Skips  \n- `skipped_likely_larger_low_bitrate_X_Mbps_for_WIDTHxHEIGHT` - Already efficient encoding\n- Files already using H.265, HEVC, or AV1 codecs\n\n### Size-based Skips\n- `skipped_larger_size_X.XXX` - Transcoded file would be larger than original\n\n## Troubleshooting\n\n### Common Issues\n\n**\"HandBrakeCLI not found\"**\n- Ensure HandBrakeCLI is installed and in your system PATH\n- Test with: `HandBrakeCLI --version`\n\n**\"ffprobe not found\"**\n- Ensure FFmpeg is installed and ffprobe is in your system PATH\n- Test with: `ffprobe -version`\n\n**Workers get stuck after pause/resume**\n- Check for HandBrake process suspension issues\n- Review debug output for specific worker problems\n- Consider restarting the script if workers remain unresponsive\n\n**High memory usage**\n- Reduce `MAX_WORKERS` if experiencing memory pressure\n- HandBrake processes can be memory-intensive for large files\n\n### Debug Information\n\nFor troubleshooting, disable progress bars to see detailed output:\n```python\nSHOW_PROGRESS = False\n```\n\nThis reveals:\n- Detailed HandBrake command execution\n- Process suspension/resume messages\n- Worker state transitions\n- Error details and return codes\n\n## Version History\n\n### v0.7.0 (Current)\n- Mapped HandBrake exit codes to human-readable reasons in failure output\n- Enhanced failure event line to include rc and explanation\n\n### v0.6.0\n- Added final move retry with exponential backoff (`FINAL_MOVE_RETRIES`, `FINAL_MOVE_RETRY_DELAY`, `FINAL_MOVE_BACKOFF_FACTOR`)\n- Enhanced network resilience features consolidated (UNC wait + finalization retries)\n- Documentation improvements and configuration section for reliability settings\n- Internal refactors / minor robustness fixes\n\n### v0.5.2\n- Separate failed runs into `transcode_failed_log.csv`\n- Added UNC network share wait/retry (configurable) to survive network adapter sleep\n- Added network recovery constants (`NETWORK_CHECK_INTERVAL`, `NETWORK_MAX_WAIT`, `NETWORK_RETRY_ENABLED`)\n- Added final move retry with exponential backoff (`FINAL_MOVE_RETRIES`, `FINAL_MOVE_RETRY_DELAY`, `FINAL_MOVE_BACKOFF_FACTOR`)\n- Internal refactors / minor robustness fixes\n\n### v0.5.1\n- Adds optional console clear/redraw around the pause menu for a crisper UI\n- Makes the pre-menu settle delay configurable via `MENU_SETTLE_MS`\n- Adds `--quiet`/`--verbose` flags to control console noise\n\n### v0.5.0\n- Reliable Ctrl+C pause menu on Windows via console control handler\n- HandBrakeCLI launched in a new process group so Ctrl+C doesn't kill it\n- Optional Windows process suspension during pause for true pauses\n- Interrupted jobs are logged as \"interrupted\" (they retry), not \"failed\"\n\n### v0.4.0\n- **Fixed** cancelled jobs being logged as 'failed' in CSV\n- **Improved** worker display ordering (always numerical)\n- **Enhanced** pause/resume reliability with better state validation\n- **Added** comprehensive debugging and error handling\n\n### v0.3.1\n- **Added** graceful shutdown vs immediate shutdown options\n- **Improved** worker thread naming (Worker_1, Worker_2, etc.)\n- **Fixed** progress bar alignment issues\n- **Enhanced** signal handling for better Ctrl+C behavior\n\n### v0.2.x\n- **Added** real-time HandBrake progress parsing\n- **Implemented** cross-platform compatibility\n- **Added** keyboard interrupt pause/resume functionality\n\n### v0.1.x\n- Initial release with basic transcoding functionality\n- Multi-threaded processing\n- CSV logging\n\n## Credits\n\n- Created by: Claude Sonnet 4 (through version v0.4.0)\n- Updated by: Chat GPT-5 (Preview) starting with v0.5.x\n\n## Contributing\n\nFeel free to submit issues, feature requests, or pull requests. When contributing:\n\n1. **Test thoroughly** with various video formats and scenarios\n2. **Maintain Windows compatibility** \n3. **Update documentation** for any new features\n4. **Follow existing code style** and commenting patterns\n\n## License\n\nThis project is provided as-is for personal and educational use. Please ensure you have appropriate rights to transcode any video files you process.\n\n## Acknowledgments\n\n- **HandBrake team** - For the excellent HandBrakeCLI transcoding engine\n- **FFmpeg team** - For the powerful ffprobe video analysis tool\n- **Python community** - For the robust standard library that makes this possible\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fe2m32%2Fhandbrake-batch-transcoder-win","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fe2m32%2Fhandbrake-batch-transcoder-win","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fe2m32%2Fhandbrake-batch-transcoder-win/lists"}