A Python CLI tool that uses audio alignment to retime SRT subtitles from TV recordings onto DVD timelines.
This tool solves the problem of subtitle timing mismatches when you have:
- DVD media files with accurate timing
- TV recording with subtitles but different timing (due to commercials, speed differences, etc.)
The tool analyzes the audio from both sources to create a piecewise time mapping, then retimes the TV subtitles to match the DVD timeline.
- Multiple matching algorithms:
- Basic MFCC correlation
- Hint-guided matching for known content
- Robust fingerprinting for challenging cases
- Audio-based alignment: Uses robust audio fingerprinting to match DVD and TV content
- Timing hints support: Optional YAML hints file for improved accuracy on known content
- Handles complex timing differences:
- Commercial insertions
- Speed differences (PAL speedup, etc.)
- Missing or censored sections
- Drift and timing variations
- Intelligent subtitle processing:
- Retimes matched content accurately
- Drops subtitles in TV-only regions (commercials)
- Flags uncertain matches for review
- Optionally splits subtitles at region boundaries
- Comprehensive reporting:
- Detailed JSON alignment report
- Human-readable summary
- Lists dropped and flagged subtitles
- Python 3.12 or higher
- FFmpeg (for audio extraction)
git clone <repository-url>
cd subtimer
pip install -e .pip install -e .[dev] # Include development dependenciessubtimer dvd_file.mkv tv_file.mkv subtitles.srtsubtimer dvd_file.mkv tv_file.mkv subtitles.srt --hints hints.yamlsubtimer dvd_file.mkv tv_file.mkv subtitles.srt -o output_directory/subtimer dvd_file.mkv tv_file.mkv subtitles.srt \
--output-srt retimed_subtitles.srt \
--hints timing_hints.yaml \
--matcher robust \
--sample-rate 22050 \
--chunk-duration 30.0 \
--min-correlation 0.3 \
--min-confidence 0.4 \
--drop-tv-only \
--flag-boundaries \
--verboseSupports any format that FFmpeg can decode:
- Video: MKV, MP4, AVI, MOV, etc.
- Audio: WAV, MP3, FLAC, AAC, etc.
- SRT format only (initial version)
- UTF-8 encoding recommended
The tool can use a YAML hints file for improved accuracy on known content:
episode_id: example_s09e01
dvd_events:
- { label: intro_start, time: "00:00:00" }
- { label: act_1_start, time: "00:00:25" }
- { label: act_2_start, time: "00:07:07" }
- { label: act_3_start, time: "00:15:15" }
- { label: credits_start, time: "00:21:55" }
tv_events:
- { label: intro_start, time: "00:00:05" }
- { label: act_1_start, time: "00:00:27" }
- { label: commercial_1_start, time: "00:06:52" }
- { label: act_2_start, time: "00:10:57" }
- { label: commercial_2_start, time: "00:19:03" }
- { label: act_3_start, time: "00:19:37" }
- { label: credits_start, time: "00:29:54" }- Auto-detects
hints.yamlin subtitle file directory - Use
--hints path/to/hints.yamlfor custom location - Greatly improves accuracy and performance for known content
The tool generates three output files:
- Retimed SRT (
*_retimed.srt): The main output with DVD-timed subtitles - Alignment JSON (
alignment.json): Detailed alignment data and processing results - Summary Report (
summary.txt): Human-readable processing summary
- Audio Extraction: Extracts and normalizes audio from both DVD and TV sources
- Feature Matching: Uses MFCC and spectral features to find matching audio segments
- Coarse Alignment: Identifies candidate matching regions using cross-correlation
- Refinement: Improves boundary precision using onset detection and optimization
- Time Mapping: Creates piecewise linear mapping between DVD and TV timelines
- Subtitle Retiming: Applies time mapping to convert subtitle timestamps
- Quality Control: Flags uncertain matches and handles special cases
DVD_FILE: DVD media file or extracted audioTV_FILE: TV media file or extracted audioSUBTITLE_FILE: TV-timed SRT subtitle file-o, --output-dir: Output directory (default: current directory)--output-srt: Custom output SRT filename--temp-dir: Temporary directory for working files
--sample-rate: Audio sample rate for processing (default: 22050)--cache/--no-cache: Enable/disable audio caching (default: enabled)
--matcher: Audio matching algorithm:basic,hints,robust(default: hints)--hints: Path to timing hints YAML file for guided matching--chunk-duration: Chunk size for matching in seconds (default: 30.0)--min-correlation: Minimum correlation threshold (default: 0.3)--min-confidence: Minimum confidence for retiming (default: 0.4)
--drop-tv-only/--keep-tv-only: Drop subtitles in TV-only regions (default: drop)--drop-unmatched/--keep-unmatched: Drop subtitles in unmatched regions (default: drop)--flag-boundaries/--no-flag-boundaries: Flag boundary-crossing subtitles (default: flag)--split-boundaries/--no-split-boundaries: Split subtitles at boundaries (default: no split)
-v, --verbose: Enable verbose logging--debug: Enable debug logging and preserve temp files
subtimer movie_dvd.mkv movie_tv_recording.mkv tv_subtitles.srtsubtimer pal_version.mkv ntsc_version.mkv pal_subs.srt --verbosesubtimer dvd_audio.wav tv_audio.wav subtitles.srt- Check that the files contain the same content
- Try lowering
--min-correlationthreshold - Ensure audio quality is reasonable
- Check that files aren't heavily compressed or corrupted
- Increase
--chunk-durationfor longer content - Adjust
--min-confidencethreshold - Try different
--sample-rate(22050 or 16000)
- Review alignment quality in
alignment.json - Use
--keep-tv-onlyand--keep-unmatchedto preserve more subtitles - Check
summary.txtfor specific issues
- Use
--cacheto avoid re-extracting audio - Lower
--sample-ratefor faster processing - Process shorter segments if memory is limited
pytestblack src/ tests/
ruff check src/ tests/mypy src/The codebase is organized into specialized modules:
media_io.py: FFmpeg integration and media file handlingaudio_prep.py: Audio preprocessing and normalizationmatcher.py: Coarse audio matching using fingerprintsrefiner.py: Boundary refinement and precision improvementalignment_map.py: Time mapping data structures and conversionsubtitle_io.py: SRT parsing and writingretime.py: Subtitle retiming logic and special case handlingreport.py: JSON and text report generationcli.py: Command-line interface
- SRT subtitles only (no ASS/SSA support)
- No GUI (command-line only)
- No subtitle OCR (requires text subtitles)
- No automatic scene reordering detection
- Single-threaded processing
[Add your license here]
[Add contribution guidelines here]