timothydodd/handbrake-scheduler
A .NET service that automatically monitors directories for video files and transcodes them using HandBrakeCLI with configurable scheduling, time windows, and network support.
HandBrake Scheduler
A .NET service that automatically monitors directories for video files and transcodes them using HandBrakeCLI with configurable scheduling, time windows, network support, and REST API for file uploads. Features both directory monitoring and web-based file upload capabilities with advanced job management.
Integration with AutoMk
HandbrakeScheduler integrates seamlessly with AutoMk to create an automated disc-to-library pipeline:
- AutoMk automatically rips Blu-ray/DVD discs using MakeMKV
- HandbrakeScheduler receives and transcodes the ripped MKV files
This integration enables hands-free processing from physical media to optimized video files ready for your Plex/media server.
Features
Core Processing
- Automatic Monitoring: Continuously monitors configured directories for new video files
- Web API Upload: REST API endpoints for file uploads with rich metadata support
- Time-Based Scheduling: Optional time windows for processing (e.g., only during off-hours)
- Advanced Job Queue: Persistent job queue with retry logic (up to 3 attempts) and status tracking
- Smart Temp File Management: Copies remote files locally for faster processing when space allows
- Progress Tracking: Real-time progress bars for file copying and transcoding operations
File Management
- Multi-Directory Support: Monitor multiple input/output directory pairs simultaneously
- Flexible File Filtering: Configurable file extensions, size limits, and recursive scanning
- Network Share Support: Works with UNC paths and network drives with credential management
- Source File Management: Optional deletion of source files after successful transcoding
- Cross-Platform Path Handling: Intelligent path normalization for Windows/Unix compatibility
API & Integration
- REST API Endpoints: File upload, job monitoring, and system control via HTTP
- Rich Media Metadata: Support for series/movie information, IMDB IDs, genres, and custom fields
- Health Checks: Built-in health monitoring endpoints
- Large File Support: Handles files up to 100GB via web upload
Monitoring & Logging
- Comprehensive Logging: Console and file logging with configurable levels
- Job Persistence: Jobs survive application restarts with automatic recovery
- Graceful Shutdown: Proper cleanup of processes and temporary files on exit
Prerequisites
- .NET 9.0 or later
- HandBrakeCLI executable
- Sufficient disk space for temporary files (when processing remote files)
- Network access for file upload functionality (if using web API)
Installation
-
Clone the repository
git clone https://github.com/timothydodd/handbrake-scheduler.git cd handbrake-scheduler -
Build the project
dotnet build --configuration Release
-
Download HandBrakeCLI
- Download from HandBrake's official website
- Extract and note the path to
HandBrakeCLIexecutable
Configuration
Create an appsettings.json file in the application directory:
{
"HandBrake": {
"HandBrakeCliPath": "/path/to/HandBrakeCLI",
"MonitoringEnabled": true,
"ScanIntervalMinutes": 10,
"EnableLogging": true,
"LogFilePath": "logs/handbrake.log",
"StartTime": "22:00:00",
"EndTime": "06:00:00",
"Username": "domain\\username",
"Password": "password",
"PersistencePath": "data",
"DefaultPreset": "HQ 1080p30 Surround",
"Folders": [
{
"InputPath": "/input/videos",
"OutputPath": "/output/transcoded",
"Preset": "Fast 1080p30",
"FileExtensions": [".mkv", ".avi", ".mp4", ".mov"],
"DeleteSource": false,
"UseTempFolder": true,
"RecursiveSearch": true,
"MaxFileSizeBytes": 21474836480,
"MinFileSizeBytes": 104857600
}
]
},
"FileTransfer": {
"IncomingDirectory": "incoming",
"MaxFileSizeBytes": 107374182400,
"MaxConcurrentProcessing": 2,
"ListenUrl": "http://localhost:5000"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"HandbrakeScheduler": "Debug"
}
}
}Configuration Options
HandBrake Settings
HandBrakeCliPath: Path to HandBrakeCLI executable (required)MonitoringEnabled: Enable continuous monitoring (default: true)ScanIntervalMinutes: How often to scan for new files (default: 10)StartTime/EndTime: Optional time window for processing (24-hour format)Username/Password: Credentials for network sharesEnableLogging: Enable file logging (default: true)LogFilePath: Custom log file pathPersistencePath: Directory for job queue persistence (default: "data")DefaultPreset: Default HandBrake preset for uploaded files
Folder Settings
InputPath: Directory to monitor for video files (required)OutputPath: Directory for transcoded files (required)Preset: HandBrake preset name (required)FileExtensions: Array of file extensions to processDeleteSource: Delete original files after successful transcodingUseTempFolder: Copy remote files to local temp for processingRecursiveSearch: Search subdirectories (default: true)MaxFileSizeBytes: Maximum file size to processMinFileSizeBytes: Minimum file size to process
FileTransfer Settings
IncomingDirectory: Directory for uploaded files (default: "incoming")MaxFileSizeBytes: Maximum upload file size in bytes (default: 100GB)MaxConcurrentProcessing: Number of concurrent processing jobs (default: 2)ListenUrl: Web API listening URL (default: "http://localhost:5000")
Usage
Running the Application
Development:
dotnet runProduction:
dotnet HandbrakeScheduler.dllIntegration with AutoMk
When receiving files from AutoMk, HandbrakeScheduler:
- Preserves Folder Structure: Uses the relative file path from AutoMk to maintain organization
- Routes by Media Type: Automatically selects appropriate HandBrake presets based on content type (Movie/TV)
- Maintains Metadata: Preserves movie titles, series information, and episode details
To receive files from AutoMk:
- Ensure HandbrakeScheduler is running on the configured port (default: 5000)
- Configure folder settings in
appsettings.jsonwith appropriate presets for Movies and TV content - AutoMk will automatically send completed rips via the
/uploadendpoint
Example folder configuration for AutoMk integration:
{
"HandBrake": {
"Folders": [
{
"InputPath": "incoming/Movies",
"OutputPath": "/output/Movies",
"Preset": "HQ 1080p30 Surround"
},
{
"InputPath": "incoming/TV Shows",
"OutputPath": "/output/TV Shows",
"Preset": "HQ 720p30 Surround"
}
]
}
}Web API Usage
The application provides REST API endpoints for file upload and monitoring:
Upload Files
# Upload a video file with metadata
curl -X POST http://localhost:5000/upload \
-F "metadata={\"OriginalFileName\":\"video.mkv\",\"FileSizeBytes\":1000000,\"MediaInfo\":{\"MediaType\":\"Movie\",\"MovieTitle\":\"Example Movie\"},\"TransferTimestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" \
-F "file=@/path/to/video.mkv"Monitor Jobs
# Check job queue status
curl http://localhost:5000/jobs
# List uploaded files
curl http://localhost:5000/files
# Health check
curl http://localhost:5000/health
# Stop processing (maintenance)
curl -X POST http://localhost:5000/stopRunning as a Service
Windows Service:
# Install as Windows Service
sc create "HandBrake Scheduler" binPath="C:\path\to\HandbrakeScheduler.exe"
sc start "HandBrake Scheduler"Linux Systemd Service:
Create /etc/systemd/system/handbrake-scheduler.service:
[Unit]
Description=HandBrake Scheduler Service
After=network.target
[Service]
Type=notify
ExecStart=/usr/local/bin/dotnet /path/to/HandbrakeScheduler.dll
Restart=always
RestartSec=10
User=handbrake
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl enable handbrake-scheduler
sudo systemctl start handbrake-schedulerDocker Support
Dockerfile:
FROM mcr.microsoft.com/dotnet/runtime:6.0
WORKDIR /app
COPY . .
RUN apt-get update && apt-get install -y handbrake-cli
ENTRYPOINT ["dotnet", "HandbrakeScheduler.dll"]Docker Compose:
version: '3.8'
services:
handbrake-scheduler:
build: .
volumes:
- ./config:/app/config
- ./input:/input
- ./output:/output
- ./logs:/app/logs
environment:
- HANDBRAKE__HandBrakeCliPath=/usr/bin/HandBrakeCLIHandBrake Presets
Common presets you can use:
Fast 1080p30- Quick encoding for 1080p contentH.264 MKV 1080p30- High quality 1080p MKVH.265 MKV 1080p30- HEVC encoding for smaller filesAndroid 1080p30- Mobile-optimized encoding
To see all available presets, run:
HandBrakeCLI --preset-listEnvironment Variables
You can override configuration using environment variables with the HANDBRAKE_ prefix:
export HANDBRAKE__HandBrakeCliPath="/usr/local/bin/HandBrakeCLI"
export HANDBRAKE__MonitoringEnabled="true"
export HANDBRAKE__StartTime="23:00:00"
export HANDBRAKE__EndTime="07:00:00"
export HANDBRAKE__FileTransfer__MaxFileSizeBytes="107374182400"
export HANDBRAKE__FileTransfer__ListenUrl="http://0.0.0.0:5000"Logging
The application provides comprehensive logging:
- Console Logging: Real-time status and progress information with color-coded levels
- File Logging: Detailed logs saved to configured file path
- Progress Bars: Visual progress indicators for file operations
- Structured Logging: JSON-formatted logs for easy parsing
- Custom Formatting: Timestamp, log level, and message formatting
Log levels can be configured per namespace in appsettings.json.
Job Management
The application includes advanced job management features:
- Persistent Queue: Jobs are saved to disk and survive application restarts
- Retry Logic: Failed jobs are automatically retried up to 3 times
- Status Tracking: Jobs track their status (Pending, Processing, Completed, Failed)
- Time Window Respect: Processing only occurs during configured time windows
- Concurrent Limiting: Configurable number of concurrent processing jobs
Media Metadata Support
The file upload system supports rich media metadata:
- Movie Information: Title, year, IMDB ID, genre, runtime
- TV Series Information: Series title, season, episode, episode title
- Custom Metadata: Additional key-value pairs for specialized use cases
- Automatic Organization: Files organized based on media type and metadata
Troubleshooting
Common Issues
HandBrakeCLI Not Found
Error: HandBrakeCLI not found at: /path/to/HandBrakeCLI
- Verify the path in
HandBrakeCliPathis correct - Ensure HandBrakeCLI has execute permissions
- Check if HandBrakeCLI is in your system PATH
Network Access Issues
Error: Access denied to network path
- Verify network credentials are correct
- Ensure the service account has network access
- Test network path access manually
Insufficient Disk Space
Warning: Insufficient disk space for temp copy
- Free up space in the temp directory
- Disable
UseTempFolderto process files directly - Adjust
MaxFileSizeBytesto filter large files
File Upload Issues
Error: File size exceeds maximum
- Check
FileTransfer.MaxFileSizeBytessetting (default: 100GB) - Verify network connectivity and timeout settings
- Ensure sufficient disk space in
IncomingDirectory
Permission Errors
Error: Access denied to output directory
- Ensure write permissions to output directories
- Check if output directories exist
- Verify service account permissions
Debug Mode
Run with debug logging:
dotnet run --environment DevelopmentOr set the log level in configuration:
{
"Logging": {
"LogLevel": {
"Default": "Debug"
}
}
}Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the MIT License file for details.
Complete Media Pipeline Example
When used together with AutoMk, you can create a fully automated media processing pipeline:
- Insert Disc: Place a Blu-ray or DVD in your drive
- AutoMk Rips: Automatically detects disc, rips with MakeMKV, identifies content via OMDB
- File Transfer: AutoMk sends the ripped MKV file to HandbrakeScheduler via HTTP
- Transcoding: HandbrakeScheduler queues and processes the file with appropriate presets
- Final Output: Transcoded file is saved to your media library with proper naming
This creates a hands-free workflow from physical disc to optimized media file, perfect for building or maintaining a Plex library.
Acknowledgments
- HandBrake for the excellent video transcoding engine
- ShellProgressBar for progress visualization
- Microsoft Extensions for hosting and configuration framework
- AutoMk for seamless disc ripping integration