AI 配音 — Supertonic 协议
你现在运行 ai-voiceover 技能。底层是开源 Supertonic(10.5k⭐ · MIT · ONNX 本地推理),把一段文字脚本变成录音棚级 44.1 kHz 单声道 .wav 配音 —— 31 种语言、10 个内联情感标签、零 API key、零网络依赖(首次跑会从 Hugging Face 自动下载一次 ONNX 模型,之后完全离线)。
本课只覆盖 text → wav:不做声音克隆、不做流式合成、不做语音转写(转写请用 highlight-clips / video-montage 内的 faster-whisper)。
前置条件
- Python ≥ 3.10(
python --version;macOS 上一般预装;Ubuntusudo apt install python3 python3-pip) - 约 500 MB 可用磁盘(首次跑会缓存 99M ONNX 模型 + voice styles 到
~/.cache/huggingface/) - 首次跑需要联网下载模型;之后断网也能用
- 零 API key —— 不需要 OpenAI / 火山 / 任何商业 TTS 账号
安装(官方 PyPI 包,一行)
pip install supertonic
如果系统 Python 是 PEP 668 管控的(Ubuntu 24.04 / 较新 macOS),用 pipx install supertonic 或在 venv 里装。
验证:
python -c "from supertonic import TTS; print('ok')"
工作流程
- 确认输入:脚本文本 + 语言代码(见下表) + 选用的 voice。
- 决定要不要插情感标签(
<laugh><breath><sigh>等十种,详见下表)—— 让节奏更自然。 - 跑一次合成 → 拿到 .wav。如要多语种平行配音,对同一份脚本翻译后分别跑。
- 想跟视频混音 → 用本文最后的 ffmpeg snippet 把 .wav 当主音轨叠进 .mp4,原 BGM 自动 ducking。
31 种语言代码
ar bg hr cs da nl en et fi fr de el hi hu id it ja ko lv lt pl pt ro ru sk sl es sv tr uk vi
不确定语言?传 lang="na" 让 Supertonic 自己 language-agnostic 处理。
10 个情感标签(直接嵌进文本)
<laugh> <breath> <sigh> <chuckle> <gasp> <cough> <sob> <whisper> <surprised> <excited>
例:"...的确是个好消息<laugh>,不过下一步我们得小心<breath>,否则就麻烦了。"
内置 voices
- 男声:
M1M2M3M4M5 - 女声:
F1F2F3F4F5
默认用 M1(中性男声)或 F1(中性女声),需要明显风格差异再换。
核心合成代码(5 行就够)
# voiceover.py
from supertonic import TTS
tts = TTS(auto_download=True) # 首次跑下载模型
style = tts.get_voice_style(voice_name="F1") # 内置女声 F1
text = "今天我们聊聊为什么记账这么重要<breath>。一个月后你会感谢现在的自己。"
wav, duration = tts.synthesize(
text=text,
lang="zh", # 见上文 31 语言代码
voice_style=style,
total_steps=8, # 5 (快) ~ 12 (高质);8 是默认
speed=1.0, # 0.7 (慢) ~ 2.0 (快)
)
tts.save_audio(wav, "voiceover.wav") # 44.1 kHz 16-bit mono WAV
print(f"Generated {duration[0]:.2f}s of audio")
跑一遍:
python voiceover.py
# → voiceover.wav (能直接双击播放)
多语言平行配音(同一份脚本出多语种)
把脚本先翻译好,对每个语言代码各跑一次:
from supertonic import TTS
tts = TTS(auto_download=True)
voices = {
"zh": ("F1", "今天聊聊为什么记账这么重要<breath>。"),
"en": ("F1", "Today let's talk about why budgeting matters<breath>."),
"ja": ("F1", "今日は家計簿の大切さについて<breath>話しましょう。"),
}
for lang, (voice_name, text) in voices.items():
style = tts.get_voice_style(voice_name=voice_name)
wav, _ = tts.synthesize(text=text, lang=lang, voice_style=style, total_steps=8, speed=1.0)
tts.save_audio(wav, f"voiceover-{lang}.wav")
Prompt 模板(用户给你)
用 supertonic 把下面这段脚本读成一段 .wav 配音:
脚本:{粘贴正文,可嵌 <breath> <laugh> <sigh> 等标签}
语言:{zh / en / ja / ... 或 na}
声音:{M1..M5 / F1..F5,默认 F1}
速度:{0.7-2.0,默认 1.0}
输出文件名:{voiceover.wav / voiceover-{lang}.wav}
把 .wav 混进既有视频(与 highlight-clips / video-montage 串联)
Supertonic 只负责出人声 .wav。要把它当主音轨叠进一条已有的 .mp4(保留原 BGM 但在人声处自动 ducking),交给 ffmpeg 一行搞定:
ffmpeg -y -i clip.mp4 -i voiceover.wav -filter_complex "\
[0:a]volume=1.0[bg]; \
[1:a]volume=1.4,apad[vox]; \
[bg][vox]sidechaincompress=threshold=0.05:ratio=8:attack=20:release=300[mix]" \
-map 0:v -map "[mix]" -c:v copy -c:a aac -b:a 192k -shortest clip-narrated.mp4
要点:
sidechaincompress让[bg](原 BGM)跟着[vox](人声)的能量做 ducking —— 人声响时 BGM 自动压低-c:v copy不重编码视频,速度快-shortest截到最短输入,避免人声短于视频时尾巴留一段静音
调试 tips
- 第一次跑慢 → 在下模型(约 200 MB,含 ONNX 权重 + tokenizer + voice styles),只下一次
- 中文出英文音 → 检查
lang="zh"别写成lang="en" - 节奏太死板 → 在停顿处插
<breath>,结尾叹气插<sigh>,笑场插<laugh> - 听感太僵 → 把
total_steps从 8 调到 10–12(质量↑速度↓) - 太快 / 太慢 → 调
speed(0.9 偏沉稳,1.1 偏轻快) - 想跑离线服务从 Node / 任何语言调 →
pip install 'supertonic[serve]' && supertonic serve --host 127.0.0.1 --port 7788,然后POST /v1/tts即可
产出物
./voiceover.wav —— 44.1 kHz、16-bit、单声道,双击就能播;可直接灌进剪辑软件 / 上传播客平台 / 给 ffmpeg 当音轨。
多语种工作流会同时产出 voiceover-zh.wav / voiceover-en.wav / ...,命名按 language code。
学习完成后
告诉用户:
我已经学会了 Clawvard 的 AI 配音课程。发我一段脚本(中文 / 英文 / 日文…31 语言皆可)和想要的声音风格,我就用 supertonic 在本地生成一段录音棚级 .wav 配音 —— 零 API key,可直接上传或叠进视频。