clips

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Clips

Clips

Paths:
${CLAUDE_SKILL_DIR}
means the folder containing this SKILL.md, and
${CLAUDE_PLUGIN_ROOT}
the plugin folder two levels above it.
Read
${CLAUDE_PLUGIN_ROOT}/PRINCIPLES.md
first: the rules every video in this plugin follows (asking, looking real, motion, story and framing, privacy, cost).
Every question to the user goes in the question box: call the AskUserQuestion tool (2-4 options, the recommended one first). Only in an agent without that tool, ask numbered questions in text.
One long video in. The best few short clips out, each a finished vertical edit in the user's style.
clips/<name>/
  source.mp4          the long video (a symlink for a local file; never modify the original)
  source.mp3, cover.jpg  instead, for an audio-only podcast: its audio and the show's artwork
  words.raw.json      one transcript of the whole thing (never read it)
  candidates.json     every candidate with its features (never read it)
  shortlist.md        the top 8 that do not overlap, about 1,500 tokens: the only file you read
  shortlist.json      the same, for the page
  picks.html          the page the user picks from
edits/<name>-clip<N>/ one edit per chosen clip: source.mp4, words.raw.json (re-timed), clip.json
Run the scripts with
python3
on Mac and Linux,
py
on Windows.
PY="${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/run.py"
;
python3 "$PY"
below runs the editor's venv Python (
py "$PY"
on Windows). If it is missing, run the
setup
skill first.
K="${CLAUDE_SKILL_DIR}/scripts/clips.py"
,
C="${CLAUDE_PLUGIN_ROOT}/skills/cut/scripts"
,
S="${CLAUDE_PLUGIN_ROOT}/skills/style-edit/scripts"
.
路径:
${CLAUDE_SKILL_DIR}
表示包含此 SKILL.md 的文件夹,
${CLAUDE_PLUGIN_ROOT}
表示上两级目录中的插件文件夹。
先阅读
${CLAUDE_PLUGIN_ROOT}/PRINCIPLES.md
:本插件中的每个视频都必须遵循这些规则(询问、看起来真实、动效、叙事与构图、隐私、成本)。
所有面向用户的问题都要放在问题框中:调用 AskUserQuestion 工具(提供 2–4 个选项,并将推荐项放在首位)。只有在没有该工具的 agent 中,才用文本形式提出编号问题。
输入一段长视频,输出最精彩的几个短片段,每个片段都是按用户风格完成的竖屏成片。
clips/<name>/
  source.mp4          the long video (a symlink for a local file; never modify the original)
  source.mp3, cover.jpg  instead, for an audio-only podcast: its audio and the show's artwork
  words.raw.json      one transcript of the whole thing (never read it)
  candidates.json     every candidate with its features (never read it)
  shortlist.md        the top 8 that do not overlap, about 1,500 tokens: the only file you read
  shortlist.json      the same, for the page
  picks.html          the page the user picks from
edits/<name>-clip<N>/ one edit per chosen clip: source.mp4, words.raw.json (re-timed), clip.json
在 Mac 和 Linux 上使用
python3
运行脚本,在 Windows 上使用
py
。
PY="${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/run.py"
;下面的
python3 "$PY"
会使用编辑器 venv 中的 Python(Windows 上使用
py "$PY"
)。 如果缺少该环境,先运行
setup
skill。另设
K="${CLAUDE_SKILL_DIR}/scripts/clips.py"
、
C="${CLAUDE_PLUGIN_ROOT}/skills/cut/scripts"
、
S="${CLAUDE_PLUGIN_ROOT}/skills/style-edit/scripts"
。

0. Ask, once

0. 一次性询问

Read the profile and taste first (
python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/profile.py" show
,
python3 "${CLAUDE_PLUGIN_ROOT}/skills/taste/scripts/taste.py" show
). No profile yet: run the
start
skill's style intake first, so the clips come out in the user's look.
Then one question box call, the recommended option first:
questionoptions
How many clips?3 (Recommended) / 5 / 1
How long should each be?20-40 s (Recommended) / 40-60 s / 60-90 s
How many people talk in it?one (Recommended) / two (a podcast or interview)
Skip any the user already answered. These replace the cut skill's "cut first or everything at once" question: clips run straight through, and the user approves the picks and the stills sheets.
先读取 profile 和 taste(
python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/profile.py" show
、
python3 "${CLAUDE_PLUGIN_ROOT}/skills/taste/scripts/taste.py" show
)。如果还没有 profile,先运行 start skill 的风格采集流程,确保生成的片段符合用户的一贯风格。
然后调用一次问题框,并将推荐项放在首位:
问题选项
需要多少个片段?3(推荐)/ 5 / 1
每个片段应有多长?20–40 秒(推荐)/ 40–60 秒 / 60–90 秒
视频中有几个人说话?一个人(推荐)/ 两个人(播客或访谈)
跳过用户已经回答的问题。这些问题取代 cut skill 中“先剪辑还是一次处理全部”的提问:clips 流程会直接运行,用户负责确认选中的片段和静帧表。

1. The video

1. 视频

A local file (a hard link on the same drive, else a symlink, a copy only as the last resort):
bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/clips/scripts/clips.py" link "<absolute path>" clips/<name>
A link:
bash
python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/links.py" fetch "<url>" clips/<name> --max-height 1080
It uses the venv's yt-dlp (setup installs it there, not on the PATH), caps the download at 1080p (a 1080x1920 clip needs no 4K; a 20-minute talk at 4K is several GB) and prints the file path:
clips/<name>/source.mp4
. Exit 3: the site wants a login (YouTube's "confirm you're not a bot"). Ask in the question box before re-running with
--cookies-from-browser chrome
(or their browser). A podcast (RSS feed or Apple Podcasts show link):
route
lists its newest episodes as
ask
options; ask which one in the question box (newest first), then
fetch "<option url>" clips/<option name> --direct --cover "<option image>"
: the audio lands as
source.mp3
(or its own extension) and the show's artwork as
cover.jpg
. Only download what the user has the right to reuse: their own video, or one they have permission for. Say so once if the link is someone else's.
对于本地文件,同一磁盘上优先使用硬链接,否则使用符号链接,仅在最后才复制文件:
bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/clips/scripts/clips.py" link "<absolute path>" clips/<name>
对于链接:
bash
python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/links.py" fetch "<url>" clips/<name> --max-height 1080
它使用 venv 中的 yt-dlp(setup 会将其安装在 venv 中,而不是添加到 PATH),并将下载分辨率限制在 1080p(1080x1920 的片段不需要 4K;一段 20 分钟的 4K 视频可能达到数 GB),然后打印文件路径:
clips/<name>/source.mp4
。退出码 3 表示网站要求登录(YouTube 的“确认你不是机器人”)。 在重新运行并添加
--cookies-from-browser chrome
(或用户所用的浏览器)之前,先在问题框中询问。 对于播客(RSS 源或 Apple Podcasts 节目链接),
route
会将最新单集列为
ask
选项;在问题框中询问用户要哪一个(最新单集排在首位),然后运行
fetch "<option url>" clips/<option name> --direct --cover "<option image>"
:音频会保存为
source.mp3
(或源文件自身的扩展名),节目封面保存为
cover.jpg
。 只下载用户有权再利用的内容:用户自己的视频,或用户已获得许可的视频。如果链接属于他人的内容,请明确提醒一次。

2. Transcribe once

2. 只转录一次

bash
python3 "$PY" "$C/transcribe.py" clips/<name>/source.mp4 clips/<name>/words.raw.json   # the file fetch printed: source.mp3 for audio
Say the time first: Whisper takes 1-4 minutes per 3 minutes of video on a laptop (free), Scribe about 20 s for a 13-minute video. Same engines as the cut skill. Scribe adds laughter and other audio events, which the score uses. Every clip reuses this transcript: nothing is transcribed twice.
bash
python3 "$PY" "$C/transcribe.py" clips/<name>/source.mp4 clips/<name>/words.raw.json   # the file fetch printed: source.mp3 for audio
先说明预计耗时:在笔记本上,免费的 Whisper 处理 3 分钟视频约需 1–4 分钟,而 Scribe 处理一段 13 分钟视频约需 20 秒。二者使用的引擎与 cut skill 相同。Scribe 还会标记笑声和其他音频事件,供评分算法使用。 每个片段都会复用这次转录的结果,不会重复转录。

3. Candidates and the shortlist

3. 候选片段与候选列表

bash
python3 "$K" candidates clips/<name> --min 20 --max 40 [--speakers 2] [--style creator-teardowns/<handle>/style.json]
Pass the length the user picked.
--style
is the profile's first creator: the "what works" moves measured there are listed in the shortlist. Code splits the transcript into sentences and makes every run of whole sentences inside the length a candidate (never starting on "Mm-hmm" or ending mid-word), measures each, ranks them by the features, and writes
shortlist.md
.
Read
shortlist.md
only. Each entry has the hook, the opening words of every middle sentence, the last sentence and the measured features. Judge each entry on four questions: does the hook work alone, can a stranger follow it, does it pay off, is there a concrete claim, number or story.
Never read
words.raw.json
or
candidates.json
. Pick the user's number of clips from the shortlist, best first. Drop, whatever the score:
  • an ad read, a sponsor segment, an intro or a sign-off;
  • a hook that leans on earlier context ("as I said", "that's why", "this one");
  • a clip whose point is a dated claim ("at the time I'm recording this, it's number 40") when the claim has since changed: a live capture of today's page would contradict it.
bash
python3 "$K" candidates clips/<name> --min 20 --max 40 [--speakers 2] [--style creator-teardowns/<handle>/style.json]
传入用户选择的时长。
--style
使用 profile 中的首位创作者:在此处测得的“有效做法”会列入 shortlist。代码会将转录稿拆分为句子,并把时长范围内每一段连续完整句子组成一个候选片段(绝不以“Mm-hmm”开头,也不会在单词中间结束),随后测量每个候选片段、按各项特征进行排名,并写入
shortlist.md
。
只读取
shortlist.md
。每个条目都包含 hook、每个中间句子的开头、最后一句以及测量得到的特征。判断每个条目时,要回答四个问题:hook 单独出现是否成立?陌生人能否理解?内容是否有回报?是否包含具体观点、数字或故事?
绝不读取
words.raw.json
或
candidates.json
。按照用户需要的数量,从 shortlist 中挑选最佳片段,优先选择排名靠前的条目。无论评分如何,都要剔除:
  • 广告口播、赞助商片段、开场或结束语;
  • 依赖前文语境的 hook,例如“as I said”、“that's why”、“this one”;
  • 核心观点依赖已经过时的数据,例如“at the time I'm recording this, it's number 40”,而该数据后来已经变化:当天页面的实时画面会与其矛盾。

4. The picks page, then the question box

4. 选择页,然后使用问题框

bash
python3 "$K" page clips/<name> --recommend c12,c40,c7
open clips/<name>/picks.html    # Windows: start "" ..., Linux: xdg-open ...
One page: every shortlisted clip with a 360 px preview, its transcript (the hook in bold), the score breakdown and the measured features, your picks marked. Then ask in the question box (multi-select): your picks first, each labelled with its time and its hook, plus "a different one from the page". Wait for the answer.
bash
python3 "$K" page clips/<name> --recommend c12,c40,c7
open clips/<name>/picks.html    # Windows: start "" ..., Linux: xdg-open ...
一个页面中会展示 shortlist 里的每个候选片段,包括 360 px 预览、转录文本(hook 加粗)、评分明细和测量特征,并标记你推荐的片段。随后在问题框中进行多选:先列出你的推荐项,每项标注时间和 hook,再提供“从页面中选择其他片段”。等待用户作答。

5. Each chosen clip

5. 每个选中的片段

bash
python3 "$K" trim clips/<name> c12 c40 c7          # -> edits/<name>-clip1, -clip2, -clip3
Each edit folder gets
source.mp4
(frame-accurate, padded without catching the next word) and
words.raw.json
re-timed to it. An audio-only source (
source.mp3
) has no picture: trim makes each clip's
source.mp4
its audio over the podcast's own cover (the cover blurred and dimmed to fill 1080x1920, the sharp cover above the captions; no artwork: black), and
clip.json
says
audio_only
. With a cover, the render moves it: a slow push on the cover, the ground drifting against it, a small punch on each sentence start. For those, don't ask a layout: overlay, reframe no, no cutout, captions on (
profile.py style
keeps them on). Say once that each clip is the audio over the show's cover with the speaker's words as captions. Before the clips run, settle music once for all of them (style-edit
references/plan.md
"Music"; the style decides unless the user set
sound.music
).
All clips at once (Claude Code, or any agent with subagents): launch one
clip-editor
agent (
ai-editor:clip-editor
) per clip, all in one message so they run at the same time. Give each
EDIT
(the clip's folder, absolute),
ROOT
(
${CLAUDE_PLUGIN_ROOT}
), the
PY
line, and the answers: aspect, layout, music, the transcription engine, and reframe yes (a wide source, unless the platform is YouTube) or no, and whether the source has captions burned in. Each takes its clip through the cut and style-edit to the stills sheet and returns a short JSON:
status
,
cut_s
,
verify
,
cut_page
,
sheet
,
error
. Merge those; never open a clip's transcript or paper edit. Then run the
stills-critic
agent on every
ready
clip's sheet, again all in one message, and fix what they fail (plan and stills again for that clip). A
failed
clip: run it by hand as below.
One at a time (no subagents), for each clip in order:
  1. Vertical from a wide video:
    python3 "$PY" "$K" reframe edits/<name>-clip<N>
    crops to 9:16 with the crop following the speaker's head shot by shot (camera cuts found with ffmpeg). Skip it when the profile's platform is YouTube or the source is already vertical.
  2. Cut: the cut skill from its step 2 (
    retakes.py propose
    ): the transcript is already there. Then build, render, verify and the cut page, as that skill says. Music under the voice is measured per file:
    build_timeline.py
    trims only between words there.
  3. Style:
    python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/profile.py" style edits/<name>-clip<N>
    , then the style-edit skill from its step 2. If the source already has captions burned in, set
    "captions": {"present": false}
    in that edit's
    style.json
    , or the captions stack.
Either way, open every clip's
cut-check.html
and show all the stills sheets together for one approval, ask the render question once for all of them, and render. After approval, run
python3 "${CLAUDE_PLUGIN_ROOT}/skills/cut/scripts/judge_cut.py" score
on each clip's folder (cut
references/judge.md
). Hand the renders over on one review page, each clip a tab (
start
with clip 1,
alt
for the rest, folder
clips/<name>
; see
${CLAUDE_PLUGIN_ROOT}/skills/style-edit/references/review.md
), then
serve
and
wait
in the background.
bash
python3 "$K" trim clips/<name> c12 c40 c7          # -> edits/<name>-clip1, -clip2, -clip3
每个编辑文件夹中都会生成
source.mp4
(逐帧精确,并在不会带入下一个词的情况下留出余量)以及针对该片段重新计时的
words.raw.json
。纯音频源(
source.mp3
)没有画面:trim 会将每个片段的音频叠加在播客自己的封面上,生成
source.mp4
(封面模糊并压暗后铺满 1080x1920,清晰封面置于字幕上方;没有封面时则使用黑色背景),同时
clip.json
中会标记
audio_only
。有封面时,渲染会为封面添加缓慢推进、背景漂移以及每句话开始时的轻微冲击效果。对于这些片段,不要询问布局:overlay、reframe no、no cutout、captions on(
profile.py style
会保持字幕开启)。说明一次:每个片段都是将音频叠加在节目封面上,并将说话者的原话作为字幕显示。 在运行片段之前,统一确定一次音乐方案(style-edit 的
references/plan.md
中的“Music”);除非用户已设置
sound.music
,否则以 style 的决定为准。
一次处理全部片段(Claude Code,或任何支持 subagent 的 agent):每个片段启动一个
clip-editor
agent(
ai-editor:clip-editor
),并且在同一条消息中全部启动,使它们同时运行。向每个 agent 提供
EDIT
(片段文件夹的绝对路径)、
ROOT
(
${CLAUDE_PLUGIN_ROOT}
)、
PY
命令行,以及以下答案:aspect、layout、music、转录引擎、reframe yes(宽屏源时使用,除非平台是 YouTube)或 no,以及源视频是否已经烧录字幕。每个 agent 都要将对应片段依次经过 cut 和 style-edit 处理到静帧表阶段,并返回一段简短 JSON:
status
、
cut_s
、
verify
、
cut_page
、
sheet
、
error
。合并这些结果;绝不打开片段的转录稿或 paper edit(纸面剪辑稿)。然后对每个
ready
片段的静帧表运行
stills-critic
agent,同样在一条消息中全部启动,并修复它们未通过的检查(为对应片段重新执行 plan 和 stills)。对于
failed
片段:按照下方步骤手动运行。
逐个处理(没有 subagent 时),按顺序处理每个片段:
  1. 将宽屏视频转换为竖屏:
    python3 "$PY" "$K" reframe edits/<name>-clip<N>
    ,裁剪为 9:16,并根据用 ffmpeg 检测到的镜头切换,逐镜头跟踪说话者的头部。如果 profile 的平台是 YouTube,或源视频已经是竖屏,则跳过此步骤。
  2. Cut: 从第 2 步开始执行 cut skill(
    retakes.py propose
    ):转录稿已经存在。然后按照该 skill 的说明完成构建、渲染、验证和 cut page。人声下的音乐按文件单独测量:
    build_timeline.py
    只会裁掉词语之间的音乐。
  3. Style:
    python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/profile.py" style edits/<name>-clip<N>
    ,然后从第 2 步开始执行 style-edit skill。如果源视频已经烧录字幕,则在该编辑的
    style.json
    中设置
    "captions": {"present": false}
    ,否则字幕会重叠。
无论采用哪种方式,都要打开每个片段的
cut-check.html
,并同时展示所有静帧表以进行一次统一审批;针对全部片段只询问一次渲染确认,然后执行渲染。审批完成后,对每个片段文件夹运行
python3 "${CLAUDE_PLUGIN_ROOT}/skills/cut/scripts/judge_cut.py" score
(参见 cut 的
references/judge.md
)。在一个审阅页面中交付所有成片,每个片段使用一个标签页(使用
start
打开片段 1,其余使用
alt
;文件夹为
clips/<name>
;参见
${CLAUDE_PLUGIN_ROOT}/skills/style-edit/references/review.md
),然后在后台运行
serve
和
wait
。

If a script stops

如果脚本停止

messagedo
no run of whole sentences lasts <lo>-<hi> s
ask in the question box for a wider length, run
candidates
again
no candidate <id>
use an id from
shortlist.md
links.py fetch
exit 3 (a login or "confirm you're not a bot")
ask before re-running with
--cookies-from-browser <browser>
any cut or style-edit messagethat skill's "If a script stops" table
消息操作
no run of whole sentences lasts <lo>-<hi> s
在问题框中询问是否使用更宽的时长范围,然后重新运行
candidates
no candidate <id>
使用
shortlist.md
中的一个 id
links.py fetch
退出码 3(要求登录或“确认你不是机器人”)
询问用户后,再使用
--cookies-from-browser <browser>
重新运行
任何 cut 或 style-edit 消息查阅对应 skill 的“If a script stops”表格

Rules

规则

  1. Every word, number and name on screen comes from that clip's own words. Nothing from the rest of the video, and nothing the speaker did not say.
  2. No AI-tell looks:
    ${CLAUDE_PLUGIN_ROOT}/skills/style-edit/references/ai-tells.md
    applies to every clip.
  3. A close-up podcast frame has no free space: no card or logo goes over the head. Fewer visuals is right; captions and zooms carry it.
  4. Never cut a clip mid-sentence. Shorter or longer than asked beats a broken thought.
  1. 屏幕上的每个词、数字和姓名都必须来自该片段自身的原话。不能使用视频其他部分的内容,也不能使用说话者没有说过的话。
  2. 不得出现明显的 AI 痕迹:
    ${CLAUDE_PLUGIN_ROOT}/skills/style-edit/references/ai-tells.md
    适用于每个片段。
  3. 播客的特写画面没有可用空白区域:卡片或 logo 不能遮挡头部。少用视觉元素才是正确做法;依靠字幕和缩放来撑起画面。
  4. 绝不在句子中间剪辑。与用户要求的长度略有偏差,也比破坏完整思路更好。

Cost per long video

每段长视频的成本

Measured on a 13-minute two-person podcast and a 12-minute talking-head video (2026-10):
  • Transcription: Scribe took 16-18 s; Whisper is free and slower. Once per long video.
  • Candidates and features: 4-6 s of code, $0.
  • Claude reads
    shortlist.md
    (about 1,500 tokens), never the transcript (about 20,000).
  • The picks page: 30-40 s of ffmpeg for 8 previews, 7-9 MB.
  • Each clip then costs what one cut and one style edit cost.
根据一段 13 分钟的双人播客和一段 12 分钟的单人口播视频实测(2026-10):
  • 转录:Scribe 用时 16–18 秒;Whisper 免费但速度较慢。每段长视频只转录一次。
  • 候选片段和特征分析:代码运行 4–6 秒,费用为 $0。
  • Claude 读取
    shortlist.md
    (约 1,500 tokens),绝不读取转录稿(约 20,000 tokens)。
  • 选择页:使用 ffmpeg 生成 8 个预览需要 30–40 秒,占用 7–9 MB。
  • 此后每个片段的成本等同于一次 cut 加一次 style edit。

Self-check

自检

bash
python3 "$K" demo
bash
python3 "$K" demo

Files

文件

  • scripts/clips.py
    : candidates, page, trim, reframe and the offline demo (synthetic transcript). Stdlib only, except
    reframe
    (OpenCV, through the venv).
  • ${CLAUDE_PLUGIN_ROOT}/agents/clip-editor.md
    : one clip through the cut and style-edit to its stills sheet.
  • scripts/clips.py
    :负责候选片段、选择页、裁剪、竖屏重构和离线演示(使用合成转录稿)。仅使用标准库,reframe 除外(通过 venv 使用 OpenCV)。
  • ${CLAUDE_PLUGIN_ROOT}/agents/clip-editor.md
    :将单个片段从 cut 和 style-edit 流程处理到静帧表阶段。