视频声音工作台
把「这个视频要什么声音」拆成四层:配音 → 配乐 → 音效 → 混音,每层先从曲库找真实录音,最后交付可直接放进视频工程的音频文件。
边界:只做声音。画面交给 video-director(默认自己写代码逐帧渲染,用户点名时才用 HyperFrames、Remotion、剪映等);本 skill 只输出音频文件、字幕时间、时间点和音量建议。
来源优先级:先曲库,后编曲,最后才合成
| 顺序 | 来源 | 什么时候用 | 脚本 |
|---|---|---|---|
| 1 | 用户给的歌 | 给了就必须用,不许换 | beats.py 测拍点 |
| 2 | HeyGen 曲库 / 音效库(默认) | 配乐和音效都先从这里找:真乐器、真录音,风格多。选定的曲子要卡拍,用 beats.py + beat_timeline.py | heygen_audio.py |
| 3 | GarageBand 编曲 | 曲库里找不到合适的,又必须按小节精确编排(抽鼓、再进鼓对准画面)时。按 loops.py --kits 实际列出的套件挑,别默认电子套件 | loops.py + arrange.py |
| 4 | 代码合成 | 最后手段:库里确实没有、而且只是短音效 | synth.py |
为什么合成排最后:模型合成的声音听多了都是一个味道(噪声上升、808 下坠、FM 叮),一条片子听下来就是「又是这一套」。曲库里是真实录音,每次能挑出不一样的东西。
arrange.py 能把几种来源放在同一个小节网格里混音、导出分轨。examples/hype-15s 演示的是这个机制,不是推荐的风格,别照着它的电音配方做下一条。
配乐和音效的硬规则
- 配乐贴主题,不自由发挥:先从主题和用户原话推出一句「这条片子听起来像什么」(情绪、能量、乐器)。产品介绍、项目宣传、发布片默认要动感、有推进力:鼓点干脆、往上走、有一个爆发的段落(有冲劲的摇滚、电影感打击乐、明快的 funk、有力的 hip-hop 律动)。慵懒爵士、lounge、lo-fi、氛围铺底这类只在用户要、或者内容就是安静的(睡前、冥想、怀旧)时用。
- 配乐和音效都不许盖过人声:音效在说话时至少比人声低 6 dB(
mix.py自动压)。有人说话时配乐至少比人声低 12 dB(默认 15)。用mix.py混,它按这个数算音量、混完再量一遍,不达标退出码 3。实测旧版手调的侧链压缩,说话时配乐只低 1.2 dB,基本一样响。 - 转场和关键帧都要有音效:每个切点一个转场音效(嗖、翻页、快门、胶片咔哒,按风格挑),每个关键动作一个命中音效(落下、揭晓、盖章、开灯)。都从曲库找,音量在人声下面。
- 候选先给用户听:2–3 首候选都在第 1 条推出的方向里(不是三种完全不同的曲风让用户猜),做成一个试听文件,和 video-director 的提案一起给用户确认。
- 对照作品记录:动手前读
~/.video-skill/作品记录.md,最近 3 条用过的曲子、主乐器不重复;交付后追加。 - 不默认「电音全家桶」:riser + 808 下坠 + 冲击 + 品牌叮这一套合成声不当默认值。动感靠曲子本身的鼓和编排,不靠合成音效堆。
工作流
- 配音先行,定时长:配音长度决定视频长度。读
references/voiceover.md。voiceover.py tts生成配音,三种来源:--source mine你的 HeyGen 复刻声音(默认),heygenHeyGen 公共声音,geminiGemini 3.8 Flash TTS(--style控制语气)。复刻声音的默认引擎经常不可用,会自动换 orca → starfish 重试。voiceover.py align把稿子切成字幕,对到真实说话段落上,输出cues.json。HeyGen 返回的字级时间戳是按字平均分的,不能用来卡字幕。
- 列出画面节拍点:爆点、转场、盖章、揭晓,各在第几秒。这是配乐和音效共用的时间表。字幕停留 ≥ 字数 × 0.25s + 0.5s,卡点不能牺牲可读性。
- 配乐:读
references/music.md。- 先写一句「这条片子听起来像什么」,用
heygen_audio.py search --type music搜 3–4 首曲风不同的候选,拼成一段试听让用户挑。 - 选定的曲子要卡拍:
beats.py测拍点和高潮,beat_timeline.py --key <关键时刻>算出歌从哪秒开始放,并按拍点出镜头时间表交给画面。 - 曲库里实在找不到、又必须按小节精确编排时,才用
loops.py+arrange.py自己编。
- 先写一句「这条片子听起来像什么」,用
- 音效:读
references/sfx.md。先从 HeyGen 音效库找真实录音,库里没有才合成。按密度档位排:只放转场和重点,或者再加关键词提示音。对齐公式:开始时刻 = 命中时刻 − 文件内峰值位置。 - 混音和响度:写
mix.json,跑mix.py:配乐按人声自动压(说话时至少低 12 dB)、音效按峰值对齐、成片 -14 LUFS、真峰值 -1.5 dBTP、导出分轨。读references/mixing.md。 - 交付前自检:
audio_qa.py查音画等长、响度、真峰值、配乐断档、结尾淡出、切点落拍。退出码 0 才交付。
不确定的风格先做试听:几段候选各 8–9 秒,拼成一个 A/B/C/D 文件发给用户挑,比口头描述有效得多。
铁律
- 同一套 loop 才能叠:GarageBand 的 loop 按歌分组(如「Cascade Bass / Lead / Pad」)。跨套件混用很容易跑调、错拍。
- 对齐的是命中点,不是文件开头:HeyGen 音效有
peak_offset,代码合成的音效由synth.py打印 peak。 - 字幕时间以真实音频为准:
voiceover.py align把稿子对到静音切出的真实段落上,不需要 whisper,也不信 TTS 返回的时间戳。 - 先做分轨再交付:混音时导出各来源的分轨,用户能听出每一层贡献了什么,也方便改单层。
- 用户点名的是硬要求:点名的歌、配音服务、「不要配乐」都照做。拿不到就在交付说明里写清原因和替代品,不许悄悄换成「差不多的」。
- 听不到就用数据验证:用 ebur128 查响度,用 volumedetect 查峰值和静音段,用波形图查结构。Agent 没有耳朵,靠数据把关,最终好不好听交给用户判断。
文件
| 文件 | 内容 | 什么时候读 |
|---|---|---|
references/voiceover.md | 复刻声音、引擎兜底、停顿写法、字幕对齐 | 要配音时 |
references/music.md | 选来源、BPM 反推、编曲套路、卡点方法、试听做法 | 要配乐时 |
references/sfx.md | 音效搜索词、代码合成配方、密度档位、对齐 | 要音效时 |
references/mixing.md | 压人声、响度标准、视频工程里怎么放、验证命令 | 每次收尾 |
scripts/voiceover.py | 列出声音 / TTS(复刻声音、HeyGen 公共声音、Gemini)/ 静音切段 / 字幕对齐 | |
scripts/loops.py | 扫描 Apple Loops、按 BPM 和套件筛选 | |
scripts/arrange.py | 按 plan.json 混出成曲和分轨 | |
scripts/heygen_audio.py | 搜索和下载 HeyGen 音乐、音效 | |
scripts/synth.py | 合成 riser / sub / ding / whoosh / tick | |
scripts/beats.py | 测现成曲子的 BPM、拍点、重拍、高潮、安静/响亮段 | 用现成曲子要卡拍时 |
scripts/beat_timeline.py | 让高潮对准关键时刻,给出裁歌命令和按拍点排的镜头时间表 | 同上 |
scripts/mix.py | 按 mix.json 混出成片声音和分轨,检查配乐有没有盖过人声 | 每次混音 |
scripts/audio_qa.py | 交付前声音自检 | 每次收尾 |
examples/hype-15s/ | 三种来源合成 15 秒动感短曲的完整示例,bash make.sh 一键复现 | 第一次用、或要一个起点时 |
依赖:ffmpeg、Python 3 + numpy、heygen CLI(已登录)、macOS 上的 GarageBand(只用到它的素材库 /Library/Audio/Apple Loops,不需要打开 App)。