Skip to content
Video & Audio
Skill

/video-shots

拉片:把一条成片拆成逐镜头的分析表——每个镜头的时长、景别、类别、运镜、画面。 分工刻在骨子里:**能量的都由代码量**(切点来自 ffmpeg 场景检测,时长是切点相减, 运动量是逐帧差分的中位数),模型只判断它真正该判断的那几件事(景别 / 类别 / 运镜 / 画面 / 节奏), 然后每一条判断都被代码当场对账——**声称推拉摇移却实测几乎不动,门直接拦**。 看片走联系表(每镜起手帧 + 收尾帧各拼一张大图,一屏二十几个镜头,a/b 对照就是运镜), 不是一张张翻。检测漏刀多刀用 recut 补刀并刀,自动重编号重算时长,手改边界过不了门。 产出

BOOST
From plugin
reelbench-skills
9083 skills
Install
$ npx -y skills add eternityspring/reelbench-skills --skill video-shots --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/video-shots

Context preview

The summary Claude sees to decide when to auto-load this skill.

拉片:把一条成片拆成逐镜头的分析表——每个镜头的时长、景别、类别、运镜、画面。 分工刻在骨子里:**能量的都由代码量**(切点来自 ffmpeg 场景检测,时长是切点相减, 运动量是逐帧差分的中位数),模型只判断它真正该判断的那几件事(景别 / 类别 / 运镜 / 画面 / 节奏), 然后每一条判断都被代码当场对账——**声称推拉摇移却实测几乎不动,门直接拦**。 看片走联系表(每镜起手帧 + 收尾帧各拼一张大图,一屏二十几个镜头,a/b 对照就是运镜), 不是一张张翻。检测漏刀多刀用 recut 补刀并刀,自动重编号重算时长,手改边界过不了门。 产出

SKILL.md

video-shots.SKILL.md
name: video-shots
version: 1.0.0
description: |
  拉片:把一条成片拆成逐镜头的分析表——每个镜头的时长、景别、类别、运镜、画面。
  分工刻在骨子里:**能量的都由代码量**(切点来自 ffmpeg 场景检测,时长是切点相减,
  运动量是逐帧差分的中位数),模型只判断它真正该判断的那几件事(景别 / 类别 / 运镜 / 画面 / 节奏),
  然后每一条判断都被代码当场对账——**声称推拉摇移却实测几乎不动,门直接拦**。
  看片走联系表(每镜起手帧 + 收尾帧各拼一张大图,一屏二十几个镜头,a/b 对照就是运镜),
  不是一张张翻。检测漏刀多刀用 recut 补刀并刀,自动重编号重算时长,手改边界过不了门。
  产出 shots.json + Markdown 镜头表 + **单页交互式拉片报告**:内嵌播放器(播放时同步高亮镜头、
  点镜头跳转)、镜头节奏带、可搜索可筛选可排序的镜头表(列表 / 卡片两种视图、首尾关键帧并排、
  点图开大图)、景别类别运镜分布、出场人物、质量门、导出 JSON。单文件零依赖,离线双击能开。
  15 道质量门全部由脚本确定性检查。
  零依赖、零 API key,只要 node 和 ffmpeg。
  Use when asked to 拉片、拆镜头、分析视频镜头、镜头时长、景别、运镜、镜头表、
  video shot breakdown、shot list from video。
allowed-tools:
  - Read
  - Write
  - Edit
  - Bash
  - Glob
triggers:
  - video-shots
  - 拉片
  - 拆镜头
  - 镜头分析
  - 分析视频
  - 镜头表
  - 景别
  - 运镜
  - shot breakdown
  - shot list
metadata:
  license: Apache-2.0
  requires:
    bins:
      - node      # >= 18,只用标准库,无 npm 依赖
      - ffmpeg    # 场景检测、运动测量、抽帧、联系表
      - ffprobe   # 片长、帧率、分辨率
  runtimes:
    - claude-code
    - codex

video-shots

给成片**拉片**——把一条片子拆成逐镜头的分析表:**时长、景别、类别、运镜、画面**。

**前提刻在骨子里:镜头边界是量出来的,不是看出来的。** 模型看视频最不可靠的就是报时间—— 「这个镜头大概 3 秒」和「2.97 秒」差的不是精度,是这份表能不能用。所以这里划一条死线:

| 谁来定 | 什么 | 怎么定 | | --- | --- | --- | | **代码** | 切点、时长、片长、帧率 | ffmpeg 场景检测 + ffprobe,两位小数 | | **代码** | 每个镜头的实测运动量 | 逐帧差分曲线的区间中位数(两端剔除,避开切点尖峰) | | **模型** | 景别、类别、运镜、画面、节奏 | 看关键帧判断——**只有这几件事是模型的活** | | **代码** | 判断对不对 | 15 道质量门,逐条对账 |

最硬的一道门是**运镜实测对账**:摄影机真动了,像素不可能不变。所以「声称推/拉/摇/移/跟, 实测帧间变化接近 0」这一向直接拦——这是模型拉片最常见的幻觉。反过来(声称固定、实测很动) **不拦**,只出提示:固定机位前面有人跳舞,帧间差一样会爆。

`{baseDir}` = 本文件所在目录。脚本 `{baseDir}/scripts/video-shots.mjs`,零依赖,`node` 直接跑。

**边界(不做的事)**:不转写语音(没有 ASR,台词靠画面上烧录的字幕读,读不到就留空并说明)、 不做人脸识别与人物自动归并(`cast` 是人工编号)、不评价片子好坏(报告只给事实和统计)、 不剪辑不导出片段、不做镜头内的物体检测。

---

Step 0 — 定输入与范围

只要一个视频文件。先问清两件事,问不到就按默认走并在汇报里说明:

  • **拉全片还是拉一段**:全片是默认。只要某一段就先用 ffmpeg 裁出来再拉,别在整片上标一半。
  • **拉来干什么**:做仿写参考(重画面与运镜)、做剪辑节奏分析(重时长与类别)、

做投放素材盘点(重产品镜与字卡)。用途不同,`note` 里该多记什么不同——**表的结构是一样的**。

Step 1 — seed 工作底稿 ⛔ 切点在这一步定死

cd <输出目录>
node {baseDir}/scripts/video-shots.mjs seed <video> --track track.json --title "<片名>" > shots.json

stderr 会报:片长、帧率、分辨率、检测到几个切点、合并后几个镜头。**先看这一行再往下走**:

  • 平均镜长十几秒、镜头数明显偏少 → 阈值高了,`--threshold 0.15` 重跑(暗戏、慢片、

同机位对话多的片子都要往下调)

  • 镜头数比肉眼数的多出一截 → 阈值低了,往 `0.4` 调,或留到 Step 4 用 `recut --merge` 并
  • 一条 3 分钟的片子跑完只要几秒钟,**多跑两遍比将就一份烂底稿划算**

底稿里 `start` / `end` / `seconds` / `motion` 已经填好,`size` / `category` / `camera` / `frame` 是空的—— **那四个空格子才是模型的活**。

Step 2 — 抽关键帧与联系表

node {baseDir}/scripts/video-shots.mjs frames shots.json --video <video>
node {baseDir}/scripts/video-shots.mjs sheet shots.json --cols 4 --rows 6
node {baseDir}/scripts/video-shots.mjs sheet shots.json --cols 4 --rows 6 --pick b

每镜两张:`frames/S01a.jpg`(起手 15% 处)和 `S01b.jpg`(收尾 85% 处)。 联系表把它们各拼成一张大图(行优先,S01 在左上),**a 表看内容,b 表看运镜**—— 同一格前后对照,取景变没变一眼就知道。

**先看联系表,再看单帧。** 一张张翻完整部片是浪费额度:一张联系表 = 二十几个镜头, 只在判不准的那几个镜头上回去看单帧(`Read frames/S07a.jpg`)。

Step 3 — 逐批填四个字段

一批 ≤ 25 个镜头(正好一张联系表)。每批拿到:

  • `{baseDir}/references/taxonomy.md`(四张词表 + 判据,**照着填**)和 `{baseDir}/references/analysis-pass.md`(怎么看、常见病)
  • 这一批的镜头底稿(镜号、起止、时长、**实测运动**)
  • 这一批的 a / b 两张联系表

填的顺序:**景别 → 类别 → 运镜 → 画面 → 节奏**。运镜看 a/b 取景差 + 实测运动值, 两者打架时**信实测**。顺带记 `subjects` / `onscreenText` / `audio`—— **画面上烧录的对白字幕算台词**,进 `audio` 并带上说话人;片名、字卡、界面文字进 `onscreenText`。

**节奏(`rhythm` + `rhythmNote`)回答的是「观众为什么还没划走」**: 钩子 / 铺垫 / 递进 / 重音 / 转折 / 兑现 / 换气 / 收口,八个角色选一个, 再用一句话写清**观众这一刻看到什么**(判据见 `taxonomy.md` 第五节)。 **可选字段:不做节奏分析就一镜都别标;标了就得整片标全**,门会拦半张表。 标满之后校验会顺带提示三件事:开篇有没有钩子、兑现前面有没有铺垫、有没有连着六镜节奏发平。

编辑 `shots.json` 时**只动那几个字段**:`start` / `end` / `seconds` / `motion` / `seedCuts` / `meta` 是机器字段,改了就是伪造证据,门会点名。

Step 4 — 补刀与并刀(发现漏切就修,别将就)

场景检测必然在两个地方出错:叠化和暗场对暗场**漏刀**,手持晃动和闪光**多刀**。 a 帧和 b 帧根本是两个场景,就是漏刀的铁证。

node {baseDir}/scripts/video-shots.mjs recut shots.json --track track.json \
  --split 63.5 --split 127.37 --merge 45.97 > shots.new.json && mv shots.new.json shots.json

自动重编号、重算时长与实测运动,补的刀记进 `manualCuts`(`boundary` 门认它)。 **边界没动过的镜头标注原样保留;被拆被并的镜头标注清空并在 `note` 里写明出身**—— 这两半是不是一回事,得重新看画面,不许把旧描述顺下去。

改完重抽这些镜头的帧(`frames` 会覆盖整个目录,直接重跑就行),把清空的格子补上。

Step 5 — 校验 ⛔ 不能跳

node {baseDir}/scripts/video-shots.mjs validate shots.json --track track.json --frames frames

15 道门全是代码:时间轴连续(按序、首尾相接、从 0 到片尾)、时长自洽(`seconds` = `end − start`, 短镜必须带 note)、镜号连号、**景别/类别/运镜三张词表**、转场枚举、**画面描述可核对** (中文 ≥12 字 / 英文 ≥8 词 + 空话词表 + 不许「这个镜头…」「This shot…」开头)、**画面描述不重复**、主体对账 `cast`、 **类别要有证据**(对话必须有台词、字卡必须有画面文字、反应必须写是谁、空镜里不许有人)、 **运镜实测对账**、**边界来自检测**(自己加的刀必须在 `manualCuts` 里声明)、关键帧齐全、 **节奏分析可核对**(可选字段:整片标或整片不标;标了就得写清为什么,空话照拦)。

**有违规逐条修,改完重跑,直到通过。** 跳过的门会明说原因(没给 `--track`、没建 `cast`、 关键帧目录不存在)——**跳过不是通过**,汇报时要讲。拉英文片加 `--lang en`, 门的名字和违规信息都会用英文说。

「提示(不拦)」那一栏不是错误,是需要人判断的地方:固定机位实测偏高, 多半是主体在动,也可能是你把一次缓推看漏了,自己回去看一眼那一镜。

Step 6 — 出报告与汇报

node {baseDir}/scripts/video-shots.mjs render shots.json --md --track track.json > shots.md
node {baseDir}/scripts/video-shots.mjs render shots.json --html --track track.json \
  --video <原片相对报告的路径> > shots-report.html

`--video` 给报告里的播放器指原片(默认用 JSON 里的 `source`;观众也能在页面上现场选本地文件)。 界面语言用 `--lang zh|en`(默认中文)。`render` 自动去 `frames/` 找关键帧, **先抽帧再 render**,缺图明说缺、不摆占位图充数。

报告是**单文件交互页**(样式与交互来自 `{baseDir}/scripts/report.css` 和 `report.js`, render 时整段内联;这三个文件必须一起拷走):

  • **播放器**:播放时同步高亮当前镜头、填充时间轴进度;点任意镜头或时间轴片段跳过去
  • **镜头节奏带**:片宽 = 时长占比,颜色深浅 = 景别远近
  • **镜头表**:列表 / 卡片两种视图,首尾关键帧并排(对照着看就是运镜),可搜索(镜号、画面、

台词、人物)、可按类别筛选、可按时长排序;点关键帧开大图

  • **统计分布 / 出场人物 / 质量检查**:默认收起,按需展开;人物卡点一下筛出他的全部镜头
  • 页头一行给结论(`14 项通过 · 1 条提示`),提示里点名的镜号可以点着跳过去

汇报一句话说清:**多少镜、平均镜长、每分钟切次、景别与运镜的大头、最长和最短的镜头在哪、 报告路径**;补了几刀并了几刀、哪几道门跳过了、哪几条提示需要人看,明说。

最终落地:

<输出目录>/
├── shots.json              ← 拉片主数据
├── track.json              ← 运动曲线(机器证据,别手改)
├── shots.md
├── shots-report.html       ← 双击就能开
├── frames/                 ← S01a.jpg / S01b.jpg …
└── sheets/                 ← sheet-a01.jpg / sheet-b01.jpg …(联系表)

---

边界

  • **没有语音转写。** 台词只来自画面上烧录的字幕;没有字幕的片子 `audio` 大面积留空是正常的,

这时把 `dialogue` 判成 `subjec

Read more
Ships withreelbench-skills

Claude Code / Codex skills for working with video.

Get the whole plugin
Stats
908
Stars
111
Forks
Active
Maintenance
JavaScript
Language
Apache-2.0
License
7d ago
Last commit
1mo ago
Created
5h ago
Added

Repo: eternityspring/reelbench-skills

Other skills on reelbench-skills.

video-scrub
Skill

video-scrub

把一条视频重建成「只有画面和声音」的干净文件——**源片的元数据一概不搬**: GPS、设备型号、账号 ID、创建时间、章节、GoPro 的遥测轨,全部留在原地。 走的是白名单而不是黑名单:不列要删什么,只说带什么过去(画面一条流、声音一条流),…

video-sync
Skill

video-sync

把拉片数据和原片合成一条**能直接看的视频**:一边是画面,一边是这一镜的分镜信息 (镜号、起止、时长、景别、类别、运镜、画面描述、台词),**镜头切了信息跟着切**, 镜头表自动滚动并高亮当前这一镜。 版式只看原片的宽高比:**横版 / 方版 →…