Files
blind/执行文档_音频素材制作.md
T
xslandClaude Opus 4.6 d03bcb14e4 v2收尾:手势升级 + 暂停退出 + 结局语音化 + 分支补全 + 12条新音频
gestures.js: 新增长按(1s)、两指长按(暂停)、三指点击(退出),支持多指检测
engine.js: REPLY_COUNT变量、长按重播/状态广播、暂停恢复退出机制、
  选择提示音、结局台词预录音频替换TTS、内容预警+心理热线
story.js: MSG-10/11 follow-up补全down(沉默)选项
index.html: 操作指南添加长按/安全手势、内容预警文字
batch_tts_voxcpm.py: 新增12条台词(结局旁白+系统提示+分支NPC反应)
audio/mp3/tts: 12个VoxCPM2生成的林夏声线MP3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-19 23:22:04 +08:00

20 KiB
Raw Blame History

《林夏》音频素材本地制作执行文档

前置文档林夏.md(游戏设计)、SOP_AI音频生产.md(生产规范) 执行环境:本机 WSL2 · RTX 5090 32GB · FFmpeg 7.0 TTS 主链路VoxCPM2(见 林夏.md §7.2),批量脚本 audio/batch_tts_voxcpm.py TTS 备用CosyVoice2-0.5B(见附录 B 目标:按 SOP 规范在本地生产全部音频素材


0. 本机资源清单

资源 路径 / 状态 用途
VoxCPM2 bash /home/xsl/AutoVideo/start-voxcpm.shhttp://127.0.0.1:8000 TTS 主链路(声音克隆 + 合成)
CosyVoice 2.0 (0.5B) /home/xsl/tools/CosyVoice · conda env: cosyvoice TTS 备用(见附录 B
FFmpeg 7.0 /usr/local/bin/ffmpeg 音频格式转换、响度归一化、听筒效果
GPU RTX 5090 32GB 跑 VoxCPM2 / CosyVoice 推理
MuseTalk /home/xsl/work/MuseTalk 注意:这是唇形同步工具,不是 TTS

SOP 中的 MiniMax / 豆包 API 全部替换为本地 VoxCPM2。音乐(Suno)、音效(ElevenLabs SFX)、环境采样(Freesound)仍走云端。 CosyVoice2 保留作为备用方案(见附录 B),仅在 VoxCPM2 表现不佳时切换。


1. 环境部署

1.1 创建项目目录结构

cd /home/xsl/blind
mkdir -p audio/{00_raw/{tts,music,sfx,ambience,ringtone},01_processed/{tts,music,sfx,ambience,ringtone},02_final/{tts,music,sfx,ambience,ringtone},03_qa_reports,99_legal}
mkdir -p voice/{linxia,mom,azhe,xiaomei,zhounan,hr,anan,dorm_a,dorm_b,dorm_c,delivery,system}  # 各角色参考音频

1.2 启动 VoxCPM2 服务

# 启动 VoxCPM2 TTS 服务
bash /home/xsl/AutoVideo/start-voxcpm.sh
# uvicorn 服务: http://127.0.0.1:8000

验证服务可用:

curl -s http://127.0.0.1:8000/docs | head -5
# 应返回 API 文档页面

VoxCPM2 API 接口(详见 林夏.md §7.2):

  • POST /v1/voices — 注册参考音频(wav_base64)→ 返回 voice_id
  • POST /v1/speech — 合成语音(text + voice_id)→ 返回 WAV
  • 输出格式:48kHz 16-bit PCM WAV

1.4 验证 FFmpeg

ffmpeg -version | head -1
# 预期输出: ffmpeg version 7.0.2-static

# 测试 loudnorm 滤镜
ffmpeg -f lavfi -i "sine=frequency=440:duration=1" -af "loudnorm=I=-16:TP=-1:LRA=11" -y /tmp/test_loudnorm.wav
echo "FFmpeg loudnorm 可用"

2. 角色参考音频准备(关键步骤)

VoxCPM2 的声音克隆需要每个角色一段参考音频(WAV 格式)。参考音频的音色决定了最终 TTS 的音色。参考音频存放在 voice/{角色}/ 目录下(详见 林夏.md §7.3 角色音色配置)。

2.1 参考音频来源方案

角色 音色要求 参考音频获取方案
mom 妈妈 50 岁,温柔克制 方案 A:找一位 45-55 岁女性朋友录 15 秒朗读(最佳);方案 B:从影视作品中截取合适片段
azhe 阿哲 27 岁,理性偏冷 从播客/有声书截取年轻男声冷淡片段
xiaomei 小美 24 岁,活泼 找年轻女性朋友录制,或从 vlog 截取
zhounan 周南 26 岁,温和拘谨 播客/有声书截取温和男声
hr HR 王姐 38 岁,知性 新闻女主播或播客截取
anan 安安 23 岁,可爱 年轻女性活泼语调截取
dorm-a/b/c 三个不同年轻女声 需要 3 段风格不同的女声参考
delivery 外卖小哥 30 岁,北方腔 短视频/影视截取
system 系统 中性 AI 女声 VoxCPM2 注册一个中性女声参考音频
self-3y 3年前自己 同 xiaomei 基底 复用 xiaomei 参考音频,调速度和音调

2.2 参考音频制作规格

  • 时长5-20 秒(推荐 10 秒左右)
  • 格式WAV16kHz 以上采样率
  • 内容:完整的中文句子(需同时记录对应文字)
  • 质量:干声为主,避免底噪、混响、BGM

存放路径:voice/{角色代号}/(与 林夏.md §7.3 保持一致)

# 如果参考音频不是 wav 或采样率不对,用 FFmpeg 转换
ffmpeg -i input.mp3 -ar 16000 -ac 1 voice/mom/ref.wav

2.3 创建参考音频记录表

voice/ 下创建 ref_manifest.txt,记录每条参考音频对应的文字:

mom/ref.wav | 今天天气不错,妈妈给你做了红烧排骨,等你回来吃饭。
azhe/ref.wav | 好的,我知道了,那件事明天再说吧。
xiaomei/ref.wav | 哎你猜怎么着,今天路上遇到一个超级搞笑的事!
zhounan/ref.wav | 嗯,其实我也不太确定,就是觉得应该跟你说一声。
hr/ref.wav | 好的,那我们下周三前把流程走完,有什么问题随时联系我。
anan/ref.wav | 天呐天呐你快来!这边超级好玩的!
dorm_a/ref.wav | 嘿你们看看我,今天升职了!请大家吃饭!
dorm_b/ref.wav | 恭喜恭喜啊,太厉害了,我就知道你行的。
dorm_c/ref.wav | 嗯,不错,对了夏夏怎么不说话啊。
delivery/ref.wav | 你好你的外卖到了,放门口了啊,麻辣烫注意别洒了。

3. TTS 生产流程

3.1 VoxCPM2 声音克隆流程

前置:确认 VoxCPM2 服务已启动(§1.2)。

单条合成步骤

  1. 将角色参考音频注册为 voice_id:POST /v1/voiceswav_base64
  2. 调用合成接口:POST /v1/speechtext + voice_id
  3. 获得 48kHz 16-bit PCM WAV
  4. 用 FFmpeg atempo 调速(按 林夏.md §7.3 各角色语速配置)
  5. 保存到 audio/00_raw/tts/

角色音色目录(与 林夏.md §7.3 一致):

voice/
├── linxia/     # 林夏(speed 1.00
├── mom/        # 妈妈(speed 0.92
├── azhe/       # 阿哲(speed 1.05
├── xiaomei/    # 小美(speed 1.10,醉态 0.95
├── zhounan/    # 周南(speed 0.95
├── hr/         # HR 王姐(speed 1.00
├── anan/       # 安安(speed 1.15
├── dorm_a/     # 室友 Aspeed 1.10
├── dorm_b/     # 室友 Bspeed 1.00
├── dorm_c/     # 室友 Cspeed 0.95
└── delivery/   # 外卖小哥(speed 1.20

3.2 用批量脚本生产(主力方式)

使用项目自带的 VoxCPM2 批量合成脚本:

# 确保 VoxCPM2 服务已启动
bash /home/xsl/AutoVideo/start-voxcpm.sh

# 批量合成所有台词
python audio/batch_tts_voxcpm.py --source voice

# 只合成特定角色
python audio/batch_tts_voxcpm.py --source voice --role linxia

# 干跑查看任务列表
python audio/batch_tts_voxcpm.py --source voice --dry-run

脚本读取 voice/ 目录下的参考音频,按 林夏.md §7.3 角色配置自动注册 voice_id 并批量合成。输出到 audio/00_raw/tts/

3.3 长戏分段处理

SOP §5.3 规定:超过 30 秒的台词必须分段录制

妈妈 4'17" 长语音(第 16 条)分 8 段

段号 文件名 台词 情绪提示
1 lv11_0200_mom_voice_01_seg1 "夏夏。妈妈知道你今天电话不接。妈妈不催你,就是想跟你说一件事。" gentle, hesitant
2 lv11_0200_mom_voice_01_seg2 "你24了对吧。妈妈24那年——你应该没听我说过——" gentle, nostalgic
3 lv11_0200_mom_voice_01_seg3 "那时候妈妈在广州,给一个香港老板做秘书,1995年。那年我也被分手过。也被开除过。一模一样的春天。" gentle, sad but holding back
4 lv11_0200_mom_voice_01_seg4 "那年我哭得特别难看。后来呢?后来就没什么后来了。我回了老家,认识了你爸,生了你。" gentle, releasing
5 lv11_0200_mom_voice_01_seg5 "我跟你说这个不是想跟你说什么都会过去——我想跟你说,那年夏天我没死,是因为我外婆每天晚上都给我打一个电话。" gentle, emotional
6 lv11_0200_mom_voice_01_seg6 "她不说什么,就问我今天吃饭了没。" gentle, peaceful
7 lv11_0200_mom_voice_01_seg7 "我现在打给你,你不接也没事。妈妈给你发个语音,你什么时候想听就听。你不用回我。" gentle, tender
8 lv11_0200_mom_voice_01_seg8 "你今天接了好多电话吧。妈妈不打扰你了。晚安。" gentle, almost smiling

每段单独合成后用 FFmpeg 拼接(见 §4.3)。

小美醉语音(第 09 条)分 4 段,speed 调低到 0.95,每段间加长停顿。

周南 4 段长讲述(第 13 条) 每段独立合成,段间留 800ms 静音。

3.4 系统 TTS

系统提示音(播报状态、念选项等)用 VoxCPM2 注册一个中性女声参考音频:

  1. 准备一段清晰的中性女声参考音频(如新闻播报片段),存入 voice/system/
  2. 通过 POST /v1/voices 注册为 system voice_id
  3. POST /v1/speech 合成所有系统语句

系统语句示例:

  • "阿哲,发来1条语音。8秒。"
  • "是否回复?"
  • "一,好,明天寄。二,你怎么不自己来拿。三,你那边都好吗。四,什么都不说。"
  • "妈妈3条未读、小美1条已读、阿哲1条未播放"

3.5 self-3y 三版预录

使用与 xiaomei 同基底参考音频,但调整 speed 为 +0.05(即 1.15):

版本 文件名 内容要求 情绪
明朗版 lv11_0030_self-3y_voice_01 3 年前刚来北京,对一切新鲜 兴奋带紧张
迷茫版 lv11_0030_self-3y_voice_02 3 年前已经累了 假装坚强
温柔版 lv11_0030_self-3y_voice_03 写给未来的自己 平静有力

台词需要编剧写好,每版约 50 秒。


4. 后期处理(FFmpeg

4.1 单条 TTS 标准处理链

# 变量
INPUT="audio/00_raw/tts/lv11_2103_mom_call_01_v1.wav"
OUTPUT="audio/01_processed/tts/lv11_2103_mom_call_01_v1.wav"

# 完整处理链(一条命令):
# [1] 高通 80Hz 去低频噪
# [2] 压缩器 4:1
# [3] 响度归一化到 -16 LUFS
# [4] 限制峰值 -1 dBTP
ffmpeg -i "$INPUT" \
  -af "highpass=f=80,\
acompressor=threshold=-18dB:ratio=4:attack=20:release=250,\
loudnorm=I=-16:TP=-1:LRA=11,\
alimiter=limit=0.891" \
  -ar 48000 -sample_fmt s16 -ac 1 \
  -y "$OUTPUT"

4.2 加听筒效果(电话 / 微信语音形态)

INPUT="audio/01_processed/tts/lv11_2103_mom_call_01_v1.wav"
OUTPUT="audio/01_processed/tts/lv11_2103_mom_call_01_v1_phone.wav"

# 模拟手机听筒: HPF 300Hz + LPF 3.4kHz + 轻微饱和
ffmpeg -i "$INPUT" \
  -af "highpass=f=300:poles=2,\
lowpass=f=3400:poles=2,\
equalizer=f=1500:t=q:w=1:g=1,\
acompressor=threshold=-20dB:ratio=3:attack=5:release=50" \
  -y "$OUTPUT"

例外mom 第 16 条 4'17" 长语音不加听筒效果——SOP 设计意图是"完整音质版"。

4.3 长戏分段拼接

# 1. 先给每段加 200ms 静音头尾
for seg in audio/00_raw/tts/lv11_0200_mom_voice_01_seg*.wav; do
  ffmpeg -i "$seg" \
    -af "adelay=200|200,apad=pad_dur=0.2" \
    -y "${seg%.wav}_padded.wav"
done

# 2. 生成拼接文件列表
ls audio/00_raw/tts/lv11_0200_mom_voice_01_seg*_padded.wav | \
  sed "s/^/file '/" | sed "s/$/'/" > /tmp/concat_list.txt

# 3. 拼接 + crossfade
ffmpeg -f concat -safe 0 -i /tmp/concat_list.txt \
  -af "acrossfade=d=0.05:c1=tri:c2=tri" \
  -y audio/00_raw/tts/lv11_0200_mom_voice_01_full.wav

# 注意:FFmpeg concat + acrossfade 只支持两个输入。
# 多段拼接需要逐段 crossfade,或直接 concat 后人工检查接缝。
# 推荐方案:先 concat 拼接,段间 200ms 静音已经足够自然。
ffmpeg -f concat -safe 0 -i /tmp/concat_list.txt \
  -c copy \
  -y audio/00_raw/tts/lv11_0200_mom_voice_01_full.wav

4.4 批量后期处理脚本

#!/bin/bash
# 批量处理 00_raw/tts/ → 01_processed/tts/
# 用法: bash audio/process_tts.sh

for f in audio/00_raw/tts/lv11_*.wav; do
  basename=$(basename "$f")
  output="audio/01_processed/tts/$basename"

  # 跳过已处理的
  [ -f "$output" ] && echo "跳过: $basename" && continue

  echo "处理: $basename"
  ffmpeg -i "$f" \
    -af "highpass=f=80,\
acompressor=threshold=-18dB:ratio=4:attack=20:release=250,\
loudnorm=I=-16:TP=-1:LRA=11" \
    -ar 48000 -sample_fmt s16 -ac 1 \
    -y "$output" 2>/dev/null

  echo "  → $output"
done

echo "TTS 后期处理完成"

4.5 最终打包(wav → ogg

#!/bin/bash
# 01_processed → 02_final (ogg Vorbis q=5)
for f in audio/01_processed/tts/*.wav; do
  basename=$(basename "${f%.wav}.ogg")
  output="audio/02_final/tts/$basename"
  ffmpeg -i "$f" -c:a libvorbis -q:a 5 -y "$output" 2>/dev/null
done
echo "OGG 打包完成"

4.6 角色专属后期(按 SOP §4.2 配置卡)

# mom: 高频衰减 -3dB + 轻 reverb
ffmpeg -i input.wav -af "equalizer=f=5000:t=h:w=2000:g=-3" -y output.wav

# azhe: 中频衰减 -2dB"闷"感)
ffmpeg -i input.wav -af "equalizer=f=2000:t=q:w=1:g=-2" -y output.wav

# delivery: 低频衰减 -6dB(模拟听筒)
ffmpeg -i input.wav -af "equalizer=f=200:t=h:w=200:g=-6" -y output.wav

# self-3y: 高频衰减 -2dB + 底噪(录音笔质感)
ffmpeg -i input.wav \
  -af "equalizer=f=5000:t=h:w=2000:g=-2" \
  -y output.wav
# 底噪可以后续叠加一层轻微白噪声

5. 音乐素材(Suno

音乐生产仍走 Suno 云端,按 SOP §6 操作。

5.1 操作步骤

  1. 登录 Suno(需要 Pro 订阅)
  2. 选 Custom Mode
  3. 按 SOP §6.2 的 4 段曲 Prompt 生成
  4. 每段跑 2 轮(出 4 首候选),选最佳
  5. 用 Extend 延长到目标时长
  6. 下载 WAV 格式到 audio/00_raw/music/

5.2 铃声生成

按 SOP §6.3 的 9 个角色铃声 Prompt 在 Suno 生成。 下载到 audio/00_raw/ringtone/

5.3 音乐后期处理

# 音乐处理: 削 AI 浊感 + 响度 -18 LUFS
for f in audio/00_raw/music/*.wav; do
  basename=$(basename "$f")
  ffmpeg -i "$f" \
    -af "equalizer=f=350:t=q:w=1.5:g=-2,\
loudnorm=I=-18:TP=-1:LRA=11" \
    -ar 48000 \
    -y "audio/01_processed/music/$basename" 2>/dev/null
done

6. 音效素材(ElevenLabs SFX

6.1 操作步骤

  1. 登录 ElevenLabsCreator 订阅,含 Sound Effects
  2. 按 SOP §7.2 的 Prompt 逐条生成
  3. 每条跑 3 次,挑最佳
  4. 下载后转 WAV
    # ElevenLabs 默认 mp3,转为 wav
    for f in audio/00_raw/sfx/*.mp3; do
      ffmpeg -i "$f" -ar 48000 -y "${f%.mp3}.wav" && rm "$f"
    done
    

6.2 音效后期

# 短音效响度 -14 LUFS
for f in audio/00_raw/sfx/*.wav; do
  basename=$(basename "$f")
  ffmpeg -i "$f" \
    -af "loudnorm=I=-14:TP=-1:LRA=11" \
    -ar 48000 \
    -y "audio/01_processed/sfx/$basename" 2>/dev/null
done

7. 环境底噪(Freesound

7.1 操作步骤

  1. 按 SOP §8.1 的清单在 Freesound 搜索
  2. 过滤:CC0 优先,≥ 44.1kHz,下载 WAV
  3. 文件名加 Freesound ID:如 amb_apartment_night_fs123456.wav
  4. 立刻登记到版权表

7.2 环境底噪后期

# 环境底噪处理: HPF 60Hz + LPF 12kHz + 响度 -22 LUFS
for f in audio/00_raw/ambience/*.wav; do
  basename=$(basename "$f")
  ffmpeg -i "$f" \
    -af "highpass=f=60,lowpass=f=12000,\
loudnorm=I=-22:TP=-3:LRA=11" \
    -ar 48000 -ac 2 \
    -y "audio/01_processed/ambience/$basename" 2>/dev/null
done

7.3 单声道转假性立体声

# 如果下载到的是单声道,做假性立体声
INPUT="audio/01_processed/ambience/amb_apartment_night.wav"
OUTPUT="audio/01_processed/ambience/amb_apartment_night_stereo.wav"

ffmpeg -i "$INPUT" \
  -filter_complex "\
[0:a]asplit=2[L][R];\
[R]adelay=12|12,equalizer=f=8000:t=q:w=1:g=1[Rd];\
[L][Rd]amerge=inputs=2[out]" \
  -map "[out]" -ac 2 \
  -y "$OUTPUT"

8. QA 验收

8.1 响度检查脚本

#!/bin/bash
# 检查所有已处理音频的响度
echo "=== TTS 响度检查 (目标 -16 LUFS) ==="
for f in audio/01_processed/tts/*.wav; do
  result=$(ffmpeg -i "$f" -af "loudnorm=print_format=json" -f null - 2>&1 | \
    grep -A1 '"input_i"' | tail -1 | tr -d ' ",' | cut -d: -f2)
  echo "  $(basename "$f"): ${result} LUFS"
done

echo ""
echo "=== 音乐响度检查 (目标 -18 LUFS) ==="
for f in audio/01_processed/music/*.wav; do
  result=$(ffmpeg -i "$f" -af "loudnorm=print_format=json" -f null - 2>&1 | \
    grep -A1 '"input_i"' | tail -1 | tr -d ' ",' | cut -d: -f2)
  echo "  $(basename "$f"): ${result} LUFS"
done

echo ""
echo "=== 环境底噪响度检查 (目标 -22 LUFS) ==="
for f in audio/01_processed/ambience/*.wav; do
  result=$(ffmpeg -i "$f" -af "loudnorm=print_format=json" -f null - 2>&1 | \
    grep -A1 '"input_i"' | tail -1 | tr -d ' ",' | cut -d: -f2)
  echo "  $(basename "$f"): ${result} LUFS"
done

8.2 验收流程

  1. 自检:跑响度检查脚本,确认所有文件在目标范围 ±1 LUFS
  2. 单条听感:用耳机逐条听,标记不满意的(记录到 03_qa_reports/
  3. 上下文听感:把同一时间段的所有音频按时间轴拼起来完整听一遍
  4. 不满意的重做:回到 §3 重新合成,调参或换参考音频

9. 执行顺序总结

第 1 步 · 启动 VoxCPM2 + 部署环境 (§1)
    ↓    约 30 分钟
第 2 步 · 准备参考音频到 voice/ (§2)  ← 这一步最关键,音色质量取决于此
    ↓    约 1-3 天(需要找人录音或搜集素材)
第 3 步 · 系统 TTS 先行 (§3.4)       ← 最简单的先跑通 VoxCPM2 流程
    ↓    约 1 小时
第 4 步 · 短台词批量生产 (§3.2 batch_tts_voxcpm.py)
    ↓    约 3-4 小时
第 5 步 · 长戏分段录制 (§3.3)
    ↓    约 2-3 小时
第 6 步 · 后期处理 (§4)
    ↓    约 2-3 小时
第 7 步 · 铃声 + 音乐 (§5)         ← 可与 TTS 并行
    ↓    约 3 小时
第 8 步 · 音效 (§6)                ← 可与 TTS 并行
    ↓    约 3 小时
第 9 步 · 环境底噪 (§7)            ← 可与 TTS 并行
    ↓    约 2 小时
第 10 步 · QA 验收 (§8)
    ↓    约 4-6 小时
第 11 步 · 最终打包 (§4.5)
    ↓    约 30 分钟
完成

附录 A · 常见问题

Q: VoxCPM2 生成的语音有电流声/杂音? A: 检查参考音频质量。参考音频必须干净无噪,采样率 ≥ 16kHz。

Q: 语速不自然? A: 用 FFmpeg atempo 调速(范围 0.5-2.0)。如果调速后音质下降,改为在合成文本中加标点控制节奏(句号=长停顿,逗号=短停顿)。

Q: 怎样让同一个音色听起来"醉了"? A: TTS 通常没有情绪控制参数。替代方案:

  1. 在文本中插入省略号、重复字来模拟口齿不清
  2. 后期用 FFmpeg 轻微变速+加混响:
    ffmpeg -i drunk.wav -af "atempo=0.95,aecho=0.8:0.7:40:0.3" -y drunk_fx.wav
    

Q: VoxCPM2 服务无法启动? A: 确认 bash /home/xsl/AutoVideo/start-voxcpm.sh 正常。确认 GPU 可用:nvidia-smi

Q: 生成很慢? A: RTX 5090 应该很快(远超实时)。如果慢,检查是否误用了 CPU。


附录 B · CosyVoice2 备用方案

仅在 VoxCPM2 表现不佳或不可用时使用。 正常生产流程请走 §1-§3 的 VoxCPM2 主链路。

B.1 环境验证

conda activate cosyvoice
cd /home/xsl/tools/CosyVoice
python -c "
import sys
sys.path.append('third_party/Matcha-TTS')
from cosyvoice.cli.cosyvoice import CosyVoice2
model = CosyVoice2('pretrained_models/CosyVoice2-0.5B')
print('CosyVoice2 加载成功,采样率:', model.sample_rate)
"

B.2 WebUI 启动

conda activate cosyvoice
cd /home/xsl/tools/CosyVoice
python webui.py --port 8001  # 注意:用 8001 避免与 VoxCPM2 的 8000 端口冲突

模式选择:3s极速复刻(上传参考音频 + 对应文字 → 合成)。

B.3 批量脚本

CosyVoice2 版批量脚本为 audio/batch_tts.py(区别于主力脚本 audio/batch_tts_voxcpm.py)。 用法:conda activate cosyvoice && python audio/batch_tts.py