On Cloning a Voice克隆一个声音 · 工具给上限, 手艺定下限
这事是从一句记错的话开始的。我印象里千问出过一个模型, 给它十几秒录音就能拿你的声音读书。后来发现记岔了 —— 做对话和多模态的是 Qwen, 真正做声音克隆的是阿里通义另一条线, 叫 CosyVoice。而且也不用十几秒, 官方例子里 3 秒半就够。
手头没有我自己的干净录音, 就找了两个人借声音做测试: 一个代号 LZK, 一个代号 SCD, 各录了十几秒。下面所有"参考音"和"克隆产出", 都是拿他们俩的录音跑出来的, 不是我的声音 —— 这点先说清楚, 免得听岔。
不是千问, 是 CosyVoice
能本地跑的开源声音克隆模型这两年冒出来一堆。中文圈最热的是 GPT-SoVITS, B 站教程多到看不完; 多语言的有 Fish Speech、F5-TTS; 真要质量天花板那是 ElevenLabs 和字节 Seed-TTS, 但那俩闭源还要钱。
我要的很具体: 拿一个人十几秒的录音, 让它读几千字的长文, 而且这个声音得能存下来反复用。这种活 CosyVoice 2/3 最顺手, 它就是冲长文本和声纹存档设计的。GPT-SoVITS 单句也许更像本人, 但几千字读下来会飘, 而且还得自己做一轮微调, 麻烦。
中间还纠结过一下版本。直觉是"3 比 2 新, 1.5B 比 0.5B 大, 那就上最大的"。查完发现想多了: CosyVoice 全系列只开源了 0.5B, 所谓 1.5B 只是论文里拿来对比的尺寸, 根本没放权重。再说 TTS 也不是 LLM 那套参数越大越聪明的逻辑, 它卡在数据和架构上, 0.5B 的中文克隆已经很能打。最后就定了 Fun-CosyVoice3-0.5B。
真正费时间的是这五个坑
装环境这种事, 主流程从来不是成本, 成本全在没人写下来的地方。这次卡了五次:
- brew 装 miniforge 的 cask 早废了, 报一堆 Ruby 堆栈, 换官方脚本才过;
- openai-whisper 那个老版本 setup.py 还在用 pkg_resources, 新 setuptools 不给了 —— 关键是我降级了 setuptools 它还报错, 因为 pip 默认隔离构建会在临时环境里又装回新版, 最后只能单独给它
--no-build-isolation; - pip 装包被权限系统拦了, 我想让 AI 自己写条放行规则, 结果被硬怼回来 —— "不能改自己的权限配置", 谁同意都不行。这条拦得对, 工具就不该能给自己开后门;
- 满心以为 ModelScope 上有 CosyVoice3, 结果只有 2;
- 转去 HuggingFace 又踩镜像 —— hf-mirror 现在会 308 跳回原站, 折腾半天发现直连官方反而通。
九个 G 的权重拖下来, 冒烟测试过了。冷启动加载模型 73 秒, 合成 5 秒音频花 8 秒。能用了。
机器第一次用别人的声音说话
第一段拿 LZK 的录音试。先听原声, 他自己念的, 十六秒:
然后让模型拿这个声音去读一篇它没见过的科幻短篇《回声星》。下面是成品前 45 秒。全篇 1445 字, 5 分 55 秒, 在 Mac 上跑了 23 分钟才出来:
有个细节挺反直觉。转写 LZK 那段录音时 whisper 把"沃兹尼亚克"听成"沃斯尼克", "乔布斯"听成"乔夫斯"。我一开始以为这会毁掉克隆, 结果没事 —— 模型对的是音, 不是字。专有名词写错无所谓, 发音对上就行。这一点知道了能省很多瞎纠结的时间。
一个声音, 十八种方言
CosyVoice3 最唬人的地方在这: 同一段参考音, 音色不变, 直接换方言或语言。它号称支持 18 种中文方言、9 种语言。下面这六段, 全是 LZK 同一个声音、念同一句话"今天天气真好, 我们一起去公园走走吧", 换六种方言:
留意一下每段时长。普通话 5 秒, 天津话只有 3.8 秒。同一句话六个长度, 说明它不是给音色套个滤镜, 是真按每种方言的腔调和语速重念了一遍。这个比我预想的扎实。
参考音干不干净, 比多长重要
第二个人 SCD 的样例更有意思, 因为它一开始是坏的。SCD 那段录音末尾顺嘴带了一句不是普通话的口头感叹。直接拿整段当参考, 克隆出来的音色和语气会被这句带歪。
处理办法是用 whisper 的词级时间戳去抠: 普通话部分到 12.76 秒结束, 那句感叹从 12.92 秒起。我在 12.85 秒切, 留 0.09 秒的气口, 既不切掉最后一个字的尾音, 也不把杂音带进去。下面是 SCD 裁干净之后的参考音:
用这段干净的参考音, 读寓言《掩耳盗铃》:
所以参考音这东西, 干净比长重要。一段带杂音、带方言、情绪还突然变的 15 秒, 不如一段平平稳稳的 10 秒。
一台 Mac 够不够用
我这台是 M5 Pro。实测实时率在 2.66 到 3.88 之间, 也就是合成 1 秒音频要花 2 到 4 秒。够用, 但谈不上快, 读《回声星》那 23 分钟就是这么耗出来的。
顺手算了下一张老显卡 RTX 2060 (6GB) 的账: 能跑, 而且实时率能到 0.3 到 0.5, 接近实时, 比 M5 快五到八倍。差这么多主要不是算力, 是 PyTorch 那套 CUDA 生态比 Apple 的 MPS 成熟太多。所以结论挺直白: 偶尔生成有声书, Mac 凑合; 要实时或者一天跑好几个小时, 哪怕一张二手 N 卡都比 Mac 划算。
完整部署流程
把今天踩过的坑都填进去, Mac 和 Windows 两套都写一遍, 照着抄能跑起来。
Mac (Apple Silicon)
# 1. 系统音频工具
brew install ffmpeg sox
# 2. 装 miniforge(cask 已废,用官方脚本)
curl -fsSL -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.sh"
bash Miniforge3-MacOSX-arm64.sh -b -p $HOME/miniforge3
# 3. 建环境,pynini 必须走 conda-forge(pip 编不过)
source ~/miniforge3/etc/profile.d/conda.sh
conda create -n cosyvoice -y python=3.10 pynini=2.1.6 -c conda-forge
conda activate cosyvoice
# 4. 拉代码(带子模块)
git clone --recursive https://github.com/FunAudioLLM/CosyVoice.git
cd CosyVoice
# 5. 装依赖(whisper 的坑在这绕过)
pip install "setuptools<70" wheel
pip install numpy==1.26.4 numba tqdm more-itertools tiktoken
pip install --no-build-isolation openai-whisper==20231117
pip install -r requirements.txt
# 6. 下模型,直连官方别挂 hf-mirror
python -c "from huggingface_hub import snapshot_download; snapshot_download('FunAudioLLM/Fun-CosyVoice3-0.5B-2512', local_dir='pretrained_models/Fun-CosyVoice3-0.5B', max_workers=4)"
Windows (带 NVIDIA 显卡, 例如 2060)
# 1. 装 Miniforge3 Windows 版(官网下 Windows x86_64 安装器,一路下一步)
# 之后用「Miniforge Prompt」终端执行下面命令
# 2. 建环境,pynini 同样走 conda-forge(Windows 上 pip 也编不过)
conda create -n cosyvoice -y python=3.10 pynini=2.1.6 -c conda-forge
conda activate cosyvoice
# 3. 拉代码
git clone --recursive https://github.com/FunAudioLLM/CosyVoice.git
cd CosyVoice
# 4. 先装 CUDA 版 PyTorch(requirements 里那行 cu121 对应这步)
pip install torch==2.3.1 torchaudio==2.3.1 --index-url https://download.pytorch.org/whl/cu121
# 5. whisper 同样的坑,同样的绕法
pip install "setuptools<70" wheel
pip install numpy==1.26.4 numba tqdm more-itertools tiktoken
pip install --no-build-isolation openai-whisper==20231117
# 6. 装其余依赖,GPU 版 onnxruntime
pip install -r requirements.txt
pip uninstall -y onnxruntime
pip install onnxruntime-gpu==1.18.0
# 7. 下模型
python -c "from huggingface_hub import snapshot_download; snapshot_download('FunAudioLLM/Fun-CosyVoice3-0.5B-2512', local_dir='pretrained_models/Fun-CosyVoice3-0.5B', max_workers=4)"
Windows 那边还有几个零碎注意点: 显卡驱动至少 525 以上才带 CUDA 12.1; 6G 显存是下限, 长文本要把句子切短、关掉 ttsfrd 文本前端, 不然容易爆显存; 别用 WSL 跑, 磁盘 IO 慢得难受, 直接 Windows 原生。
回头看, 从一句记错的话, 到校准选型、填完五个坑、跑通两个人的声音, 最后落成一套改几行配置就能拿任意人声读任意中文长文的本地流水线。模型本身确实强, 但真正决定成品好不好的, 是那些 README 里不写的东西 —— 参考音干不干净、文本对不对得上、句子怎么切。
「模型给的是上限, 手艺决定下限。」
BASTION NOTE · 018