Communitygithub.com

原片变短视频:对话式剪出 final.mp4

用对话剪任何视频:把原始素材放进文件夹,拿回 edit/final.mp4。本地免费 Whisper 转写,自动剪掉口癖和空白,逐段调色,每个剪辑点 30 毫秒音频淡入淡出,烧录字幕和动画叠层,并在每个剪辑点自检。无需任何 API key。

原片变短视频:对话式剪出 final.mp4 是什么?

「原片变短视频」配方第 1 步(剪出成片母版),来自 Moh4696/freecut。它是 browser-use/video-use 的分支,把付费的 ElevenLabs 依赖换成免费、可插拔的转写后端。适用于 Claude Code、Codex 及任何有 shell 权限的智能体,用 npx skills add Moh4696/freecut 安装。它在本地转写素材(mlx-whisper 或 faster-whisper,需要说话人分离时可选 VibeVoice 或 ElevenLabs),生成短语级转写稿,根据素材内容提问,给出 4–8 句剪辑方案并等你确认。随后生成 EDL,用 ffmpeg 逐段调色,每个剪辑点加 30 毫秒淡入淡出,由并行子智能体制作叠层动画(HyperFrames、Remotion、Manim 或 PIL),最后烧录字幕,并在成片的每个剪辑点逐一检查(最多 3 轮自检),会话记忆保存在 project.md。

兼容平台✓Claude Code✓Codex CLI~Cursor
npx skills add Moh4696/freecut

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

freecut

原则

  1. LLM 从原始转录 + 按需画面中进行推理。 唯一值得保留的衍生产物是紧凑的短语级转录文件 (takes_packed.md)。其他一切——填充词标记、重拍检测、镜头分类、强调打分——都在决策时动态推导。
  2. 音频是首要的,视觉是其次的。 剪辑候选来自语音边界和静音间隙。仅在决策点处深入检查视觉信息。
  3. 提问 → 确认 → 执行 → 迭代 → 持久化。 在用户用清晰的自然语言确认策略之前,绝不触碰剪辑。
  4. 泛化。 不要预设视频类型。查看素材,询问用户,然后进行编辑。
  5. 艺术自由是默认状态。 本文档中的每个具体值、预设、字体、颜色、持续时间、音调结构和技术都只是一个已验证视频的实例——而非强制要求。阅读它们以理解什么是可能的以及为什么有效。然后根据素材本身和用户的实际需求,做出你自己的审美判断。唯一必须做的事在下面的硬性规则部分。 其他一切都是你的自由。
  6. 自由创造。 如果素材需要一种本文档未描述的技术——分屏、画中画、底部身份卡片、反应剪辑、速度斜坡、定格、交叉淡入淡出、匹配剪辑、L 剪辑、J 剪辑、呼吸处的速度斜坡等等——尽管去做。辅助工具是 ffmpeg 和 PIL。只要格式支持,它们什么都能做。无需等待许可。
  7. 在展示给用户之前,验证你自己的输出。 如果你自己都不会发布它,那就不要展示出来。

硬性规则(生产正确性——不可协商)

以下是产生静默失败或错误输出的偏离情况。它们关乎正确性,而非品味。记住它们。

  1. 字幕在滤镜链中最后应用,在所有叠加动画之后。否则叠加层会遮挡字幕。这是静默失败。
  2. 逐段提取 → 无损的 -c copy 拼接,而不是单通道滤镜图。否则在添加叠加层时会对每个片段进行二次编码。
  3. 在每个片段边界处添加 30ms 音频淡入淡出 (afade=t=in:st=0:d=0.03,afade=t=out:st={dur-0.03}:d=0.03)。否则每个剪辑点都会出现可听见的爆音。
  4. 叠加层使用 setpts=PTS-STARTPTS+T/TB 将其第 0 帧移动到窗口起始位置。否则在叠加窗口期间会看到动画的中间部分。
  5. 主 SRT 文件使用输出时间线偏移量:output_time = word.start - segment_start + segment_offset。否则在片段拼接后,字幕会错位。
  6. 绝不在单词中间进行剪辑。 每个剪辑边缘都必须对齐到转录文本中的单词边界。
  7. 在每个剪辑边缘添加填充。 工作窗口:30–200ms。ASR 时间戳有 50–100ms 的漂移——填充可以吸收这种漂移。快节奏视频使用更紧的填充,电影感视频使用更松的填充。
  8. 仅使用词级别的、逐字的 ASR 文本。 绝不要使用 SRT/短语模式(会丢失亚秒级间隙数据)。也不要使用标准化的填充词(会丢失编辑信号)。
  9. 按源文件缓存转录。 除非源文件本身发生变化,否则绝不重新转录。
  10. 并行子 Agent 处理多个动画。 绝不要串行处理。通过 Agent 工具一次性生成 N 个;总耗时为最慢的那个。
  11. 执行前确认策略。 在用户批准清晰的自然语言计划之前,绝不触碰剪辑。
  12. 所有会话输出都在 <videos_dir>/edit/ 目录下。 绝不要写入 freecut/ 项目目录内。

本文档中的其他所有内容都是实例。当素材需要时,可以随时偏离。

目录布局

技能文件位于 freecut/ 中。用户素材存放在他们指定的任何位置。所有会话输出都进入 <videos_dir>/edit/。

<videos_dir>/
├── <源文件, 保持原样>
└── edit/
    ├── project.md               ← 记忆;每个会话追加
    ├── takes_packed.md          ← 短语级转录,LLM 的主要阅读视图
    ├── edl.json                 ← 剪辑决策
    ├── transcripts/<name>.json  ← 缓存的规范化 ASR JSON
    ├── animations/slot_<id>/    ← 每个动画的源文件 + 渲染 + 推理
    ├── clips_graded/            ← 逐段提取的片段(含调色和淡入淡出)
    ├── master.srt               ← 输出时间线字幕
    ├── downloads/               ← yt-dlp 输出
    ├── verify/                  ← 调试帧 / 时间线 PNG
    ├── preview.mp4
    └── final.mp4

设置

首次安装存在于 install.md(克隆、依赖、ffmpeg、技能注册、API 密钥)。不要在每次会话时都重新运行;冷启动时只需验证:

  • 转录后端可用。默认是 whisper(免费、本地)——检查 mlx-whisper(Apple Silicon)或 faster-whisper 是否可以导入。如果两者都未安装,告诉用户 pip install mlx-whisper(或 faster-whisper),而不是静默地回退到付费后端。对于可选的 vibevoice / elevenlabs 后端,在 freecut 仓库根目录的环境变量或 .env 文件中检查 VIBEVOICE_ASR_URL / ELEVENLABS_API_KEY。
  • ffmpeg + ffprobe 在 PATH 中。
  • Python 依赖已安装(在仓库内执行 uv sync 或 pip install -e .)。
  • 如果会话需要 HyperFrames 或 Remotion 插槽,Node.js + npm 需可用。HyperFrames 目前需要 Node.js 22+。
  • yt-dlp、HyperFrames、Remotion、Manim 仅在首次使用时安装。
  • 首次使用的动画设置应在插槽目录内进行,绝不能在 freecut 仓库根目录。HyperFrames 可以通过 npx --yes hyperframes ... 调用;Remotion 可以使用 npx create-video@latest 搭建,或者在本地项目中作为依赖安装后再使用其 remotion render 命令。
  • 此技能包含了 skills/manim-video/。在构建 Manim 插槽时,请阅读其 SKILL.md。

辅助脚本(helpers/transcribe.py、helpers/render.py 等)与此 SKILL.md 文件位于同一目录。根据包含此文件的目录解析它们的路径——该技能通常被符号链接到 ~/.claude/skills/freecut/ 或 ~/.codex/skills/freecut/。

辅助脚本

  • transcribe.py <video> — 单文件转录。通过 --backend {whisper,vibevoice,elevenlabs} 可选择后端(默认 whisper,本地 + 免费,单说话人)。vibevoice 使用 VIBEVOICE_ASR_URL 实现实时说话人日志;elevenlabs 使用 ELEVENLABS_API_KEY 并支持 --num-speakers。结果会被缓存。
  • transcribe_batch.py <videos_dir> — 4 工作线程并行转录。使用相同的 --backend 标志。适用于多段素材。
  • pack_transcripts.py --edit-dir <dir> — transcripts/*.json → takes_packed.md(短语级别,静音 ≥ 0.5s 或说话人变化时断句)。由于 JSON 形状已规范化,此功能在所有后端上工作方式相同。
  • timeline_view.py <video> <start> <end> — 生成胶片条 + 波形 PNG。按需的视觉深入检查。不是扫描工具——在决策点使用,而不是持续使用。
  • render.py <edl.json> -o <out> — 逐段提取 → 拼接 → 叠加层(PTS 偏移) → 最后是字幕。--preview 用于快速生成 720p 预览。--build-subtitles 用于内联生成 master.srt。
  • grade.py <in> -o <out> — ffmpeg 滤镜链调色。包含预设 + --filter '<raw>' 用于自定义。

对于动画,创建 <edit>/animations/slot_<id>/ 目录,使用 Bash 工具,并通过 Agent 工具生成一个子 Agent。

工作流程

  1. 清点素材。 使用 ffprobe 检查每个源文件。对目录运行 transcribe_batch.py。运行 pack_transcripts.py 生成 takes_packed.md。对一两个片段运行 timeline_view 以获得视觉第一印象。

  2. 预扫描问题。 快速浏览一遍 takes_packed.md,记录口头失误、明显的用词不当或需要避免的措辞。形成一个简单列表,作为编辑简报的输入。

  3. 对话。 用清晰的自然语言描述你所看到的。根据素材本身提出针对性问题。收集:内容类型、目标长度/宽高比、美学/品牌方向、节奏感、必须保留的时刻、必须剪掉的时刻、动画和调色偏好、字幕需求。不要使用固定的检查清单——每次的合适问题都不同。

  4. 提出策略。 4–8 句话:结构形态、片段选择、剪辑方向、动画计划、调色方向、字幕风格、预估时长。等待确认。

  5. 执行。 通过编辑子 Agent 简报生成 edl.json。在存在歧义的时刻深入检查 timeline_view。在并行的子 Agent 中构建动画。对每个提取的片段应用调色。通过 render.py 合成最终视频。

  6. 预览。 运行 render.py --preview。

  7. 自我评估(在展示给用户之前)。 对渲染后的输出(而非源文件)在每一个剪辑边界处运行 timeline_view(±1.5s 窗口)。检查每张图片是否存在以下问题:

    • 剪辑点处的视觉不连贯/闪烁/跳跃
    • 边界处的波形尖峰(漏掉 30ms 淡入淡出的音频爆音)
    • 字幕被叠加层遮挡(违反规则 1)
    • 叠加层未对齐或显示错误帧(违反规则 4)

    同时抽样检查:前 2s、最后 2s 以及中间 2–3 个点——检查调色一致性、字幕可读性、整体连贯性。对输出运行 ffprobe,验证时长与 EDL 预期一致。

    如果任何一项失败:修复 → 重新渲染 → 重新评估。自我评估最多进行 3 轮——如果 3 轮后问题依然存在,向用户标记这些问题,而不是无限循环。只有在自我评估通过后才展示预览。

  8. 迭代 + 持久化。 接收自然语言反馈,重新计划,重新渲染。绝不重新转录。用户确认后生成最终渲染版本。将结果追加到 project.md。

剪辑技巧

  • 音频优先。 从单词边界和静音间隙中寻找候选剪辑点。
  • 保留峰值时刻。 笑声、笑点、强调的节拍。剪辑点应延伸到笑点之后以包含反应——笑声本身就是节拍。
  • 说话人交接 时,在两次发言之间保留一定的时间间隔。常用值:400–600ms。快节奏视频更短,电影感视频更长。这是一个品味判断。
  • 音频事件作为信号。 (laughs)、(sighs)、(applause) 标记了节拍。剪辑点应延长以包含它们。
  • 静音间隙是剪辑候选。 长度 ≥ 400ms 的静音通常是最干净的。150–400ms 的短语边界在视觉检查后可用。长度 < 150ms 不安全(可能位于短语中间)。
  • 剪辑填充示例(此技能发布的演示视频使用):在第一个保留单词前填充 50ms,在最后一个保留单词后填充 80ms。混剪节奏更紧,纪录片更松。保持在 30–200ms 的工作窗口内(硬性规则 7)。
  • 绝不要独立地推理音频和视频。 每个剪辑点都必须同时作用于两个轨道。

打包的转录文件(主要阅读视图)

pack_transcripts.py 读取所有 transcripts/*.json 文件,并生成一个 markdown 文件,其中每个片段(take)都是一个由短语级行组成的列表,每行以其 [起始-结束] 时间范围作为前缀。短语在静音 ≥ 0.5s 或说话人变化时断开。这是编辑器子 Agent 用来选择剪辑点的工件——它通过纯文本提供了单词级别的精度,而所需的 tokens 仅为原始 JSON 的十分之一。

示例行:

## C0103  (持续时间: 43.0s, 8 个短语)
  [002.52-005.36] S0 一个 Web Agent 所做的百分之九十的工作都是完全浪费的。
  [006.08-006.74] S0 我们解决了这个问题。

编辑器子 Agent 简报(用于多片段选择)

当任务是“从多个片段中,为每个节拍选择最佳的一个”时,生成一个专门的子 Agent,并附带一个如下形状的简报。结构是承载核心逻辑的;音调形状示例仅供参考。

你正在编辑一个 <类型> 视频。为每个节拍选择最佳的一个片段,并按节拍的逻辑顺序排列,而不是按源文件的顺序。

输入:
  - takes_packed.md(所有片段的时间标注短语级转录)
  - 产品/叙事背景:<来自用户的 2 句话描述>
  - 说话人:<姓名、角色、表达风格说明>
  - 预期结构:<选择一个原型,或自行创造>
  - 需要避免的口头失误:<来自预扫描步骤的列表>
  - 目标时长:<秒>

常见的结构原型(选择一个,或者改编/创造):
  - 科技产品发布/演示:  钩子 → 问题 → 解决方案 → 好处 → 示例 → 行动号召
  - 教程:             介绍 → 准备 → 步骤 → 陷阱 → 总结
  - 采访:             (问题 → 回答 → 追问)循环
  - 旅行/活动:       到达 → 亮点 → 安静时刻 → 离开
  - 纪录片:           论点 → 证据 → 反方观点 → 结论
  - 音乐/表演:        前奏 → 主歌 → 副歌 → 桥段 → 尾奏
  - 或者创造你自己的。

规则:
  - 起始/结束时间必须落在转录文本的单词边界上。
  - 在剪辑边界添加填充(工作窗口 30-200ms)。
  - 优先选择 ≥ 400ms 的静音作为剪辑目标。
  - 如果没有更好的片段,可以保留不可避免的口误。在“原因”中注明。
  - 如果超过预算,进行修改:删除一个节拍或修剪尾部。报告总时长并自我修正。

输出(JSON 数组,不要包含说明文字):
  [{"source": "C0103", "start": 2.42, "end": 6.85, "beat": "钩子",
    "quote": "...", "reason": "..."}, ...]

返回最终的 EDL 和一行总时长检查结果。

调色(当用户要求时)

你的工作是推理图像,而不是应用某个预设。查看一帧画面(通过 timeline_view),决定哪里有问题,调整一项,再次查看。

心理模型是 ASC CDL。每个通道:out = (in * slope + offset) ** power,然后是全局饱和度。slope → 高光,offset → 阴影,power → 中间调。

示例滤镜链(grade.py 的 --list-presets 可以列出预设;将它们作为起点或混合使用):

  • warm_cinematic — 复古/技术感,微妙的青橙色调分离,低饱和度。在真实的发布视频中使用过。对口播视频安全。
  • neutral_punch — 最小化的校正:对比度提升 + 温和的 S 形曲线。无色相偏移。
  • none — 直接复制。用户未提出要求时的默认选项。

对于其他任何情况——肖像、自然、产品、音乐视频、纪录片——创造你自己的滤镜链。grade.py --filter '<raw ffmpeg>' 接受任何滤镜字符串。

硬性规则:在提取过程中逐段应用(不要在拼接后应用,后者会导致二次编码)。在没有检查肤色之前,绝不要使用激进的调色。

字幕(当用户要求时)

字幕有三个值得考虑的维度:分块(每行 1/2/3 个词或一个句子)、大小写(全大写/首字母大写/自然写法)和位置(距离底部边缘的距离)。正确的组合取决于内容。

已实践的风格——选择一个,改编它,或根据内容创造新的:

  • 全大写 / 每行 1 词 / 底部 3% 边距 — 非常适合活泼的快节奏促销视频。
  • 首字母大写 / 每行 2 词 / 底部 5% — 干净的科技教程。
  • 自然写法 / 每句一行 / 底部 5% — 反光/文档风格。
  • 自然写法 / 混合(2-3 词为主,关键句用整句)/ 底部 4% — 视频播客/对话风格。

实现细节:撰写者会在 project.md 中生成一个分块的“燃烧列表”。render.py 的 --build-subtitles 命令将其转换为带时间偏移量的 SRT 文件。单行中的溢出由 ffmpeg 的 subtitles 滤镜自动换行处理——皮质损伤并不意味着你需要强制预换行。

在部署之前通过 timeline_view 验证最终字幕。

叠加动画(按需)

::: important 并行化 始终同时启动所有动画插槽。不要串行构建。使用 Agent 工具并行生成 N 个子 Agent。总墙钟时间 ≈ 最慢的那个。 :::

每个动画都是一个 slot_<id>/ 目录,包含:

  • source.gif / source.mov / source.png / source_<frame>.png — 动画资产,由子 Agent 生成
  • render.sh — 一个 shell 脚本,在操作完成后输出 slot_<id>_final.mov(或 .png 序列)到 slot 目录。使用 ffmpeg 渲染到 -c prores_ks -profile:v 3 -pix_fmt yuv422p10le 以保留颜色精度;最后的合成阶段会根据需要转换为 H.264/5。
  • reasoning.md — 关于为什么选择此动画及其结构的简短说明。

子 Agent 会收到此 SKILL.md 中它们所需的部分(特别是关于叠加层和 setpts 偏移的规则),以及任何特定的用户偏好。它们可以使用 HyperFrames、Remotion、Manim(通过 skills/manim-video/ 子技能)、PIL、ffmpeg(如 drawtext、movie 滤镜)或你认为合适的任何方法。没有任何限制。

当子 Agent 完成其动画仓库后,它会返回其 slot_<id>/ 目录的路径。主 Agent 收集这些路径,将它们填充到 EDL 的 "effects": [{"type": "overlay", "path": ".../slot_<id>/", ...}] 中,然后传递到 render.py,后者会处理偏移、持续时间、alpha 通道和最终的合成。

额外创建模式

如果用户想要一些与当前编辑不直接相关的额外内容、风格或技术解释——例如,一个展示镜头如何工作的演示动画,或一个在开始时介绍说话人身份的卡片——自由地创建一个新的动画插槽并并行启动一个子 Agent。像常规叠加动画一样处理时间和合成。

构图方法

对于引导视觉注意力的静态叠加层——例如,在相机设置教程中将当前设置居中并淡化其余部分的圆形遮罩——使用 PIL 生成矢量风格的遮罩,使用 center: (radius, softness, opacity...) 符号。像常规动画一样在 slot_<id>/ 中设置它。

平台集成

  • 此技能依赖于 Agent 工具进行子 Agent 通信(从主技能上下文向上生成)。在 Claude Code 中,这是 Codex 或 Bash 工具。在 Cursor 中,它是 @Codex 或 Agent 的等效调用。如果你所在的平台不支持子 Agent,需要手动运行 Bash 命令直到工具完成。
  • 时间线查看器使用 matplotlib(由 transcribe.py 或 timeline_view.py 触发)。这在无头环境中可以工作,但会保存 PNG 而不是显示窗口。
  • Sub-agent 编排在缺少 Agent 工具的平台上会自动降级为串行 Bash 调用。这对于最终视频来说仍然是正确的,只是更慢。

参考

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能