Input a video link or local path → auto-detect → background download → segment → compress → Doubao transcription → strict verbatim transcript (stdout + save to disk)
Stage 0 · Locate the skill root directory (first thing)
When triggered, you must first locate yourself and run this:
VT_HOME="$(
for d in "$HOME/.agents/skills/video-transcript" \
"$HOME/.Codex/skills/video-transcript" \
"$HOME/.codex/skills/video-transcript" \
"$HOME/.claude/skills/video-transcript" \
"$(pwd)/.Codex/skills/video-transcript" \
"$(pwd)/.claude/skills/video-transcript" \
"$(pwd)/skills/video-transcript" \
"$HOME/.Codex/plugins/video-transcript/video-transcript" \
"$HOME/.claude/plugins/video-transcript/video-transcript"; do
[ -f "$d/SKILL.md" ] && echo "$d" && break
done
)"
export VT_HOME
echo "VT_HOME=$VT_HOME"
If the output is empty, it means the skill is installed in a non-standard location. Ask the user for the path, then manually export VT_HOME=<路径>.
After thatAll commandsgo through "$VT_HOME/scripts/transcript.py", do not hard-code relative or absolute paths.
Stage 1 · Intent confirmation and routing (must be done first)
Before running any download/transcription command, first determine which one the user wants:
| User intent | Handling |
|---|---|
| Explicitly says "extract verbatim transcript", "transcribe to text", "video copy", "subtitles" | Continue with this skill's transcription process |
| Explicitly says "download only", "download the video", "save MP4", "no transcription needed" | Do not run transcript.py; instead call video-download |
| Only pastes a link, says "handle this video", or does not clearly state the desired result format | First ask: "Do you only want to download the video, or do you want to extract the verbatim transcript?" and execute after the user confirms |
When downloading only, locate and call video-download:
VD_HOME="$(
for d in "$HOME/.agents/skills/video-download" \
"$HOME/.Codex/skills/video-download" \
"$HOME/.codex/skills/video-download" \
"$HOME/.claude/skills/video-download" \
"$(pwd)/skills/video-download"; do
[ -f "$d/SKILL.md" ] && echo "$d" && break
done
)"
export VD_HOME
echo "VD_HOME=$VD_HOME"
python3 "$VD_HOME/scripts/download_video.py" "<URL或本地路径>" --json
After download-only completes, follow video-download 's acceptance criteria to return the durable MP4 path, metadata path, duration, resolution, video/audio codecs, and file size; do not proceed to compression or Doubao transcription.
Stage 2 · Dependency check (first time/suspicious)
On the first run or when encountering an error, do a check-up first:
python3 "$VT_HOME/scripts/transcript.py" --doctor
If there are ✗ items, tell the user:
- Missing ffmpeg / playwright / chromium / API Key, etc. → run the one-click installation wizard:
bash "$VT_HOME/install.sh" - Only enter Stage 3 when all checks are ✓.
Stage 3 · Trigger method and execution
After the user confirms they want the verbatim transcript, if they provide a video link (URL or local path), just run:
python3 "$VT_HOME/scripts/transcript.py" "<URL或本地路径>"
Supported inputs:
- Bilibili:
https://www.bilibili.com/video/BVxxxorb23.tv/xxxshort link - Douyin:
https://www.douyin.com/video/xxx、v.douyin.com/xxx、douyin.com/jingxuan?modal_id=xxx - Xiaohongshu:
xiaohongshu.com/discovery/item/xxx、xiaohongshu.com/explore/xxx、xhslink.com/xxx - YouTube:
youtube.com/watch?v=xxx、youtu.be/xxx - WeChat Channels:
https://weixin.qq.com/sph/xxx、channels.weixin.qq.com/finder-preview/pages/sph?id=xxx - Local video file path
The script automatically: 0. Detect — launch a headless browser to get the title, duration, and direct video/audio links; print a 📊 assessment table + estimated time
- Download — reuse the direct links obtained from detection (without restarting the browser); Bilibili uses dash streams (download video/audio separately + ffmpeg merge); other platforms use direct mp4
- For WeChat Channels, first call
video-downloadto download as a local MP4, then enter the compression and transcription process; the parsing method is determined byvideo-download/.env'sWECHAT_RESOLVERdecides
- For WeChat Channels, first call
- Long video segmentation — if the total duration is > 8min, automatically split into 6min/segment to avoid the model summarizing it into an abstract
- Compress — ffmpeg, target 30MB; automatically select resolution based on duration, in one pass
- Transcribe — Doubao video understanding API, strict verbatim prompt (preserve colloquialisms, internet memes, pauses)
- Merge — Merge the outputs of each segment for long videos + automatically adjust the segment header timestamp offset
⚠️ Two things you (the agent) must do
(1) Repeat the evaluation table — set the user's waiting expectation
After the script starts, the first section of stderr will print the 📊 video detection evaluation table.You must immediately repeat it to the user, and tell them:
- Video title, duration, number of segments
- Estimated time(give the user a waiting expectation, this is the most important point)
Don't wait until the transcription finishes to say it,first repeat the evaluation table → then continue waiting for the transcription. If the user can't see the duration and estimated time, they'll think the program is stuck.
Example:
Video detection complete:
- Platform: Bilibili / Title: "xxx"
- Duration 17 min 12 sec, will be split into 3 segments for independent transcription
- Estimated time 3 min 20 sec ~ 5 min 25 sec, running now, please wait...
(2) After transcription is complete, you must output the full verbatim transcript
At the end, the script will print the full Markdown verbatim transcript to stdout.You must display the entire verbatim transcript as-is in the conversation, don't just say "saved to xxx.md" — that's equivalent to the user seeing nothing.
Correct approach:
- Capture everything in stdout after
# <标题>that is all the Markdown - Repeat it fully to the user (title, duration, all paragraphs)
- Append a line at the end stating the save path, so the user can later open the .md file
Wrong approach:
- ❌ "The verbatim transcript has been saved to outputs/xxx.md, please check the file"
- ❌ Only display the first few paragraphs and omit the rest
- ❌ Summarize/condense the content (the verbatim transcript must be displayed verbatim)
Stage 4 · Output destinations
The script willoutput to two destinations simultaneously:
- stdout direct outputFull Markdown text — for the agent to repeat to the user (see Stage 3, item 2 mandatory requirement)
- Save to diskto
$VT_HOME/outputs/<标题>_transcript.md— managed by the skill itself, all outputs in one place
Cancel saving to disk:--no-save
Change save path:--output-dir <path>
Evaluation table example
═══════════════════════════════════════════════════════
📊 视频探测
───────────────────────────────────────────────────────
平台: B 站
标题: 在浙江和安徽之间,一座10万人的城市消失了
时长: 17分12秒
分段: 3 段(每段 ≤ 6 分钟)
预估耗时: 3分20秒 ~ 5分25秒
═══════════════════════════════════════════════════════
Output format example
# 视频标题
> 时长 5:32 | 来源: <URL或文件名>
## 1. 引入话题 [00:00 - 00:42]
大家好,今天我们要聊的是...
## 2. 核心观点 [00:42 - 02:15]
那么我的看法是这样的,首先...
Features:
- Semantic segmentation: automatically split into 3-8 segments by topic, each segment with a short subtitle
- Paragraph-level timestamps: each paragraph starts with
[MM:SS - MM:SS], easy to locate - Verbatim transcription: preserve colloquialisms ("uh" "well" "ah" "like"), internet memes, pauses, no summarizing, no rewriting
- No-speech segments: use
_(此处无人声,XX秒)_to mark
Stage 5 · Exception handling
| Scenario | Handling |
|---|---|
--doctor reports missing dependency |
Run bash "$VT_HOME/install.sh" |
没找到豆包 API Key |
Check $VT_HOME/.env; if never configured, have the user run install.sh to guide filling in the Key |
| API 401 / "model not authorized" | Volcano Ark console → Model Square → click "Activate" for Doubao-Seed-2.0-pro |
| Douyin image-text note (note link) | Notify the user that image-text is not supported, only video |
| Platform frontend redesign caused scraping failure | See $VT_HOME/FALLBACK.md for manual fallback |
| WeChat Channels indicates missing video-download | First install video-download skill, or place it in the same skill directory as video-transcript sibling skill directory |
| WeChat Channels indicates missing SPH_COOKIE/YUANBAO_COOKIE | Currently using WECHAT_RESOLVER=cookie; you can configure Cookie in video-download/.env or explicitly change to WECHAT_RESOLVER=public-worker |
| Long videos are summarized by the model rather than transcribed verbatim | Automatically handled (>8min segments); if it still occurs, please report |
| Video still > 50MB after compression | Script automatically iterates reducing bitrate/resolution (up to 4 rounds) |
Channels parsing method is determined by video-download/.env . If public Worker is currently selected, write:
WECHAT_RESOLVER=public-worker
Can also temporarily override explicitly:
VIDEO_DOWNLOAD_WECHAT_RESOLVER=public-worker python3 "$VT_HOME/scripts/transcript.py" "https://weixin.qq.com/sph/xxx"
Command-line option
| Parameter | Description |
|---|---|
input |
Video URL or local file path (required,--doctor can be omitted when) |
--title |
Video title (defaults to the detected one) |
--target-size |
Compression target size in MB, default 30 |
--no-save |
Do not save .md to disk (default saves to $VT_HOME/outputs/) |
--output-dir |
Change save path |
--doctor |
Checkup mode: check dependencies + configuration |
Notes
- Doubao native video understanding; the model directly listens to video audio, no independent ASR needed
- Timestamp precision is paragraph-level (not word/sentence-level), used for chapter location
- By default stdout directly outputs the full Markdown text (for upper-layer agent display);Simultaneouslysave to disk
- Estimated time model (based on actual measurements): headless startup 10s + download (0.4s per video second) + 12s compression per segment + 30s API per segment, give a ±20% range
- API Key configuration exists in
$VT_HOME/.env(permissions 600, gitignore), not distributed with the repository