{"id":"video-cut","name":"video-cut","summary":"エージェントが選んだ元のセグメントで長い動画を短いクリップにカットします。二段階のクリエイティブプロセスの編集ステップとして、clip_plan.jsonとソースビデオが読み込まれ、edited_source.mp4が出力されます。","body":"## 1. 定位\n\n本技能只执行 Agent 已经做出的剪辑决定：\n\n1. 校验并补全 `clip_plan.json`，写出带 `clip_id`、原片/输出时间与时长的 `clip_plan_validated.json`。\n2. 先避开原片硬切附近的闪帧风险，最后把边界吸附到可靠句末/自然停顿；声音完整性拥有最终优先级。\n3. 拼接选定区间，输出 `edited_source.mp4`。\n4. 编排流程默认到此停止，由 Agent 按真实输出时间线写 `narration.json`。\n5. 旧版单阶段路径还会把原片时间的旁白映射为 `narration_mapped.json`。\n\n相同输入会得到相同输出。缓存仅表示：当 `edited_source.mp4` 新于 `clip_plan.json` 时复用成片。\n\n## 2. 输入契约\n\n`work_dir/clip_plan.json` 可以是数组，也可以是 `{\"clips\": [...]}`：\n\n```json\n{\"start\": 12.0, \"end\": 28.5, \"reason\": \"b02 | turn | power: A→B | POV=女主 | 保留反应 | 入点=问题落下 | 出点=沉默结束\"}\n```\n\n- `start` / `end` 是原片秒数；也接受 `source_start` / `source_end` 或 `in` / `out`。\n- 顶层可选 `target_duration`，例如 `\"10m\"`。\n- 多视频项目的每个片段还必须填写 `source_id`。\n- `speech_boundary_anchors.json` 与 ASR 时间段由理解阶段提供；Agent 先写大致区间，工具会尝试吸附并把仍在讲话区间内的入/出点作为 blocker 返回。\n\n`work_dir/narration.json` 只在旧版单阶段路径中可选读取；该路径要求旁白使用原片时间。若允许重复或重叠片段，旁白可带 `source_clip_id` 消歧。\n\n## 3. 剪辑意图契约\n\n工具不会替 Agent 做创作选择。写片段前先完成本节的剪辑意图检查，并让每个区间映射到 `recap_story_plan.json` 的一个 beat。\n\n使用现有自由文本 `reason` 保存简洁决定：\n\n```text\nbeat_id | function | change | POV | preferred moment | 入点 reason | 出点 reason\n```\n\n不要因为“事件重要”就保留整段；要保留最能让 change 成立的具体表演、反应、动作或揭示。理解与情绪允许时晚进早出，同时保证台词、动作和技术边界完整。\n\n下面的 `scripts/...` 均相对于本技能目录。若执行器从仓库根目录启动，请给脚本路径加上本技能的绝对目录。脚本不从其他技能目录读取文件；外部输入仅限命令显式传入的视频、参数与 `work_dir` 产物。\n\n## 4. 运行命令\n\n```bash\npython3 scripts/cut.py <video> --work-dir <work_dir> \\\n  [--target-duration 10m] [--clip-padding 0] [--allow-overlap]\n```\n\n## 5. 输出契约\n\n- `clip_plan_validated.json`：标准化片段，包含 `clip_id`、`source_start/end`、`output_start/end` 与 `duration`。\n- `edited_source.mp4`：按计划拼接后的短视频。\n- `narration_mapped.json`：仅旧版单阶段路径生成；编排流程使用 `--no-narration-map`，不会生成该文件。\n\n编排流程下游把 `edited_source.mp4` 当作视频，把 Agent 按输出时间写的 `narration.json` 当作旁白。\n\n## 6. 边界与时间线规则\n\n- 旧版路径中，`clip_plan.json` 与 `narration.json` 都使用原片时间；本工具负责原片 → 输出映射。\n- 编排路径中，`narration.json` 直接使用剪后输出时间，不再映射。\n- 默认禁止重叠或重复原片区间；`--allow-overlap` 开启后，旁白应填写 `source_clip_id`。\n- 片段起点只能位于源头、可靠句末/静音窗，或与上一片段构成无损同源连续连接；片段终点同理。ASR 判定仍在讲话且无法吸附时写入 `unsafe_clip_sentence_boundary` 并阻断。\n- `SCENE_CUT_SNAP` 默认开启：先按画面把 source start 向后、source end 向前吸附到附近硬切，随后句末吸附再做最终修正，避免视觉修正重新制造半句原声。默认范围为 `SCENE_CUT_SNAP_MARGIN=0.5` 秒，检测阈值为 `SCENE_CUT_DETECT_THRESHOLD=0.4`。\n- 连续同源片段的无损连接不做句中双侧音频淡出；非连续片段仍在安全停顿内做防爆音淡入淡出。\n- 旧版旁白映射若跨越 clip 边界，不再裁短后继续：`clamped_beats` 永久阻断，`--allow-sparse-cut` 也不能绕过旁白句子完整性。\n\n## 7. 能力边界\n\n- 不重新转写或分析视频。\n- 不写旁白，也不替 Agent 选择片段；只消费 `clip_plan.json`。\n- 除拼接与时间映射所需处理外，不额外重编码。","author":"@worldwonderer","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/worldwonderer/video-recap-skills/tree/main/skills/video-cut","license":"MIT","category":"coding","lang":"multi","tokens":1282,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"scripts/cut_cli.py","size":12793,"sha256":"691597f91c02ff1b86224db79c2abe1eac9e8753111d102b36e4e66c2df602a8"},{"path":"scripts/cut_contract.py","size":20579,"sha256":"cf325f15158ea45a3900f8f978adbf89466b369416b0a469182856a8ba4c0580"},{"path":"scripts/cut.py","size":1769,"sha256":"97e2b5b16bf6a84efdad5c1ed9cb8754439be127aa22eb0e32ea6a7b8221825f"},{"path":"scripts/cut_render.py","size":12677,"sha256":"fafbdf63e01c42e4d8014e832148ab08ad3dca3467f14bb6db869ee5265e8c1b"},{"path":"scripts/lib.py","size":3133,"sha256":"6807102e25f7a36048d567dda01a2576fcd00b60638c662fcd97a8c9282b52be"},{"path":"scripts/media_geometry.py","size":11791,"sha256":"5a79bfa1312b28213fa319f421dcfee0daf908be283457ac3f46847ec8970bc9"},{"path":"scripts/narration_mapping.py","size":9996,"sha256":"47ad5cfc2880df788ff50b5693ec4c417fc4af48c37c641a5120949f420e933b"},{"path":"scripts/sentence_boundaries.py","size":29125,"sha256":"41ad05ce58ae90eb6f76c6154378f4a6756f23fa38e6720fb2db547e64d38d47"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":true,"networkEndpoints":[]}}