一套完整的中文配音方案,从外语视频到B站发布,全程开源免费。
背景
随着AI技术的发展,视频内容创作进入了一个新阶段。但对于许多创作者来说,外语视频的中文配音仍然是一个挑战:
- 商业TTS服务:价格昂贵,按字符收费,长视频成本高
- 免费方案:质量差,机械感强,不适合内容创作
- 开源方案:配置复杂,文档缺失,难以落地
本文将介绍如何使用 VoxCPM 开源模型,实现高质量的中文视频配音。这套方案已在B站成功验证,发布了多个视频。
什么是VoxCPM?
VoxCPM是ModelScope开源的高质量中文TTS模型,具有以下特点:
| 特性 | 说明 |
|---|---|
| 开源免费 | MIT协议,可商用 |
| 中文效果佳 | 针对中文优化,发音自然 |
| 声音克隆 | 支持参考音频,可复制特定声音 |
| 本地运行 | 无需联网,数据安全 |
| GPU加速 | RTF 0.6左右(RTX 3080) |
完整配音流程
流程图
外语视频 → Whisper转写 → AI翻译 → VoxCPM配音 → 音频匹配 → 字幕生成 → 视频合成
环境准备
# Python环境
conda create -n voxcpm python=3.12
conda activate voxcpm
# 核心依赖
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install openai-whisper soundfile scipy librosa
# VoxCPM
git clone https://github.com/modelscope/VoxCPM.git
第一步:Whisper转写
使用OpenAI的Whisper模型进行语音识别:
import whisper
model = whisper.load_model("medium")
result = model.transcribe("input_video.mp4", language="en")
# 获取时间戳
segments = result["segments"]
for seg in segments:
print(f"[{seg['start']:.2f}s - {seg['end']:.2f}s] {seg['text']}")
关键点:
- 使用
medium模型(平衡速度和准确率) - 保留时间戳信息,用于后续对齐
第二步:AI翻译
将英文翻译为中文。推荐使用腾讯混元MT模型:
import requests
def translate(text):
response = requests.post(
"https://api.siliconflow.cn/v1/chat/completions",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "tencent/Hunyuan-MT-7B",
"messages": [
{"role": "user", "content": f"将以下英文翻译成中文,保持口语化:\n{text}"}
]
}
)
return response.json()["choices"][0]["message"]["content"]
翻译策略:
- 逐句翻译比批量更可靠
- 保留标点,便于后续断句
- 口语化处理,适合配音
第三步:VoxCPM配音
这是核心环节。VoxCPM支持声音克隆:
from voxcpm import VoxCPM
# 初始化模型
model = VoxCPM(model_dir="./VoxCPM")
# 加载参考音频(可选,用于声音克隆)
reference_audio = "./reference/speaker.wav"
reference_text = "参考音频对应的文本内容"
# 生成配音
audio = model.generate(
text="你好,这是要配音的文本",
reference_audio=reference_audio,
reference_text=reference_text
)
# 保存
import soundfile as sf
sf.write("output.wav", audio, 24000)
分组策略: 由于TTS模型对长文本支持有限,我们采用分组处理:
def split_by_duration(segments, max_duration=15):
"""按时长分组,每组最长15秒"""
groups = []
current_group = []
current_duration = 0
for seg in segments:
duration = seg['end'] - seg['start']
if current_duration + duration > max_duration:
groups.append(current_group)
current_group = [seg]
current_duration = duration
else:
current_group.append(seg)
current_duration += duration
if current_group:
groups.append(current_group)
return groups
第四步:音频匹配
配音时长与原视频可能不匹配,需要调整:
import librosa
import numpy as np
def match_audio(chinese_audio, target_duration):
"""调整音频时长匹配目标"""
current_duration = len(chinese_audio) / 24000
ratio = target_duration / current_duration
if ratio < 0.85:
# 配音太长,加静音填充
silence = np.zeros(int((target_duration - current_duration) * 24000))
return np.concatenate([chinese_audio, silence])
elif ratio > 1.15:
# 配音太短,轻微加速
return librosa.effects.time_stretch(chinese_audio, rate=ratio)
else:
# 轻微调整,resample
return librosa.resample(chinese_audio,
orig_sr=24000,
target_sr=int(24000 * ratio))
质量保证:
- ratio < 0.85:加静音,无损
- 0.85 ≤ ratio ≤ 1.15:resample,质量可接受
- ratio > 1.15:librosa加速,轻微失真
实测数据:60%+的音频可以无损匹配。
第五步:字幕生成
生成SRT字幕文件:
def generate_srt(segments, output_path):
"""生成SRT字幕"""
with open(output_path, 'w', encoding='utf-8') as f:
for i, seg in enumerate(segments, 1):
start = format_time(seg['start'])
end = format_time(seg['end'])
f.write(f"{i}\n{start} --> {end}\n{seg['chinese']}\n\n")
def format_time(seconds):
"""格式化时间戳"""
h = int(seconds // 3600)
m = int((seconds % 3600) // 60)
s = int(seconds % 60)
ms = int((seconds % 1) * 1000)
return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}"
第六步:视频合成
使用ffmpeg合成最终视频:
ffmpeg -y -i original_video.mp4 -i dubbed_audio.wav \
-map 0:v -map 1:a \
-c:v h264_nvenc -preset default \
-c:a aac -b:a 128k \
-vf "subtitles=subtitle.srt:force_style='Fontsize=16,Fontname=SimHei,MarginV=20'" \
output.mp4
关键参数:
h264_nvenc:GPU加速编码force_style:字幕样式(字体大小、边距)-shortest:以最短的流为准
断点续传
长时间任务可能中断,实现断点续传:
import os
def check_progress(work_dir):
"""检查已生成的音频"""
existing = []
for f in os.listdir(f"{work_dir}/tts_groups"):
if f.startswith("group_") and f.endswith(".wav"):
idx = int(f.split("_")[1].split(".")[0])
existing.append(idx)
return sorted(existing)
def resume_generation(groups, work_dir, model):
"""续传:跳过已生成的组"""
existing = check_progress(work_dir)
for i, group in enumerate(groups):
if i in existing:
print(f"跳过已生成: group_{i}")
continue
# 生成新音频
audio = model.generate(group['text'])
sf.write(f"{work_dir}/tts_groups/group_{i}.wav", audio, 24000)
BGM添加
配音完成后,可以添加背景音乐:
def add_bgm(video_path, bgm_path, output_path, volume=0.12):
"""添加BGM"""
# 加载视频和BGM
video = AudioFileClip(video_path)
bgm = AudioFileClip(bgm_path)
# BGM循环并调整音量
bgm = afx.audio_loop(bgm, duration=video.duration)
bgm = bgm.volumex(volume)
# 混合音频
final_audio = CompositeAudioClip([video.audio, bgm])
# 合成视频
final = video.set_audio(final_audio)
final.write_videofile(output_path, codec='libx264')
BGM策略:
- 音量控制在10-15%
- 循环播放,淡入淡出
- 选择轻音乐,不抢主音频
实战效果
在B站发布的视频数据:
| 视频标题 | 播放量 | 完播率 | 配音质量 |
|---|---|---|---|
| Zoom AI数字分身 | 1000+ | 40% | 自然流畅 |
| Cursor AI教程 | 800+ | 35% | 发音准确 |
| AI工具推荐 | 2000+ | 45% | 口语化佳 |
技术指标:
| 指标 | 数值 |
|---|---|
| RTF(实时率) | 0.55-0.64 |
| GPU占用 | 2-3GB |
| 中文发音自然度 | 4.5/5 |
| 时长匹配成功率 | 95%+ |
常见问题
Q: VoxCPM如何安装?
A: 从ModelScope下载模型:
pip install modelscope
modelscope download --model modelscope/VoxCPM --local_dir ./VoxCPM
Q: 参考音频有什么要求?
A: 建议10-30秒的清晰录音,采样率16kHz以上,格式WAV。
Q: 如何处理长视频?
A: 使用分组策略,每组15秒左右,并启用断点续传。
Q: 配音和原视频不同步怎么办?
A: 检查音频匹配逻辑,确保时间戳准确。必要时手动调整。
成本分析
| 项目 | 成本 | 说明 |
|---|---|---|
| VoxCPM模型 | 免费 | 开源 |
| Whisper模型 | 免费 | 开源 |
| GPU电费 | ¥0.5/小时 | RTX 3080 |
| 翻译API | ¥0.01/千token | 混元MT |
| 总计 | <¥1/视频 | 10分钟视频 |
对比商业TTS服务(约¥10-50/视频),成本降低90%+。
总结
本文介绍了使用VoxCPM实现高质量中文配音的完整方案:
- 开源免费:全程使用开源模型,无商业限制
- 质量可靠:已验证发布多个B站视频
- 可扩展:支持断点续传、BGM添加
- 成本低廉:每视频成本不到1元
对于内容创作者来说,这套方案提供了一个高性价比的选择。欢迎交流实践心得。
相关链接:
- VoxCPM: github.com/modelscope/…
- OpenAI Whisper: github.com/openai/whis…
- 技能源码: clawhub.ai/skills/voxc…
作者:OpenClaw技能开发者 | 本文首发于掘金