Fully Automated Video Editing for Talking-Head Videos (No CapCut Route)
What Problem Does This Solve?
After a user finishes recording a talking-head video, this skill automates the entire chain: transcription → error correction → silence removal → stutter/repeat deletion → mistake correction with overlay → final render. The entire process runs without ever opening CapCut. The output is a directly publishable video (hard-burned subtitles + top-of-frame yellow correction bars).
To change any parameter (font size, cut segments, text) modify the values and rerun the script; iteration cost is about one minute.
Boundary with jianying-subtitle-fixer: That tool modifies CapCut drafts (user must export manually); this skill outputs a final video directly via ffmpeg. If the user doesn't mention CapCut, use this skill.
Environment Dependencies (Already Set Up Locally)
- Python:
C:\Users\44162\AppData\Local\Programs\Python\Python312\python.exe(faster-whisper 1.2.1 + torch installed; models cached in ~/.cache/huggingface, includes 'small') - ffmpeg:
D:\software\ffmpeg\bin\ffmpeg.exe(auto-detected by scripts)
Standard Workflow (AI Follow This)
Step 0 ffprobe to get video duration/resolution (for adaptive font sizing later)
Step 1 Transcription: transcribe.py -> raw.json (sentence + word timestamps)
Step 2 AI Analysis (core value of this skill, see below) -> write cut_plan.json
Step 3 AskUserQuestion for all content deletion decisions (ask everything at once, not one by one)
Step 4 Render: render.py --plan cut_plan.json -> final video
Step 5 Frame-sampling quality check (extract one frame per correction segment, Read + visual check for text completeness and no overflow)
Step 6 Delivery: report what was cut, what was corrected, and file location
Step 1 Transcription Command
& "C:\Users\44162\AppData\Local\Programs\Python\Python312\python.exe" "<skill>/scripts/transcribe.py" --video "<video path>" --outdir "<working dir>" --prompt "Chinese technical tutorial about XXX, YYY and other topics"
--prompt should use the video topic + high-frequency terminology (fetched from term list ~/.claude/skills/jianying-subtitle-fixer/config/terms.json).
This significantly improves hit rate for proper nouns.
Suggested working directory: D:\ContentProduction\Editing\workspace\<date-job>\.
Step 2 AI Analysis (Irreplaceable Human Step, Methodology in references/cut-heuristics.md)
After reading the full raw.json, produce four things:
- Subtitle correction fixed: Correct homophone errors and misheard terms line by line. Keep the original spoken style; only fix errors, do not polish (subtitles are tied to audio; rewriting would cause mismatch). See references for common whisper mishearing patterns.
- Content cuts content_cuts: Entire sections to delete (timestamps + reason), with types and judgment criteria in references. For word-level repeats (e.g., "I posted... I posted" within a sentence), use word timestamps for precise positioning.
- deleted_ids: IDs of subtitle lines covered by content_cuts (these lines will not appear in subtitles).
- Corrections corrections: Paragraphs with factual errors, to be overlaid with a yellow bar at the top of the frame. Written into cut_plan.json.
Step 3 User Approval (Principles)
- Clearly deletable content (stuttered restarts, false starts, half-abandoned sentences): Add directly to the plan; just explain in the report.
- Factual error paragraphs: Ask the user "Delete / Keep + correction bar"; for opinion content, prefer keep + correction.
- Correction text and fact-check conclusions (if web verification is needed, WebSearch first to find the original source) must be shown to the user for review.
- Use AskUserQuestion to ask all pending decisions at once.
Step 4 Render Command
& "C:\Users\44162\AppData\Local\Programs\Python\Python312\python.exe" "<skill>/scripts/render.py" --plan "<working dir>/cut_plan.json"
cut_plan.json format (full explanation in render.py header comments):
{
"video": "C:/original_video.mp4",
"out": "C:/final_video.mp4",
"raw": "raw.json",
"content_cuts": [[213.45, 230.98, "experiment rephrase struggling"]],
"deleted_ids": [48, 49, 50],
"fixed": {"1": "corrected text"},
"corrections": [[12.95, 20.14, "Correction: correct name is XX"]],
"silence": {"min_dur": 1.0, "keep": 0.25},
"style": {"sub_size": 64, "cor_size": 48}
}
All timestamps use the original video timeline (script automatically remaps to post-cut timeline). silence/style are optional. Default subtitle style is large mobile-friendly (based on 2560px width: 64/48, auto-scaled proportionally by resolution). If user says "font too small," adjust style values and rerun.
Step 5 Frame-Sampling Quality Check
Read actual correction timestamps (Cor lines) from final.ass, then extract frames on the new timeline:
& "D:\software\ffmpeg\bin\ffmpeg.exe" -y -i "<final video>" -vf "select='eq(n\,<frame_number>)',scale=1100:-1" -vsync vfr "<qc_dir>/qc_%d.jpg"
Frame number = seconds × 20fps. Read + visual check each frame: text complete, not too wide, no overlap with bottom subtitles.
Pitfall Archive (Lessons Learned, Do Not Repeat)
- aselect silence failure: aselect on some AAC streams cuts nothing without error → Audio removal must use
asplit+atrim+concat(render.py already implements this; do not revert to aselect). - concat cannot follow single-stream select as a concatenator (pad count mismatch error); select+setpts already outputs continuous stream.
- Final video verification must ffprobe both video and audio streams separately: format duration may be inflated by the longer stream, masking "no cut" (experienced: render "succeeded" but audio was fully kept).
- subtitles filter path: Use relative paths consistent with render cwd to avoid Chinese path escaping issues.
- Silence removal must have word protection zone (strip_guard built into render.py): whisper word timestamps may not align perfectly with silencedetect; soft words (e.g., English terms at sentence start) might fall into "silence" and get half-cut.
- The transcription script handles ffmpeg stderr with GBK compatibility (Windows encoding legacy issue; ignore thread errors).
Iteration Cost
Change font size, correction text, or add/remove cut segments → modify corresponding fields in cut_plan.json and rerun render.py; each iteration takes 1-2 minutes. The final video is overwritten; the original video is never modified.