SRT Aligner
Use this skill to turn a final script plus audio or a rough timed subtitle file into a clean .srt subtitle file.
For the user's Jianying/CapCut workflow, prefer the continuous mode below when they provide:
- A rough SRT generated by ASR.
- A correct final manuscript or correct line-broken subtitle copy.
- Requirements like
每一行文本对应一条字幕, 无标点, 字幕之间不要有空白, max_gap_between_cues_sec = 0, 无重叠, or 每行不超过17字.
If the user only provides a line-broken subtitle text and asks to process long lines, do not generate SRT. Run the line-only mode below: preserve existing short lines, remove punctuation, and split only lines longer than the requested character limit.
Workflow
- Collect inputs:
- Audio/video file path.
- Final script/copy text, preferably as
.txt or pasted text saved to a file.
- Output filename, defaulting to the audio basename plus
.srt.
- Get timing data from the audio:
- Strongly prefer Whisper JSON with word timestamps, such as
segments[].words[].
- If no timed transcript exists yet, use the local ASR/video subtitle workflow and request word timestamps whenever the tool supports it.
- If only segment timestamps or an existing
.srt are available, the script can still produce a best-effort result, but it must be treated as review-needed.
- For every Jianying/CapCut narration draft, default to
scripts/align_continuous_srt.mjs. Do not wait for the user to repeat “字幕填满” or “无空白”.
- Use
scripts/align_srt.mjs only when the user explicitly wants natural silent gaps or the output is not intended for Jianying/CapCut continuous captions.
- Read the generated report before calling the SRT final:
timingMode: "word" is the preferred mode.
timingMode: "segment-text" means segment text was used as pseudo word timing.
timingMode: "segment-proportional" means the result is rough timing only.
- Check
weakCues and estimatedCues; these are the subtitles most likely to need manual review.
- Inspect the SRT for obvious timing/text problems:
- Empty subtitles.
- Overlong lines.
- Large gaps caused by unmatched text.
- Garbled ASR words leaking into the final script. The output text should come from the user script, not the raw ASR transcript.
- Save the final
.srt in the requested output location and mention whether the report found weak cues.
Line-Only Text Mode
Use this when the user provides only 分行字幕 / pasted subtitle text and asks to handle lines over 17 characters. This mode does not need audio or SRT.
node scripts/optimize_line_breaks.mjs `
--script line-broken-copy.txt `
--out optimized-lines.txt `
--max-chars 17
Line-only mode:
- Preserves user-provided short lines as-is after punctuation/space cleanup.
- Splits only lines longer than
--max-chars.
- Prefers semantic split points such as
或者, 并且, 但是, 所以, 因为, 如果, 甚至, 而是, 就是, 以及, and 和.
- Avoids leaving obvious function words at line tails or heads when a nearby split is available.
- Writes a
.qa.json beside the output with line count, max length, over-limit lines, blank lines, and punctuation issues.
If the user later provides audio and a rough SRT, feed the optimized line file into continuous mode with --keep-lines.
Jianying Continuous Mode
Use this mode for long Chinese narration when the final subtitle must import into Jianying without visible blank spaces between cues.
node scripts/align_continuous_srt.mjs `
--script final-copy.txt `
--timed rough-asr.srt `
--out final-continuous.srt `
--max-chars 17
If the script is already correctly line-broken and each line must become exactly one subtitle cue, add:
--keep-lines
Default behavior is repair/optimize the user's line-broken copy first, then align timing. Do not add --keep-lines unless the user explicitly asks to preserve their exact line breaks without repairs.
Continuous mode does all of these:
- Uses the user's final script as subtitle text and uses rough SRT/ASR only for timing.
- Removes punctuation from subtitle text.
- Uses the user's pasted line breaks as the primary structure when the input already looks like line-broken subtitle copy.
- Treats manuscript line breaks as soft boundaries, so a word or sentence split across two pasted lines can be repaired locally before timing alignment.
- Avoids full-script reflow for line-broken subtitle copy; it only repairs suspicious adjacent boundaries unless the input is a long unbroken manuscript.
- Keeps each subtitle cue at or below
--max-chars.
- Preserves one input line as one subtitle only when
--keep-lines is provided.
- Uses Chinese word segmentation plus protected phrases to avoid splitting one word across cue boundaries.
- When
jieba is available, continuous mode uses it as the primary Chinese dictionary layer, then derives subtitle-safe phrase blocks from the token stream. This helps keep phrases such as 人与人之间, 并不友好的女人, 择偶策略, 远古时期, and 情绪状态 from being split awkwardly.
- The jieba layer also derives limited collocation blocks, such as
社会道德绑架, 给你灌输, and 精密运转, so the line breaker avoids splitting common noun-action and modifier-action structures.
- Uses a dedicated character-level global aligner for long Chinese narration, so repeated phrases are less likely to jump to the wrong later occurrence.
- Computes cue boundaries from the previous line's last matched character and the next line's first matched character, which is more stable when rough SRT has local ASR errors.
- Protects common relationship-copy phrases and fixed expressions such as
主动权, 情绪价值, 思维导图, 游刃有余, 吸血鬼, 两性博弈, 道德评价体系, and 心理学机制 from bad line splits, while also using generic Chinese word boundaries for unseen words.
- Adds a semantic compound layer above the default Chinese tokenizer, so noun phrases such as
择偶策略, 远古时期, 现代社会, 普通男人, and 双重生存策略 stay together even when the platform tokenizer splits them into smaller pieces.
- Avoids leaving Chinese function words or measure words at bad line edges, such as splitting
一个, 就是, or X的.
- Repairs common phrase and sentence-anchor collisions inside one subtitle line, such as
游刃有余为什么因为..., by splitting short logic anchors like 为什么, 因为, 只要, 如果, 但是, 所以, and 以及 into cleaner cue boundaries when the split is locally safe.
- Runs a final line-edge pass for Chinese particles, so subtitles do not start with orphaned fragments like
的... or 起来... when the previous line can donate the needed word group without exceeding --max-chars.
- Forces adjacent cues to touch exactly: previous
end equals next start.
- Writes a
.qa.json report checking line count, blank text, punctuation, overlaps, max gap, max characters per cue, and line-break QA issues.
Useful segmentation options:
--segmenter jieba
Requires python3 -m pip install --user jieba. If --segmenter jieba is requested and jieba is unavailable, the script fails clearly. With the default --segmenter auto, it uses jieba when installed and falls back to the built-in tokenizer otherwise.
For the user's current standard, the QA target is:
blank_text: 0
punctuation_issues: 0
overlaps: 0
max_gap_between_cues_sec: 0
lineCountMatches: true
max_chars_per_cue <= 17
lineQa.summary.totalIssues: 0 or manually reviewed
Downstream Video-Skill Handoff
Before an SRT is handed to shuping-ziranliu, hengban-ziranliu, or jiepai-jianji, require all of the following:
- Adjacent subtitle cues touch exactly: previous
end equals next start.
- The first cue starts at the intended narration start.
- The final cue ends at the narration end; a sub-frame encoder tail is acceptable only when verified as inaudible.
blank_text = 0, overlaps = 0, and max_gap_between_cues_sec = 0.
- The subtitle text comes from the final manuscript; ASR supplies timing only.
If a downstream draft already exists and its source subtitle track contains micro-gaps, do not patch an opened/encrypted Jianying timeline in place. Rebuild a new draft from a clean source or a copy. Fill ordinary narration gaps by extending the preceding cue to the next cue start. Preserve only deliberate non-narration sections introduced by the editing workflow, such as the 1.833333-second gear bridge in shuping-ziranliu.
Alignment Script
Use the bundled Node script:
node scripts/align_srt.mjs --script copy.txt --timed whisper.json --out output.srt
Useful options:
node scripts/align_srt.mjs `
--script copy.txt `
--timed whisper.json `
--out output.srt `
--report output.report.json `
--max-chars 30 `
--min-duration 0.8 `
--max-duration 5.5
Supported timed inputs:
- Whisper-style JSON:
{ "segments": [{ "start": 0, "end": 1.2, "text": "...", "words": [{ "word": "...", "start": 0, "end": 0.3 }] }] }
- Whisper segment JSON without word timestamps.
- Existing
.srt files, used as segment-level timing fallback.
Continuous mode is especially useful with existing rough .srt files because it can turn a noisy ASR subtitle into a clean final subtitle while preserving the rough timing skeleton.
Heuristics
- Keep Chinese subtitle chunks around 18-30 characters unless the user asks otherwise.
- Keep English subtitle chunks around 42-70 characters.
- Prefer splitting at
。!?;,、,.!?;: and line breaks.
- When the final script differs slightly from ASR, trust the user's script for subtitle text and use ASR only for timing.
- The aligner now uses global token matching for word timestamps, so skipped words, repeated phrases, and short ASR insertions should not push the whole SRT off track.
- If word timestamps are missing but segment text exists, it distributes segment time across segment tokens and performs global matching against that pseudo timing.
- If only empty segment timing exists, it distributes script chunks across the full segment duration by character count and marks all cues as estimated.
- If alignment confidence looks poor, tell the user and provide the best-effort SRT plus the report path.
- For long Chinese rough-SRT alignment, if confidence is unexpectedly poor, prefer continuous mode first. It has its own character-level report and
weakCues list for local review.
Output
Return:
- The
.srt file path.
- The
.report.json file path.
- The timing source used: word timestamps, segment text pseudo timing, or proportional fallback.
- Whether
weakCues / estimatedCues need review.
1---2name: srt-aligner3description: Match a user-provided script/copy with an audio file or timed transcript and generate clean SRT subtitles. Use when the user says they will provide 文案 and 音频, asks to 匹配文案和音频, generate SRT, create subtitles from a script, align narration copy to audio, or convert ASR/Whisper output into polished subtitle files.4---56# SRT Aligner78Use this skill to turn a final script plus audio or a rough timed subtitle file into a clean `.srt` subtitle file.910For the user's Jianying/CapCut workflow, prefer the continuous mode below when they provide:1112- A rough SRT generated by ASR.13- A correct final manuscript or correct line-broken subtitle copy.14- Requirements like `每一行文本对应一条字幕`, `无标点`, `字幕之间不要有空白`, `max_gap_between_cues_sec = 0`, `无重叠`, or `每行不超过17字`.1516If the user only provides a line-broken subtitle text and asks to process long lines, do not generate SRT. Run the line-only mode below: preserve existing short lines, remove punctuation, and split only lines longer than the requested character limit.1718## Workflow19201. Collect inputs:21 - Audio/video file path.22 - Final script/copy text, preferably as `.txt` or pasted text saved to a file.23 - Output filename, defaulting to the audio basename plus `.srt`.242. Get timing data from the audio:25 - Strongly prefer Whisper JSON with word timestamps, such as `segments[].words[]`.26 - If no timed transcript exists yet, use the local ASR/video subtitle workflow and request word timestamps whenever the tool supports it.27 - If only segment timestamps or an existing `.srt` are available, the script can still produce a best-effort result, but it must be treated as review-needed.283. For every Jianying/CapCut narration draft, default to `scripts/align_continuous_srt.mjs`. Do not wait for the user to repeat “字幕填满” or “无空白”.294. Use `scripts/align_srt.mjs` only when the user explicitly wants natural silent gaps or the output is not intended for Jianying/CapCut continuous captions.305. Read the generated report before calling the SRT final:31 - `timingMode: "word"` is the preferred mode.32 - `timingMode: "segment-text"` means segment text was used as pseudo word timing.33 - `timingMode: "segment-proportional"` means the result is rough timing only.34 - Check `weakCues` and `estimatedCues`; these are the subtitles most likely to need manual review.356. Inspect the SRT for obvious timing/text problems:36 - Empty subtitles.37 - Overlong lines.38 - Large gaps caused by unmatched text.39 - Garbled ASR words leaking into the final script. The output text should come from the user script, not the raw ASR transcript.407. Save the final `.srt` in the requested output location and mention whether the report found weak cues.4142## Line-Only Text Mode4344Use this when the user provides only 分行字幕 / pasted subtitle text and asks to handle lines over 17 characters. This mode does not need audio or SRT.4546```powershell47node scripts/optimize_line_breaks.mjs `48 --script line-broken-copy.txt `49 --out optimized-lines.txt `50 --max-chars 1751```5253Line-only mode:5455- Preserves user-provided short lines as-is after punctuation/space cleanup.56- Splits only lines longer than `--max-chars`.57- Prefers semantic split points such as `或者`, `并且`, `但是`, `所以`, `因为`, `如果`, `甚至`, `而是`, `就是`, `以及`, and `和`.58- Avoids leaving obvious function words at line tails or heads when a nearby split is available.59- Writes a `.qa.json` beside the output with line count, max length, over-limit lines, blank lines, and punctuation issues.6061If the user later provides audio and a rough SRT, feed the optimized line file into continuous mode with `--keep-lines`.6263## Jianying Continuous Mode6465Use this mode for long Chinese narration when the final subtitle must import into Jianying without visible blank spaces between cues.6667```powershell68node scripts/align_continuous_srt.mjs `69 --script final-copy.txt `70 --timed rough-asr.srt `71 --out final-continuous.srt `72 --max-chars 1773```7475If the script is already correctly line-broken and each line must become exactly one subtitle cue, add:7677```powershell78--keep-lines79```8081Default behavior is **repair/optimize the user's line-broken copy first, then align timing**. Do not add `--keep-lines` unless the user explicitly asks to preserve their exact line breaks without repairs.8283Continuous mode does all of these:8485- Uses the user's final script as subtitle text and uses rough SRT/ASR only for timing.86- Removes punctuation from subtitle text.87- Uses the user's pasted line breaks as the primary structure when the input already looks like line-broken subtitle copy.88- Treats manuscript line breaks as soft boundaries, so a word or sentence split across two pasted lines can be repaired locally before timing alignment.89- Avoids full-script reflow for line-broken subtitle copy; it only repairs suspicious adjacent boundaries unless the input is a long unbroken manuscript.90- Keeps each subtitle cue at or below `--max-chars`.91- Preserves one input line as one subtitle only when `--keep-lines` is provided.92- Uses Chinese word segmentation plus protected phrases to avoid splitting one word across cue boundaries.93- When `jieba` is available, continuous mode uses it as the primary Chinese dictionary layer, then derives subtitle-safe phrase blocks from the token stream. This helps keep phrases such as `人与人之间`, `并不友好的女人`, `择偶策略`, `远古时期`, and `情绪状态` from being split awkwardly.94- The jieba layer also derives limited collocation blocks, such as `社会道德绑架`, `给你灌输`, and `精密运转`, so the line breaker avoids splitting common noun-action and modifier-action structures.95- Uses a dedicated character-level global aligner for long Chinese narration, so repeated phrases are less likely to jump to the wrong later occurrence.96- Computes cue boundaries from the previous line's last matched character and the next line's first matched character, which is more stable when rough SRT has local ASR errors.97- Protects common relationship-copy phrases and fixed expressions such as `主动权`, `情绪价值`, `思维导图`, `游刃有余`, `吸血鬼`, `两性博弈`, `道德评价体系`, and `心理学机制` from bad line splits, while also using generic Chinese word boundaries for unseen words.98- Adds a semantic compound layer above the default Chinese tokenizer, so noun phrases such as `择偶策略`, `远古时期`, `现代社会`, `普通男人`, and `双重生存策略` stay together even when the platform tokenizer splits them into smaller pieces.99- Avoids leaving Chinese function words or measure words at bad line edges, such as splitting `一个`, `就是`, or `X的`.100- Repairs common phrase and sentence-anchor collisions inside one subtitle line, such as `游刃有余为什么因为...`, by splitting short logic anchors like `为什么`, `因为`, `只要`, `如果`, `但是`, `所以`, and `以及` into cleaner cue boundaries when the split is locally safe.101- Runs a final line-edge pass for Chinese particles, so subtitles do not start with orphaned fragments like `的...` or `起来...` when the previous line can donate the needed word group without exceeding `--max-chars`.102- Forces adjacent cues to touch exactly: previous `end` equals next `start`.103- Writes a `.qa.json` report checking line count, blank text, punctuation, overlaps, max gap, max characters per cue, and line-break QA issues.104105Useful segmentation options:106107```powershell108--segmenter jieba109```110111Requires `python3 -m pip install --user jieba`. If `--segmenter jieba` is requested and jieba is unavailable, the script fails clearly. With the default `--segmenter auto`, it uses jieba when installed and falls back to the built-in tokenizer otherwise.112113For the user's current standard, the QA target is:114115- `blank_text: 0`116- `punctuation_issues: 0`117- `overlaps: 0`118- `max_gap_between_cues_sec: 0`119- `lineCountMatches: true`120- `max_chars_per_cue <= 17`121- `lineQa.summary.totalIssues: 0` or manually reviewed122123## Downstream Video-Skill Handoff124125Before an SRT is handed to `shuping-ziranliu`, `hengban-ziranliu`, or `jiepai-jianji`, require all of the following:126127- Adjacent subtitle cues touch exactly: previous `end` equals next `start`.128- The first cue starts at the intended narration start.129- The final cue ends at the narration end; a sub-frame encoder tail is acceptable only when verified as inaudible.130- `blank_text = 0`, `overlaps = 0`, and `max_gap_between_cues_sec = 0`.131- The subtitle text comes from the final manuscript; ASR supplies timing only.132133If a downstream draft already exists and its source subtitle track contains micro-gaps, do not patch an opened/encrypted Jianying timeline in place. Rebuild a new draft from a clean source or a copy. Fill ordinary narration gaps by extending the preceding cue to the next cue start. Preserve only deliberate non-narration sections introduced by the editing workflow, such as the 1.833333-second gear bridge in `shuping-ziranliu`.134135## Alignment Script136137Use the bundled Node script:138139```powershell140node scripts/align_srt.mjs --script copy.txt --timed whisper.json --out output.srt141```142143Useful options:144145```powershell146node scripts/align_srt.mjs `147 --script copy.txt `148 --timed whisper.json `149 --out output.srt `150 --report output.report.json `151 --max-chars 30 `152 --min-duration 0.8 `153 --max-duration 5.5154```155156Supported timed inputs:157158- Whisper-style JSON: `{ "segments": [{ "start": 0, "end": 1.2, "text": "...", "words": [{ "word": "...", "start": 0, "end": 0.3 }] }] }`159- Whisper segment JSON without word timestamps.160- Existing `.srt` files, used as segment-level timing fallback.161162Continuous mode is especially useful with existing rough `.srt` files because it can turn a noisy ASR subtitle into a clean final subtitle while preserving the rough timing skeleton.163164## Heuristics165166- Keep Chinese subtitle chunks around 18-30 characters unless the user asks otherwise.167- Keep English subtitle chunks around 42-70 characters.168- Prefer splitting at `。!?;,、,.!?;:` and line breaks.169- When the final script differs slightly from ASR, trust the user's script for subtitle text and use ASR only for timing.170- The aligner now uses global token matching for word timestamps, so skipped words, repeated phrases, and short ASR insertions should not push the whole SRT off track.171- If word timestamps are missing but segment text exists, it distributes segment time across segment tokens and performs global matching against that pseudo timing.172- If only empty segment timing exists, it distributes script chunks across the full segment duration by character count and marks all cues as estimated.173- If alignment confidence looks poor, tell the user and provide the best-effort SRT plus the report path.174- For long Chinese rough-SRT alignment, if confidence is unexpectedly poor, prefer continuous mode first. It has its own character-level report and `weakCues` list for local review.175176## Output177178Return:179180- The `.srt` file path.181- The `.report.json` file path.182- The timing source used: word timestamps, segment text pseudo timing, or proportional fallback.183- Whether `weakCues` / `estimatedCues` need review.