Synchronize subtitle timestamps using an existing accurate transcription.
This tool takes timing from one subtitle file and text from another file, then produces a new .srt with both good timing and good text.
Input 1: SRT with good timestamps and lower-quality text
Input 2: TXT with good text, or SRT with good text but bad timestamps
Output: SRT with good text and good timestamps
Typical use case:
House.M.D.S08E12.10bit.x265.1080p.BluRay.Joy.srt
good timing, weaker text
House M.D. - 8x12 - Chase.HDTV.LOL.en.srt
better text, weaker timing
Output:
House M.D. - 8x12 - Chase.HDTV.LOL.en.synced.srt
better text + good timing
This build keeps the original SRT-Sync token-DP alignment idea, but adds a Windows-friendly GUI and practical subtitle cleanup.
Main features:
- compact drag-and-drop GUI
- optional Windows
.exebuild - app logo/icon
- real 0–100 progress bar
- processed/left DP-cell counter
- support for second input as either
.txtor.srt - local-rate gap placement for sentences present in the second file but missing in the timing file
- final wrapping of long subtitle lines into two readable SRT lines
The core alignment still follows the original algorithm:
1. Convert timing SRT into XML-like text with timestamp markers.
2. Tokenize both inputs.
3. Run the original full dynamic-programming token alignment.
4. Transfer timing markers to the better text.
5. Write a synced SRT.
The original DP recurrence is preserved:
cost0 = costs[x-1][y-1] + 0.99 * cost
cost1 = costs[x-1][y] + self.costT(toks1[x-1])
cost2 = costs[x][y-1] + self.costT(toks2[y-1])Sometimes the second file contains a sentence that is missing from the timing-corrected SRT.
Example:
Timing SRT:
00:11:57,000 --> 00:12:00,000
The matched line starts here.
Better-text SRT:
A missing sentence before it.
The matched line starts here.
In this case, the missing sentence should not be merged into the 00:11:57 subtitle.
This version does the following:
1. Detect target-only text from the original DP alignment.
2. Check whether it appears before or after the matched text.
3. If it appears before the matched line, check the gap before that line.
4. Estimate local milliseconds per word from nearby timing-SRT blocks.
5. Place the missing sentence ending at the matched line's start time.
So if the matched line starts near:
00:11:57
and the local speaking rate says the missing sentence needs about 12 seconds, it will be placed approximately as:
00:11:45,000 --> 00:11:57,000
A missing sentence before it.
After synchronization, long subtitle lines are split into two visual SRT lines.
Example:
1
00:00:01,000 --> 00:00:04,000
This is a long subtitle line
split into two readable lines.This uses a real newline inside the SRT block. It does not insert literal <br>, <b>, or </b> tags.
The split is chosen near the middle of the subtitle, preferring punctuation when possible.
On Windows, extract the package and run:
run_gui.batThen choose:
1. Correct timing SRT
2. Better text SRT/TXT
3. Output synced SRT
You can either drag files into the rectangular boxes or click the boxes to browse.
status
Show status messages.
trace
Print original token-pair trace.
This is very verbose and usually should stay off.
gap ms
Minimum real timing gap before missing text is inserted.
Default: 700
fallback ms/word
Fallback milliseconds per word if local speech rate cannot be estimated.
Default: 280
min words
Minimum number of words in target-only text before trying to create a new subtitle line.
Default: 3
wrap
Character target for splitting long subtitle text into two visual lines.
Default: 42
Use 0 to disable wrapping.
input 2
auto, srt, or txt.
auto is usually fine.
Basic usage:
python SrtSync.py timing.srt better_text.srtWith options:
python SrtSync.py timing.srt better_text.srt ^
--progress ^
--min-gap-ms 700 ^
--ms-per-token 280 ^
--min-target-missing-words 3 ^
--local-rate-window 6 ^
--wrap-chars 42 ^
--output synced.srtDisable gap insertion:
python SrtSync.py timing.srt better_text.srt --no-gap-fillDisable line wrapping:
python SrtSync.py timing.srt better_text.srt --wrap-chars 0Force second input format:
python SrtSync.py timing.srt better_text.srt --target-format srt
python SrtSync.py timing.srt better_text.txt --target-format txtRun:
build_FORCE_ICON.batThe executable will be created at:
dist\SRT-Sync.exe
If that fails, try:
build_FORCE_ICON_ONELINE.batDrag-and-drop uses tkinterdnd2.
When running from source, install it with:
pip install tkinterdnd2or run:
install_dragdrop.batWhen building the EXE using the included scripts, tkinterdnd2 is bundled automatically.
The original project also includes a transcription helper:
python transcribe.py data/KatyPerry-Firework.mp3 largeThis creates:
data/KatyPerry-Firework.mp3.srt
The transcription depends on Whisper and FFmpeg.
Install example:
pip install -U openai-whisper
sudo apt update && sudo apt install ffmpegOriginal Python version:
https://github.com/EtienneAb3d/SRT-Sync
Java version:
https://github.com/EtienneAb3d/WhisperTimeSync
WhisperHallu:
https://github.com/EtienneAb3d/WhisperHallu
karaok-AI:
https://github.com/EtienneAb3d/karaok-AI
ChatMate:
https://github.com/EtienneAb3d/ChatMate
Commercial/industrial AI linguistic projects:
https://cubaix.com
This build is meant for practical subtitle cleanup where one source has better timing and another source has better text.
It is not a semantic translator. It aligns text using token-level dynamic programming, so very different paraphrases may still need manual checking.