Subtitles
This is a standalone task, not part of a process. Execute it whenever the user requests—right after editing, or again after deleting a few lines.
It has only one prerequisite: the edit list already exists. Not because it comes after editing, but without the edit list, it can't know which lines are retained and their exact timings in the final video.
text
Requires edit-list.json (edit list), transcript.json (word-by-word transcript)
Produces subtitles.json
Stop once completed, do not guide the user on next steps.
First read and execute the Business Skill Phase Contract, with criteria based on Subtitle Proofreading Rules, and proper noun conventions from the AI Term Dictionary.
Who Decides What
This is the foundation for all subsequent steps.
text
Voiceover editing decides "which lines to keep and when" ← The only source of truth for timings
Subtitles decides "what text appears on screen" ← The only source of truth for display
Each subtitle screen stores a list of word IDs + display text, no timestamps. Timings are calculated from the edit list every time. This ensures no discrepancies between the two data sources, and invalidations can be pinpointed to specific screens: "Words in screens 7 and 12 have been cut", instead of the unactionable "subtitles may be outdated".
Storing independent text for subtitles is intentional. Transcripts answer "what was said", while subtitles answer "what should be shown"—punctuation, removed filler words, and official proper noun spellings should naturally differ. Forcing a single string to serve both purposes would make it impossible to add commas to subtitles.
0. Readiness Check
First perform the "readiness check" from
Check for Updates—verify if skills are up-to-date and if the Runtime is compatible; the
plugin root is also located there (replace
in commands with the actual path). Proceed only if "ready"; follow the instructions for "new session required" or "stop" (including the "forbid custom alternative interfaces" rule), as business Skills do not include their own environment logic.
If the readiness result is
runtime.kind=desktop-managed
, directly reuse the stable CLI and the same
service installed by the desktop App; do not parse the Electron path, install additional dependencies, or start a second Runtime.
1. Entry Assertions
bash
node "<plugin root>/scripts/ensure-running.cjs" --json
node "<plugin root>/scripts/videocut-cli.cjs" inspect "<project directory>" --json
| Assertion | Action if not met |
|---|
| exists and contains segments | Clearly inform the user that the edit list is missing, and ask them to start voiceover editing first. Do not perform editing yourself. |
| exists | The project is not ready; stop. Do not create a transcript yourself. |
Do not assert the existence of , nor perform transcription. Subtitles do not need either—see the next section.
2. Text Correction: Dictionary First, Script Second
No re-transcription needed. The original word-by-word transcript already has timestamps, and the edit list knows which segments are retained—the timing of each word in the final video is calculated, not re-transcribed:
text
Word's timing in source video Available in transcript
Retained segments Available in edit list
Word's timing in final video Calculated from the above two
Re-running ASR would just re-listen to the same content, wasting time and money, and producing worse results—proper nouns would need to be corrected again. (
is a legacy from the previous design, where subtitles intended to get timestamps by transcribing the edited video. This issue was resolved after subtitles were anchored to word IDs.
Do not use it for subtitle creation.)
Both tools are required.
bash
# Dictionary: Fixed spellings for this speaker, no evidence needed
node "<plugin root>/scripts/videocut-cli.cjs" transcript dictionary "<project directory>" --dictionary "<plugin root>/references/ai-term-dictionary.md" --json
# Script: Only execute if the author has a script, requires evidence for each change
node "<plugin root>/scripts/videocut-cli.cjs" transcript align "<project directory>" --script "<voiceover script file>" --json
text
Dictionary Always uses fixed spellings Ignores context, applies changes directly, and lists all modifications
Script Only applies spellings when context matches Requires evidence for each change; reports "unable to confirm" for mismatches, does not guess
Why a dictionary is mandatory, even with a script: Voiceovers may be re-recorded. In real projects, the same line may be recorded four times, leading to conflicting contexts like "connect fork" and "fork is", where align can only report "unable to confirm"—it follows rules and does not guess, because misspelling a name is worse than mishearing it. It may only correct one out of three instances of "fork".
A dictionary avoids this issue: in this speaker's content, "fork" is "X".
There is only one dictionary, located at the plugin level
references/ai-term-dictionary.md
: it modifies the transcript, which is shared by voiceover editing and subtitles. Do not create a separate dictionary under this skill.
Review the change list after correction. The dictionary ignores context, so it may make mistakes—for example, normalizing the speaker's actual utterance "Skills" (Claude Skills, plural proper noun) to "Skill". If you see errors, modify the dictionary instead of patching the command.
only reports proposals without applying them. To apply the proposals, convert
to
and run:
bash
node "<plugin root>/scripts/videocut-cli.cjs" transcript correct "<project directory>" --file "<correction file>" --json
After correcting the transcript,
subtitle screens referencing these words will be updated automatically, returning
. Unmodifiable entries (lines that have been manually rewritten) will be added to
and reported for review, no guessing involved.
If neither the dictionary nor the script provides a confirmed correct spelling, do not guess. Report it to the user and ask them to update the dictionary—updating the dictionary will automatically fix it for the next video, while guessing requires repeated corrections.
3. Split into Screens
bash
node "<plugin root>/scripts/videocut-cli.cjs" subtitle build "<project directory>" --json
Four rules, applied in order:
text
① Removed content The remaining segments are adjacent on the timeline but semantically unrelated.
Removing "silence" does not count — cutting a pause in the middle of a sentence should not split the sentence.
② Any punctuation Provided by Volcano, includes periods and commas — **same granularity as voiceover editing segmentation**,
breaks at the same positions. Punctuation takes priority over all timing evidence: speakers may speak two sentences without pausing, or pause in the middle of a sentence.
③ Paragraph boundaries + pauses **Only used if the word has no punctuation**. This is for "guessing sentence endings by paragraphs when there's no punctuation";
if there is punctuation, rules ② and comma-based segmentation apply — they consider screen length, while rule ③ does not.
(Triggering rule ③ on punctuation boundaries increased screen count from 40 to 43 in real projects, creating more fragmented screens)
④ Long pauses heard by viewers To split within a sentence, a longer silence is required.
Voiceover editing and subtitles share the same punctuation and segmentation granularity: one comma per segment / screen.
Fragments (one or two words) will be merged, but never across periods — "You see" starts a new sentence, not the end of the previous one; merging forward would result in "...call Grok CLI you see", mixing two sentences.
Short sentences spoken quickly by the speaker will be retained (e.g., "Every morning" and "Execute task" each lasting 0.6 seconds in real projects). This is how the speaker actually spoke, no alert needed. Using one comma per screen will inevitably produce such screens; alerting for this would be equivalent to alerting for normal speech—too many alerts will be ignored.
Remaining text longer than one screen will be evenly split into multiple screens, one line per screen. If splitting creates one or two-word fragments, it indicates the boundary in rule ② is not actually a period; merge the fragment back into the previous screen.
The command returns four items, all of which need review:
text
stale Screens affected by editing — specifies exact screen numbers and lost words
tooFast Too many words, insufficient time to read
transcriptMoved The transcript has been modified since last use
When Subtitles Already Exist — Stop and Ask
Without
, the command will refuse to run.
This is the only step in this skill that requires user consent, because
overwrites manual screen splits and wording that users spent time on, which cannot be recovered automatically.
text
User wants to modify a few words Do not run build. Ask them to edit directly in Studio, or specify which screens to modify.
User wants to start over Confirm before adding --replace.
4. Review: Screen-by-Screen in Studio
bash
node "<plugin root>/scripts/videocut-cli.cjs" open "<project directory>" --json
After opening, switch to the "Subtitles" tab in the left panel. One line per screen: left side shows serial number and timing, right side shows text; click to edit directly.
- Enter = Split into a new screen from the cursor position
- Backspace at line start = Merge with the previous screen
- Select one of the four presets in the right panel "Settings → Subtitles" for consistent styling across the entire video
- Subtitles are directly visible on the screen; position and font size are proportional to the video — preview and final video use the same settings
During review, at least confirm: proper nouns are correct, no missing words, sentence breaks are natural, and each screen stays long enough to read.
5. Stop at
This task is completed. Do not perform physical cutting, storyboarding, animation, or video rendering, and do not urge the user on next steps.
Reports must be separated: Product structured readback is API/readback PASS; real browser frame review for the same project is visual frame PASS; if no one has verified that subtitles match the video, it is human listening UNVERIFIED — do not use DOM, screenshots, or file detection as substitutes.
Boundary: Burning Subtitles into Video is Not Part of This Task
The delivery method is
burning into video, which is handled during the export phase. The output of subtitles is
— all dimensions are percentages of the video frame, and export will convert them to pixels based on the output resolution, using the same settings on both sides.
The mp4 exported today will not include subtitles, as that step has not been performed. Clearly state this consequence in the report; do not just say "subtitles are ready" — users will assume subtitles are included in the final video.
Recovery and Failure Handling
- : Subtitles already exist. Ask first, do not use directly.
- : Another process is writing to the file. Re-read, do not overwrite automatically.
- Dictionary reports "unable to parse line N": This is a malformed table row. Rules only recognize table rows (
| Correct spelling | Common misrecognitions |
); prose and lists are silently ignored.
- reports "must not change any word id, time or gap flag": The correction proposal includes timing changes. Only modify text.
- : Do not loop reinstallation.
- For any failure, do not claim "transcription completed" as "subtitles ready". ASR output is raw material, not the final product.