关于 sound-design
sound-design 是用于为动态视频设计音效的 Python 工具集,面向需要让声音与画面时间线同步的创作者。它通过标准库合成声音,并提供混音、响度母带处理和 WAV 输出。
主要功能
- 01纯 Python 标准库合成音效
- 02按时间线放置并混合声音
- 03自动响度母带处理
- 04输出 WAV 文件
- 05提供多种音效生成器
适用场景
- 01为动画文字和界面动效添加音效
- 02按视频时间线制作同步音轨
- 03为短促音效混音并控制响度
MCP 相关
README 提及可选使用 ElevenLabs MCP 生成语音或无法合成的声音,并将文件写入 public/。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ whaleyxbt/ claude-motion --skill sound-design安装后在 Claude Code 中输入/sound-design确认已加载。
详细介绍
声音设计
大多数 AI 制作的动态图形都没有声音。声音能让作品更有成片感。
sfx/ 引擎完全使用 Python 标准库合成所有声音:不需要采样、不涉及许可、不需要安装,每次运行的输出都相同。它读取与画面相同的时间线 JSON,因此声音不会与画面不同步。
组成部分
| 文件 | 作用 |
|---|---|
sfx/synth.py | 声音生成器:每个生成器都返回 48 kHz 的单声道采样 |
sfx/mix.py | Mix:安排声音的时间、将母带处理到目标响度并写入 WAV |
sfx/loudness.py | BS.1770 综合响度(与 ffmpeg 的 ebur128 一致) |
sfx/cues/<video>.py | 提示表:为一段视频设计声音 |
python3 -m sfx --list # generators with what each is for
python3 -m sfx sfx/cues/<video>.py # render → mastered WAV
为新视频编写提示表
创建 sfx/cues/<video>.py:
from sfx.synth import click, pop, whoosh, chime, riser, impact
TIMELINE = "timeline.json" # the same file the composition reads
OUT = "public/sfx.wav"
TARGET_LUFS = -14.0 # optional, this is the default
def score(mix, tl):
s1 = tl["s1"]
mix.put(s1["title"], whoosh(0.4, 500, 2400, peak=0.45), 0.12)
for i, t in enumerate(s1["items"]):
mix.put(t, pop(900 + i * 150, 400), 0.3, pan=-0.4 + i * 0.3)
mix.put(t, samples, gain, pan):t必须始终取自tl,不能手动输入数值。相对于节拍的偏移(s1["exit"] + 0.05)可以使用。mix.typing(start, end, chars):每个字符对应一次带有人性化变化的按键声。mix.put_stereo(t, left, right, gain):用于pad()等立体声源。- 母带处理会自动完成:引擎会进行软削波并设置增益,以达到
TARGET_LUFS;同时只在必要时提高驱动量,确保真峰值 ≤ −2 dBFS(为 AAC 过冲留出空间,使 MP4 保持在 −1 dBTP 以下)。如果混音主要由短促音效组成,且音效之间留有静音,就无法在不产生严重失真的情况下达到 −14;此时引擎会降低最终响度并给出提示。应通过加入持续声音(如铺底音或更长的尾音)来解决,而不是强行达到目标。 - 在
package.json中添加指向新提示表的"sfx"脚本,或直接运行它。
sfx/cues/effort.py 是一个完整的真实示例:包含 128 个声音和一段铺底音。
视觉事件 → 声音
| 画面内容 | 生成器 | 说明 |
|---|---|---|
| 打字 | mix.typing() | 抖动 ±4–6 ms,随机增益 |
| 单词/行显现 | whoosh() + blip(),在落点处播放 | 短促、轻盈 |
| 徽章、标签、标注弹出 | pop() | 在一组连续音效中逐渐升高音调 |
| 控件卡入某个步进 | click() + blip(),音调取自对应调性 | |
| 草图/绘制动画 | scratch() | |
| 逐渐增强 | riser() | 恰好在重击处结束;每段视频只用一个大型渐强音 |
| 成功/到达 | chime() | 调内和弦 |
| 主视觉转场 | 转场进入时用 whoosh(),重击处用 `impact()`` | 每段视频只用一次重击音 |
| 全程铺底 | 使用带 envelope() 的 pad() | 在主视觉转场下方压低音量 |
用声音强调,不要用声音叙述:并非每个动作都需要声音。连续运动(漂移、颗粒、旋转)保持静音。
音量与空间
- 主视觉重击:增益 0.25–0.35。辅助声音:0.08–0.2。铺底音:约 0.03,在主视觉转场下方压低约 65%。
- 声像跟随画面位置(−1 为左……+1 为右)。连续音效应在立体声场中移动。
- 选定一个调性,并让所有有音高的声音都保持在该调内;随着进度推进,音高逐渐升高,并在重点处解决。(effort 示例中的铺底音和滑块音符为 D 大调,但场景 3 的弹出音和提示音仍为 C 大调。不要照搬这种做法。)
添加生成器
在 sfx/synth.py 中编写一个函数,返回 SR 采样率的浮点数列表。请在文档字符串第一行写明其用途;--list 会显示该信息。生成噪声时使用模块级 random,以确保渲染结果可复现。生成任何轻盈音效时,都应基于 bandnoise() 构建。
验证
npm run sfx # or python3 -m sfx sfx/cues/<video>.py
npm run wave # out/wave.png + loudness of the WAV
npm run build
node scripts/wave.mjs out/effort.mp4 # loudness of what you'll actually post
在 out/wave.png 中,每条珊瑚色线都代表一个时间线节拍。每个瞬态都应落在线上或稍晚一点的位置。若某个声音落在两条线之间,说明使用了硬编码时间或过期 WAV。对于使用单独时间线文件的视频,请传入 --timeline。
可选:生成音频
对于旁白或无法合成的声音,可以使用 ElevenLabs MCP(参见 .mcp.json.example)生成文件到 public/。使用 <Audio src={staticFile(...)} /> 将其放入 <Sequence from={beat * FPS}>。