Communitygithub.com

make-video

使用 Remotion 和本地 AI 工具,从一行想法制作出完成的社交视频(YouTube Short、Instagram Reel 或 YouTube 长视频),成本为 $0。涵盖脚本编写、语音、字幕、音乐、音效、渲染和自动质量检查。

make-video 是什么?

make-video 是一个强大的 AI 智能体技能,用于在本地免费创建社交视频。它利用 Remotion 进行渲染,并结合 Chatterbox、Whisper 和 FluidSynth 等工具,实现脚本编写、语音生成(支持用户声音克隆)、逐字同步字幕、音乐和音效生成。该技能专为 macOS(Apple Silicon)设计,无需 API 密钥或付费。其主要优势在于完全的本地运行,从头到尾控制整个流程,从一行想法到可交付的 MP4 文件。该技能提供自动质量检查(QA)门控,确保最终视频符合技术规范(如响度、字幕准确性)。它支持多种视频格式(Reel、Short、长视频),并内置了确保内容吸引力和可观看性的创作模板。对于寻求完全免费、自托管视频制作管道的开发者、内容创作者和 AI 爱好者来说,此技能非常适合。该技能来自 TheNoumanDev,是零成本工作室项目的一部分。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TheNoumanDev/zero-dollar-studio/tree/main/plugins/make-video/skills/make-video

在你喜欢的 AI 中提问

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

文档

make-video 是做什么的?

将创意转换为渲染且经过检查的 MP4,仅使用免费的本地工具。从此技能创建的项目拥有其自己的规则(在 AGENTS.md 中),请遵循它们(动画纯度、useScale、sec()、文件夹布局)。

0. 设置一个视频项目(一次性)

如果当前文件夹没有 tools/make-story.sh,则它还不是一个视频项目:

  1. 首先检查机器: uname -sm(需要 Darwin arm64)、node --version(20+)、brew --version、df -h ~(约需要 8 GB 可用空间)。在其他操作系统上,在继续之前说明哪些功能无法工作(Chatterbox 和 take 检查器在 Apple GPU 上运行)。如果缺少 Node 或 Homebrew,为用户提供一个安装命令并等待。

  2. 告知用户将要下载的内容,并等待他们的确认。 未经确认切勿开始下载。显示此表格(全部免费,来自官方源):

    下载内容大小用途存放位置
    npm 包(Remotion 等)~500 MB渲染node_modules/
    ffmpeg、uv、FluidSynth(Homebrew,仅当缺失时)~150 MB音视频工具Homebrew
    Python 包(PyTorch、Chatterbox…)~1.5 GB语音、质量检查.venv/
    GeneralUser GS 音色库~30 MB音乐tools/soundfonts/
    Chatterbox 权重~3 GB语音Hugging Face 缓存(~/.cache/huggingface),所有项目共享
    Whisper small.en~590 MB字幕tools/models/
    Whisper large-v3-turbo(可选的 take 检查器)~1.6 GB重新录制不清晰的台词Hugging Face 缓存

    总计约 6 GB,需要 10-20 分钟。提供更轻量的选项:SKIP_TAKE_CHECK=1 跳过 take 检查器(总计 4.4 GB)。询问在哪里创建项目(默认 ~/videos)。

  3. 在他们确认后,将此 SKILL.md 旁边的 template/ 文件夹复制到项目中,包括点文件(cp -R <skill dir>/template/. <dest>/),然后执行 git init。

  4. 在后台运行 tools/setup.sh,并让用户了解进度:说明当前进行到哪一步(它会打印 ▶ 行),并在大文件下载期间告知进度(du -shL ~/.cache/huggingface/hub/models--ResembleAI--chatterbox,目标约 3 GB)。重新运行是安全的:已完成的步骤会被跳过,中断的下载会继续。如果下载停滞(5 分钟内大小没有增长),停止它并重新运行 setup。如果失败,阅读错误信息,修复原因(缺少工具、磁盘空间、网络)并重新运行;不要绕过缺失的模型。

  5. 验证它能工作:tools/make-story.sh stories/fridge-drama FridgeDrama 将在约 4 分钟内生成 33 秒的示例视频(三个蔬菜在冰箱里争吵)。向用户展示 out/FridgeDrama.mp4,然后询问他们想要制作什么。

工具会自动找到模型(Chatterbox 和 take 检查器来自 Hugging Face 缓存,字幕来自 tools/models/),因此设置后无需进行任何配置。第二个项目会重用缓存的权重,因此其设置会快得多。

1. 锁定简报(仅在缺失时询问)

字段默认值
平台/格式Reel/Short:1080×1920,30 fps · YouTube:1920×1080,30 fps · Feed 帖子:1080×1350
时长Reel/Short:15-45 秒 · YouTube:3-10 分钟
类型故事(角色交谈,因此使用 §3B)或 动态图形(文本、数据、图表,因此使用 §3A)
主题 + 单一要点观众应记住的唯一一件事
音频语音(Chatterbox)、音乐 + 音效(tools/music.py)或仅音乐
语音Chatterbox 的内置声音,或用户自己录音的克隆(§3B)。未经他人同意切勿克隆。

2. 在编写任何代码之前编写脚本

时长预算: 以 Chatterbox 的语速,英语口语约每秒 2.6 个单词。目标时长 ≈ 单词数 ÷ 2.6 + Σ 停顿 + 片尾。在生成之前进行检查。(冰箱戏剧:62 个单词 + 6.4 秒停顿 + 3 秒片尾 = 33 秒。)

竖屏短视频的节奏规则:

  • 第 0 帧开始挂钩画面和音频。前 1.5 秒决定留存率,第 0 帧通常是缩略图,所以永远不要从空白或淡入帧开始。
  • 每行 ≤ 12 个单词。字幕一次显示 ≤ 3 个单词。
  • 每秒都有移动。
  • 1080×1920 的安全区: 任何重要内容不得高于 y=220 或低于 y=1540(平台 UI),并且低于 y≈1000 时不得在 x≈940 右侧(点赞、评论、分享按钮沿右边缘向下排列——tools/qa.py --layout 会检查失败)。将主持人放在左下角。
  • 以回报或笑点结束,然后是 2-3 秒的行动号召卡片。

讲解模板(“它是如何工作的”和开发者技巧 Reels,45-60 秒,120-160 个单词):

  1. 挂钩(≤ 3 秒):一个令人惊讶的真实事实或结果。
  2. “这就是它实际工作的方式”:一句打开解释的话。
  3. 2-4 个节拍,每个包含一个数字 + 一个类比(“视频只是每秒 30 张照片,就像翻页书”)。
  4. “但这里有个问题”:转折、难题或常见错误。
  5. 一行回报,然后是一个明确的行动号召(保存、分享或关注)。

然后,列出脚本下的每一个事实主张及其来源链接,标记任何你无法验证的内容,并在配音前修复或删除它。当一个数字或主张出现时,在屏幕上显示来源(小号,卡片底部)。

Shorts/Reels 的制作清单:

  • 可见的进度。 分步视频使用 <StepCard steps={[{at: 0, title: "Download it"}, …]} />(src/components/StepCard.tsx):一个“STEP 2/4”胶囊和分段条。
  • 卡拉 OK 字幕(可选样式)。 <Karaoke words={captions} keywords={["free"]} style={{left: 60, right: 140, top: 1180}} />(src/components/Karaoke.tsx):2-5 个单词的整个块显示在屏幕上,正在说的单词实心,即将出现的单词灰色,关键词和重读单词使用强调色,以便观众在静音自动播放时可以提前阅读。传递 qa 以便布局检查能看到它。
  • 系列标签。 左上角的情节标记(“PART 2”)让帖子看起来容易狂看。
  • 显示对比。 之前/之后或“我们 vs 他们”作为双栏卡片比演讲效果更好。
  • 故事节拍胜过列表。 “尝试 1 失败 → 尝试 2 失败 → 什么有效”比列出功能更能吸引注意力。
  • 在 CTA 之前放回报。 一句人性化的话,然后是行动号召。
  • 只有当背后有真实的东西(指南、提示、仓库)在等着时,才承诺“评论关键字,我会 DM 你”的奖励。

面向 TTS 的写作:

  • 不要以“…”开头一行:Chatterbox 会即兴添加一个填充词。
  • 不要以裸数字词开头一行(“Two. The face”变成了“to the face”)。写“Second, …”。
  • 按照实际发音写出数字和奇怪的名称(“five point six”,“X Z”),并将真实文本放入该行的 caption 字段。
  • 四舍五入大数字(“over 600”);TTS 会混淆“646”和“87,000”。
  • 挂钩中的短词会模糊(“This repo”被听成“The three”)。重新措辞,直到 take 检查器能正确识别。
  • 不要让多个声音同时喊同一个短词;混音会使其模糊。
  • 标点符号指导表达:“?”提升,“.”落下,大写字母增加强调。

3A. 动态图形视频

  1. 复制 src/compositions/_Template → src/compositions/<Name>,每种节拍类型(Hook、Point、Stat、List、CTA)对应一个组件。
  2. 从脚本计算时长(节拍之和减去转场),就像 getSampleIntroDuration 所做的那样。
  3. 在 src/Root.tsx 中使用内联 defaultProps 注册它。
  4. 仅音乐:编写一个包含 totalMs、outroStartMs 和 events 的 JSON 时间线,然后运行 tools/music.py。

3B. 配音故事(角色 + 字幕 + 音乐)

创建 stories/<slug>/script.json(复制 stories/fridge-drama/script.json):

  • characters:color、exaggeration(0.3 平静 → 0.9 戏剧化),以及可选的 refVoice:一个干净的 10-30 秒 WAV 文件,位于 tools/voices/ 中用于克隆。没有它,则使用 Chatterbox 的内置声音。要克隆用户的声音:他们在安静的房间中自然交谈 60-90 秒,然后裁剪出一个干净的 10-15 秒片段,没有音乐或回声(ffmpeg -ss <start> -t 12 -i note.m4a -af highpass=f=80,loudnorm=I=-18 -ar 24000 tools/voices/me.wav)。
  • lines:speaker、text、pauseAfter(秒),可选的 event + eventAt: "start" 用于标记故事节拍(门开了、躲起来…),动画和音乐都以此为关键帧。
  • 每行可选的声音指导:emotion(calm|neutral|warm|excited|dramatic|whisper)、pace(slow|normal|fast)、emphasis(用大写表示并在字幕中高亮显示的单词)、pauseBefore(秒)。"pace": "slow" 加上 0.4 秒的停顿可以使每个词都清晰。

然后运行一个命令:

tools/make-story.sh stories/<slug> <CompositionId>     # 语音 → 字幕 → 音乐/SFX → lint → 渲染 → 母带 → 质量检查
SKIP_VOICE=1 tools/make-story.sh …                     # 仅迭代视觉效果
SAMPLE=15 tools/make-story.sh …                        # 渲染前 15 秒以供批准,然后停止
工具输出
tools/voice.pypublic/<slug>/lines/*.wav(按文本和语音设置缓存)、public/<slug>/voice.wav、stories/<slug>/timeline.json(行时间、事件、每帧嘴型包络)。安装了 take 检查器后,Whisper 会听每一句话并重新录制不清晰的句子(VOICE_TAKES,默认为 3)。
tools/captions.mjspublic/<slug>/captions.json(来自 Whisper 的单词时间,来自脚本的拼写)、stories/<slug>/captions-report.json(每行的词错误率和匹配词、Whisper 遗漏的“填充”部分、整体 matchRate)
tools/music.pypublic/<slug>/music.wav(MIDI → FluidSynth,适配剪辑)、public/<slug>/sfx.wav
tools/qa.pystories/<slug>/qa/report.md:PASS / FIX / FAIL

从 timeline.json / captions.json 构建组合(参见 src/compositions/FridgeDrama/data.ts)。使用 mouthOpen() 驱动嘴型,视线朝向活跃的说话者,通过 timeline.events.* 驱动事件,时长来自 timeline.durationInFrames。

任何时间变化(文本或停顿)都需要重新生成字幕。 字幕时间是绝对的,否则会漂移。make-story.sh 总是重新运行字幕。

4. 验证(始终在声称完成之前进行)

tools/make-story.sh 以 tools/qa.py 结束,如果出现 FAIL 则退出并返回非零值。它检查文件、响度(-14 ±1 LUFS,真峰值 ≤ -1)、字幕准确性、节拍剪辑(≤ 120 毫秒)、冻结片段(≤ 3 秒)、视觉多样性(最长相同外观的运行 ≤ 5 秒)以及重复屏幕文本的字幕。LAYOUT=<CompId> 还会根据死区和面部检查字幕(组合需要一个 qa 属性,用 #FF00FF 勾勒字幕,用 #00FFFF 勾勒面部)。阅读 stories/<slug>/qa/report.md 并修复每一个 FAIL 和 FIX。

然后目视检查:

  1. npm run lint。
  2. 如果 stories/<slug>/captions-report.json 中任何一行的 WER > 0.2,则可能含糊不清:重新措辞并重新生成(由于缓存,成本低)。Whisper 遗漏的单词仅放置在语音部分上方的间隙中,较长的单词获得更多时间,并列在 filled 下:听那些部分。匹配率低于 70% 时,脚本和音频不一致,因此在继续之前重新配音。
  3. 在关键节拍(挂钩、每个说话者、每个事件、片尾)渲染静态帧,将它们合并成一张联系表,然后查看它:
    npx remotion still <Id> out/stills/f<N>.png --frame=<N> --scale=0.4
    ffmpeg -i a.png -i b.png … -filter_complex hstack=inputs=K out/stills/contact.png
    
    检查角色大小、安全区、覆盖角色的叠加层、片尾后面的遗留物、字幕同步以及文本大小(标签 ≥ 28 像素,正文 ≥ 54 像素,宽度为 1080)。
  4. 从最终的 MP4 中提取 4-5 帧并查看它们。
  5. 对于任何重要内容,请让一个全新的子代理在没有任何背景的情况下评论联系表。新鲜的视角能发现制作者遗漏的问题。

5. 交付

向用户提供 MP4、标题、说明、3-5 个标签和一个缩略图帧。未经明确批准,切勿发布或上传任何内容。 提醒他们在使用克隆声音或 AI 面部时,勾选 YouTube 的“修改或合成内容”标签。

能节省数小时的规则

  • 一次只渲染一个。 同时进行多个 Remotion 渲染会使机器过载数小时。管道已传递 --timeout=180000 --concurrency=2。
  • 使用 npx remotion add <pkg> 添加 Remotion 包,永远不要使用普通的 npm i,以保持版本匹配。
  • 响度:对话 −16 LUFS,音乐背景约 −24,最终母带 −14(两遍,已在 make-story.sh 中)。保持语音至少比音乐高出 10 dB。
  • 只有当 defaultProps 是 Root.tsx 中的内联对象时,Studio 才能保存属性编辑。
  • 编写覆盖行的 zsh 循环,使用 while read -r a b c; do …; done <<EOF,因为 for x in "a b c" 会中断。

更多经验教训,以及如何添加你自己的:reference/lessons.md。

测量成本(M1 Max,64 GB)

步骤时间
Chatterbox 模型加载每次运行约 20 秒(每行都缓存时跳过)
语音生成第一行约 55 秒(预热),之后约 3 倍实时
Take 检查每个需要重录的句子约 20-30 秒
字幕(Whisper small.en,WebGPU)11 行约 10 秒
音乐 + 音效2-5 秒
渲染 1080×1920,33 秒约 97 秒(每秒视频约 3 秒)
完整管道缓存语音时约 2 分钟;从头开始约 4 分钟

make-video 由 TheNoumanDev 创建,来自 zero-dollar-studio。它是 @0x45.dev YouTube 频道背后的管道。

相关技能