diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9c1bd39..896ebeb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ All notable changes to capcut-cli are documented here. The format follows [Keep
### Added
- `doctor` reports what each draft store holds — for every default CapCut/JianYing project directory it finds (or the one folder named with the new `--drafts
`), a `draft-store` check counts the projects as readable, markerless, encrypted or unreadable. A JianYing 6.0+ store, where every project the app wrote is an encrypted payload, is now named once and up front (warn) with what still works — `init`, `quickstart` and `compile` build plaintext drafts from the bundled template — instead of being discovered one failed command at a time. Same classification as the `template.store` report of `init`/`quickstart`/`compile`. `capcut doctor --drafts ` also makes the check usable on a machine without the app, and in CI.
+- `examples/short-video-narration.md` (+ zh-CN) — silent clip → 9:16 draft with a TTS voiceover and script-accurate captions, as four commands (`quickstart --ratio 9:16` → `tts --text-file` → `caption --from-segment --script` → `lint`) and as one script, `examples/scripts/narrate-short.sh`. `examples/scripts/edge-tts-wav.sh` bridges edge-tts (MP3 only) to the WAV `tts` expects at `{out}`; any other engine plugs in through `--tts-cmd`. The vision-model step that writes the script is optional and stays outside the CLI: the script is a text file.
## [0.25.0] — 2026-09-18
diff --git a/docs/quickstart.zh-CN.md b/docs/quickstart.zh-CN.md
index 93f1f53..241f6bc 100644
--- a/docs/quickstart.zh-CN.md
+++ b/docs/quickstart.zh-CN.md
@@ -95,6 +95,7 @@ capcut transition <草稿> <片段ID> "_3D空间" --jianying
## 接下来
+- 想直接出一条带旁白和字幕的 9:16 短视频草稿:[短视频旁白示例](../examples/short-video-narration.zh-CN.md)(`quickstart` → `tts` → `caption` → `lint`,一个脚本串起来)。
- [命令参考(简体中文)](./command-reference.zh-CN.md) —— 全部命令一览
- [中文 README](../README.zh-CN.md) —— 项目总览、安装与赞助
- [examples/](../examples/) —— 端到端示例(英文:配音对齐、serve 自动化、批量字幕修正)
diff --git a/examples/README.md b/examples/README.md
index 8c9c771..f2dff91 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -13,10 +13,11 @@ Copy-paste recipes for common CapCut / JianYing workflows. Every recipe is one s
| [keyframe-pan.md](./keyframe-pan.md) | Unfinished-pan keyframe pattern for epilogue / payoff stills |
| [verify-vo-alignment.md](./verify-vo-alignment.md) | Pre-flight check on ElevenLabs voiceover + word-level timestamps |
| [serve-automation.md](./serve-automation.md) | Wire the stateless JSONL queue runner into n8n / Make / Coze / Docker |
+| [short-video-narration.md](./short-video-narration.md) · [中文](./short-video-narration.zh-CN.md) | Silent clip → 9:16 draft with a TTS voiceover and script-accurate captions |
All shell-only recipes assume `capcut` is on your `$PATH` (`npm install -g capcut-cli`).
-The three keyframe / VO recipes ship with companion Python scripts under [`./scripts/`](./scripts/) — Python 3.9+, no external deps.
+The three keyframe / VO recipes ship with companion Python scripts under [`./scripts/`](./scripts/) — Python 3.9+, no external deps. The narration recipe ships two shell scripts there (`narrate-short.sh`, `edge-tts-wav.sh`).
> **JianYing (剪映) users:** every recipe works on JianYing projects too — point `` at the JianYing draft directory.
-> **中文 / Chinese:** the project README has a Chinese translation at [`README.zh-CN.md`](../README.zh-CN.md). Translation of these recipes is pending.
+> **中文 / Chinese:** the project README has a Chinese translation at [`README.zh-CN.md`](../README.zh-CN.md). The short-video narration recipe is written in both languages ([中文](./short-video-narration.zh-CN.md)); translation of the others is pending.
diff --git a/examples/scripts/edge-tts-wav.sh b/examples/scripts/edge-tts-wav.sh
new file mode 100755
index 0000000..17a132c
--- /dev/null
+++ b/examples/scripts/edge-tts-wav.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+# edge-tts writes MP3 whatever the file is called; `capcut tts` expects the
+# engine to write a WAV at {out}. This wrapper bridges the two:
+# capcut tts 0s --text-file script.txt \
+# --tts-cmd "bash examples/scripts/edge-tts-wav.sh {text} {out} zh-CN-XiaoxiaoNeural"
+# Args: [voice]. Needs edge-tts (pip install edge-tts) and ffmpeg.
+set -euo pipefail
+text="${1:?text}"
+out="${2:?out.wav}"
+voice="${3:-${EDGE_TTS_VOICE:-zh-CN-XiaoxiaoNeural}}"
+tmp="$(mktemp -t edge-tts-XXXXXX).mp3"
+trap 'rm -f "$tmp"' EXIT
+edge-tts --voice "$voice" --text "$text" --write-media "$tmp" >/dev/null
+ffmpeg -v error -y -i "$tmp" -ar 24000 -ac 1 "$out"
diff --git a/examples/scripts/narrate-short.sh b/examples/scripts/narrate-short.sh
new file mode 100755
index 0000000..a02e847
--- /dev/null
+++ b/examples/scripts/narrate-short.sh
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+# Silent clip -> narrated 9:16 draft, editable in CapCut / JianYing.
+#
+# bash examples/scripts/narrate-short.sh ["Draft name"] [--drafts ] [--voice ]
+#
+# script.txt is the narration, plain text, one sentence per line. Write it by
+# hand, or let any vision model describe the clip first (see the recipe). The
+# script never needs a model: text in, draft out.
+#
+# Steps (each is one capcut command; run them by hand if you prefer):
+# 1. quickstart --video --ratio 9:16 portrait draft with the clip on the main track
+# 2. tts --text-file script.txt voiceover from the script via edge-tts (any --tts-cmd works)
+# 3. caption --from-segment captions with whisper's timing and the script's wording
+# 4. lint the draft is clean before it is opened in the app
+# Needs: capcut (npm i -g capcut-cli), ffmpeg, edge-tts (pip install edge-tts).
+# Optional: whisper for step 3 — without it the draft still has the clip and the voiceover.
+# CAPCUT_TTS_CMD overrides the engine template ({out} required, {text} optional).
+set -euo pipefail
+
+clip="${1:?usage: narrate-short.sh [name] [--drafts ] [--voice ]}"
+script="${2:?script.txt (one sentence per line)}"
+name="旁白短视频"
+shift 2
+# A third positional that does not start with "--" is the draft name.
+if [ $# -gt 0 ] && [ "${1#--}" = "$1" ]; then name="$1"; shift; fi
+drafts=()
+voice="${EDGE_TTS_VOICE:-zh-CN-XiaoxiaoNeural}"
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --drafts) drafts=(--drafts "$2"); shift 2 ;;
+ --voice) voice="$2"; shift 2 ;;
+ *) echo "unknown flag: $1" >&2; exit 2 ;;
+ esac
+done
+[ -s "$script" ] || { echo "script is empty: $script" >&2; exit 2; }
+here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# Built separately: a "{out}" inside "${VAR:-...}" would close the expansion early.
+default_tts="bash $here/edge-tts-wav.sh {text} {out} $voice"
+tts_cmd="${CAPCUT_TTS_CMD:-$default_tts}"
+
+# Run a capcut command; on failure print its message and stop. On success print its JSON.
+run() {
+ local out
+ if ! out="$("$@" 2>/dev/null)"; then
+ echo "$1 ${2:-} failed:" >&2
+ "$@" 2>&1 >/dev/null | head -c 400 >&2 || true
+ echo "$out" | head -c 400 >&2
+ echo >&2
+ exit 1
+ fi
+ printf '%s' "$out"
+}
+# Read one top-level key from a JSON document on stdin (empty when absent or not JSON).
+key() {
+ python3 -c "import json,sys
+try: d = json.load(sys.stdin)
+except Exception: sys.exit(0)
+v = d.get('$1', '')
+print(len(v) if isinstance(v, list) else v)"
+}
+
+# 1. Portrait draft with the clip on the main track.
+project="$(run capcut quickstart "$name" --video "$clip" --ratio 9:16 "${drafts[@]}" | key draft_path)"
+[ -n "$project" ] || { echo "quickstart returned no draft_path" >&2; exit 1; }
+echo "draft: $project"
+
+# 2. Voiceover from the script, placed at 0s.
+segment="$(run capcut tts "$project" 0s --text-file "$script" --tts-cmd "$tts_cmd" | key segment_id)"
+[ -n "$segment" ] || { echo "tts returned no segment_id" >&2; exit 1; }
+echo "voiceover: segment $segment"
+
+# 3. Captions: whisper supplies the timing, the script supplies the wording.
+# Whisper missing is not fatal — the draft already has clip + voiceover.
+if captions="$(capcut caption "$project" --from-segment "$segment" --script "$script" 2>&1)"; then
+ echo "captions: $(printf '%s' "$captions" | key segments) cue(s)"
+else
+ echo "captions: skipped — $(printf '%s' "$captions" | key error | head -n 1 | cut -c1-160)"
+fi
+
+# 4. Lint, then open in the app (restart CapCut/JianYing so it lists the new draft).
+capcut lint "$project" -H
+echo
+echo "Open CapCut / JianYing and pick \"$name\"."
diff --git a/examples/short-video-narration.md b/examples/short-video-narration.md
new file mode 100644
index 0000000..2cafa6c
--- /dev/null
+++ b/examples/short-video-narration.md
@@ -0,0 +1,68 @@
+# Short-video narration: silent clip → 9:16 voiced draft
+
+English | [中文](./short-video-narration.zh-CN.md)
+
+Three commands: `quickstart` creates a 9:16 draft with the clip on the main track, `tts` voices your script, `caption` writes captions with whisper's timing and your script's wording, then `lint` checks the result. No GUI in the loop; when you open the app, the video, voiceover and caption tracks are all still editable.
+
+## You need
+
+- capcut-cli (`npm install -g capcut-cli`, Node ≥ 18)
+- ffmpeg
+- a local TTS. The example uses [edge-tts](https://github.com/rany2/edge-tts) (`pip install edge-tts`, free neural voices); any command that can write a WAV plugs in through `--tts-cmd`
+- optional: whisper (`pip install openai-whisper`) for the captions. Without it the draft still has the clip and the voiceover
+
+## Inputs
+
+```
+clip.mp4 # silent footage, landscape or portrait (--ratio 9:16 sets the canvas)
+script.txt # narration, one sentence per line
+```
+
+Write the script yourself, or let any vision model look at the clip first. For example, sample frames and hand them to whatever model CLI you use:
+
+```bash
+mkdir -p frames && ffmpeg -v error -i clip.mp4 -vf fps=1/2 frames/%02d.jpg
+ "Write a 5-sentence spoken narration for these frames, one sentence per line, no title" frames/*.jpg > script.txt
+```
+
+The model is optional: the script is a plain text file and a hand-written one works the same.
+
+## One command
+
+```bash
+bash examples/scripts/narrate-short.sh clip.mp4 script.txt "Narrated short" --voice en-US-AriaNeural
+```
+
+`--drafts ` names the draft library; without it the machine's default directory is used. The script only chains the four steps below.
+
+## Step by step
+
+```bash
+# 1. Portrait draft, clip on the main track
+capcut quickstart "Narrated short" --video clip.mp4 --ratio 9:16
+# draft_path in the result is the draft folder
+
+# 2. Voiceover at 0s. edge-tts only writes MP3 and `capcut tts` expects the engine
+# to write a WAV at {out}, so examples/scripts/edge-tts-wav.sh converts in between
+capcut tts "" 0s --text-file script.txt \
+ --tts-cmd "bash examples/scripts/edge-tts-wav.sh {text} {out} en-US-AriaNeural"
+# segment_id in the result is the voiceover segment
+
+# 3. Captions: timing from whisper, wording from your script
+capcut caption "" --from-segment --script script.txt
+
+# 4. Check
+capcut lint "" -H
+```
+
+Restart CapCut / JianYing once so it lists the new draft, then open it.
+
+## Other voices, other engines, caption styling
+
+- edge-tts voices: `edge-tts --list-voices` (`--voice` or the `EDGE_TTS_VOICE` environment variable)
+- other engines: any command that writes a WAV to `{out}`. `{text}` is optional; without it the script is piped to stdin (how piper works). macOS `say`: `--tts-cmd "say -o {out} --data-format=LEI16@24000 {text}"`; in the script, override with the `CAPCUT_TTS_CMD` environment variable
+- caption styling: `caption --preset ` (extract one with `make-preset` from a caption you styled in the app) or `--style-ref `; `--karaoke` for word highlighting
+
+## JianYing 6.0+
+
+A draft created this way is plaintext; JianYing 11.4 (macOS) is reported to open and upgrade it in place, other builds are unverified. Existing encrypted drafts are not read by this CLI; `capcut decrypt ` reports the state, and [jianying-encryption.md](../docs/jianying-encryption.md) has the background.
diff --git a/examples/short-video-narration.zh-CN.md b/examples/short-video-narration.zh-CN.md
new file mode 100644
index 0000000..c3de7c6
--- /dev/null
+++ b/examples/short-video-narration.zh-CN.md
@@ -0,0 +1,68 @@
+# 短视频旁白:无声素材 → 9:16 口播草稿
+
+[English](./short-video-narration.md) | 中文
+
+三条命令:`quickstart` 建一个 9:16 草稿并放入素材,`tts` 用你的文案生成旁白,`caption` 用 whisper 的时间轴配上你的文案生成字幕,最后 `lint` 检查。全程不开剪映界面;打开剪映时,视频轨、旁白轨、字幕轨都还是可编辑的。
+
+## 你需要
+
+- capcut-cli(`npm install -g capcut-cli`,Node ≥ 18)
+- ffmpeg
+- 一个本地 TTS。示例用 [edge-tts](https://github.com/rany2/edge-tts)(`pip install edge-tts`,微软中文神经网络音色,免费);任何能写出 WAV 的命令都可以通过 `--tts-cmd` 接入
+- 可选:whisper(`pip install openai-whisper`),用于字幕。没有它,草稿仍然包含素材和旁白
+
+## 输入
+
+```
+clip.mp4 # 无声素材(横竖都行,--ratio 9:16 决定画布)
+script.txt # 旁白文案,一行一句
+```
+
+文案自己写,或者先让任意视觉模型看一遍素材再写。例如先抽帧,再把帧交给你手头的模型 CLI:
+
+```bash
+mkdir -p frames && ffmpeg -v error -i clip.mp4 -vf fps=1/2 frames/%02d.jpg
+<你的视觉模型 CLI> "根据这些画面写一段 5 句的中文口播文案,一行一句,不要标题" frames/*.jpg > script.txt
+```
+
+模型不是必需的:文案就是一个普通文本文件,手写同样可以。
+
+## 一键
+
+```bash
+bash examples/scripts/narrate-short.sh clip.mp4 script.txt "旁白短视频" --voice zh-CN-XiaoxiaoNeural
+```
+
+`--drafts <目录>` 指定草稿库;不指定就用本机的默认目录。脚本只是把下面四步串起来。
+
+## 分步
+
+```bash
+# 1. 9:16 草稿,素材上主轨
+capcut quickstart "旁白短视频" --video clip.mp4 --ratio 9:16
+# 结果里的 draft_path 就是草稿目录
+
+# 2. 旁白,放在 0s。edge-tts 只会写 MP3,capcut tts 要求引擎把 WAV 写到 {out},
+# 所以经过 examples/scripts/edge-tts-wav.sh 转一次
+capcut tts "" 0s --text-file script.txt \
+ --tts-cmd "bash examples/scripts/edge-tts-wav.sh {text} {out} zh-CN-XiaoxiaoNeural"
+# 结果里的 segment_id 是旁白片段
+
+# 3. 字幕:时间来自 whisper,文字来自你的文案。中文默认每条最多 16 个字,按字断句,不加空格
+capcut caption "" --from-segment --script script.txt
+
+# 4. 检查
+capcut lint "" -H
+```
+
+重启一次剪映,让它读到新草稿,然后在草稿列表里打开它。
+
+## 换音色、换引擎、改字幕样式
+
+- edge-tts 中文音色:`edge-tts --list-voices | grep zh-CN`(Xiaoxiao、Yunxi、Yunyang……),用 `--voice` 或环境变量 `EDGE_TTS_VOICE` 指定
+- 其他引擎:任何能把 WAV 写到 `{out}` 的命令都行。`{text}` 可选;模板里没有 `{text}` 时,文案从 stdin 传入(piper 就是这样用)。macOS 自带的 `say`:`--tts-cmd "say -o {out} --data-format=LEI16@24000 {text}"`,脚本里用 `CAPCUT_TTS_CMD` 环境变量覆盖
+- 字幕样式:`caption --preset `(先用 `make-preset` 从你调好的字幕段提取)或 `--style-ref `;卡拉 OK 高亮加 `--karaoke`
+
+## 剪映 6.0+ 用户
+
+这样新建的草稿是明文,据报告剪映 11.4(macOS)打开后会就地升级,其他版本未验证。已有的加密草稿本 CLI 不读取,`capcut decrypt <草稿>` 会报告加密状态;来龙去脉见 [jianying-encryption.zh-CN.md](../docs/jianying-encryption.zh-CN.md)。