跳到主要内容

语音转换 / 声音克隆

DiffVC 本地部署:一张 32GB 老卡就够,难的是那份 2022 年的依赖

华为诺亚方舟实验室的 ICLR 2022 Oral 官方实现,约 1.26 亿参数,整套推理权重加起来不到 0.6GB。10 秒音频、30 步 ml 采样的峰值显存在 2GB 上下——显存从来不是这个模型的瓶颈。

DiffVC 是论文《Diffusion-Based Voice Conversion with Fast Maximum Likelihood Sampling Scheme》(ICLR 2022 Oral)的官方实现,代码在 huawei-noah/Speech-Backbones 仓库的 DiffVC 子目录下,MIT 授权。它做的是 any-to-any 一次性语音转换:给一段源语音,再给一段几秒钟的目标说话人参考音频,直接把音色换过去,源说话人和目标说话人都不需要出现在训练集里。结构上分两级——一个 846 万参数的“平均音色”编码器把 mel 谱压成剥离个人音色的中间表示,再由一个 1.178 亿参数的二维 U-Net 扩散解码器在目标说话人条件下反扩散重建 mel,最后交给 HiFi-GAN 出波形。DiffVC 本体合计约 1.26 亿参数,fp32 权重约 0.5GB,推理时 notebook 会用 generator.nparams 把这个数直接打出来。

这个模型真正稀缺的资源不是显存,是耐心。10 秒音频、n_timesteps=30、mode='ml' 的一次转换峰值显存也就 2GB 上下,30 秒长句 3~4GB——U-Net 把 80×T 的 mel 当成一张二维图去卷,显存基本随片长线性涨,唯一会 OOM 的场景是你一口气塞进去几分钟的整段录音。麻烦全在环境:仓库里那份 requirements.txt 钉死了 torch==1.7.1、torchaudio==0.5.1、librosa==0.6.0、numpy==1.19.0,其中 torchaudio 0.5.1 根本不是 torch 1.7.1 的配对版本,librosa 0.6 在今天的 numba/numpy 上装都装不上。更要命的是 torch 1.7.1 的 cu110 wheel 只编到 sm_80,RTX 3090/A10/A6000(sm_86)、RTX 4090(sm_89)、RTX 5090(sm_120)、H100/H200(sm_90)全都会甩出 no kernel image is available 或架构不兼容告警。

那还值不值得现在部署 DiffVC?看你在意什么。后来的扩散语音转换基本都从它身上长出来:AAAI 2024 的 DDDM-VC 在致谢里明写扩散部分的代码取自 DiffVC,但它的授权是 CC BY-NC-SA 4.0,商用免谈;风头更劲的 Seed-VC 是 GPL-3.0,而且仓库已经变成 Public archive 不再更新。DiffVC 这边,本体、HiFi-GAN、说话人编码器三块在 THIRD_PARTY_NOTICE 里逐条列明全是 MIT,Speech-Backbones 仓库至今没有归档。要做基线复现、要改架构、要拿去商用,它依然是最省事的那个起点——前提是你肯花一小时把 2022 年的依赖翻新一遍。

01 —

权重清单:DiffVC 不是一个文件,是四个

跑通一次转换要同时装好转换模型、平均音色编码器、声码器和说话人编码器,缺一个都出不了声

版本参数量显存上下文说明
Diff-LibriTTS(vc_libritts_wodyn.pt)126M(编码器 8.46M + 扩散解码器 117.8M)fp32 权重 ~0.5GB;10 秒句子 30 步推理峰值 ~2GB22.05kHz · 80 mel · n_fft 1024 · hop 256 · n_timesteps=30官方默认权重,LibriTTS 约 1100 位说话人训练,any-to-any 首选。文件名里的 wodyn 是论文条件方式消融中胜出的那一档:说话人 embedding 加上加噪后的目标 mel,不喂整条扩散轨迹。
Diff-VCTK126M,与 LibriTTS 版同结构fp32 权重 ~0.5GB,推理占用同上22.05kHz · 80 mel · hop 256VCTK 109 位说话人训练,其中 99 位在论文里被留作 unseen 测试集。录音棚干声、英式口音场景更贴;论文的条件方式消融里 wodyn 在 VCTK 上把说话人相似度推到 46.7%。
平均音色编码器 enc.pt(FwdDiffusion)8.46M(MelEncoder 6.84M + PostNet 1.62M)fp32 ~34MB6 层 Transformer,channels 192、filters 768、2 头、相对位置窗口 4训练解码器之前必须先有它。要么下官方 LibriTTS 版丢进 logs_enc/,要么自己跑 Montreal Forced Aligner 出 TextGrid、用 get_avg_mels.ipynb 造平均音色 mel 再跑 train_enc.py。train_dec.py 里 Adam 只挂在 model.decoder.parameters() 上,编码器全程冻结。
HiFi-GAN universal_v1 声码器~14Mfp32 ~56MB22.05kHz 输出;mel 滤波器组 fmin=0、fmax=8000DiffVC 只产 mel,波形完全靠它,取自 jik876/hifi-gan 的通用权重,MIT 授权。注意 mel basis 的 fmax 卡在 8kHz——8kHz 以上的齿音细节本来就不在建模范围内,别指望它还原。
GE2E 说话人编码器 checkpts/spk_encoder/pretrained.pt~1.4M(3 层 LSTM,hidden 256,输出 256 维 embedding)fp32 ~6MB16kHz · 40 mel · 25ms 窗 / 10ms 步 · 1.6 秒 partial唯一随仓库直接下发、不用去 Google Drive 拉的权重,来自 Real-Time-Voice-Cloning。它跑的是另一套前端:webrtcvad 切静音、归一化到 -30 dBFS、重采样到 16kHz——和 DiffVC 主体的 22.05kHz 前端是两条独立管线,改采样率时两边都要动。

02 —

GPU 选型:对 CUDA 架构比对显存更要紧

DiffVC 全程 fp32,选卡前先把计算能力和你打算用的 torch 版本对齐

  • 先试听效果,或批量转换几百上千条 10 秒以内的语音

    Tesla V100 32GB$0.188/卡·时

    全表最便宜的一张卡,还给到 32GB;sm_70 正好落在 torch 1.7.1+cu110 官方 wheel 的架构列表里,是少数几张照抄 requirements.txt 也能直接跑起来的卡。

  • 按官方默认复现解码器训练(batch_size=32、train_frames=128、全程 fp32)

    RTX 3090 24GB$0.193/卡·时

    Adam 只优化 1.178 亿参数的解码器,权重加梯度加一阶二阶动量固定占约 1.9GB,剩下全是激活;24GB 刚好吃下默认配置,注意 sm_86 需要把 torch 升到 1.8+/cu111 以上。

  • 整段 3 分钟以上录音一次性转换不切片,或把 batch_size 拉到 64 重训

    RTX A6000 48GB$0.817/卡·时

    U-Net 显存随 mel 帧数线性上涨,48GB 的余量让你不必写切片和拼接逻辑,顺带把片段边界的音色漂移问题一起省掉。

  • 翻新到 torch 2.x,把 30 步反扩散做成常驻批量服务

    RTX 4090 24GB$0.540/卡·时

    论文在 GPU 上给出 ML-30 的 RTF 约 0.5、ML-6 约 0.1,换到 Ada 架构上只会更好;24GB 足够让 DiffVC、HiFi-GAN、说话人编码器同时常驻再开并发。

03 —

四步在 NexGPU 上把 DiffVC 跑起来

从开机到听见第一段转换音频,卡上的时间不超过二十分钟

  1. 01

    开一台带 CUDA 的实例,拉代码

    在 console.nexgpu.net 选卡,先试水就用 Tesla V100 32GB($0.188/卡·时),镜像从 2000+ 预置里挑现成的 PyTorch。按秒计费、无最低消费、不用申请配额,SSH/Jupyter/Web 终端都通。DiffVC 的官方入口本来就是一个 notebook,直接用 Jupyter 最顺手。注意仓库是整个 Speech-Backbones,DiffVC 只是其中一个子目录,同级还有 Grad-TTS 和 SPIRAL。

    git clone https://github.com/huawei-noah/Speech-Backbones.git && cd Speech-Backbones/DiffVC
  2. 02

    别照抄 requirements.txt

    那份依赖是 2022 年钉死的:torch==1.7.1 配 torchaudio==0.5.1(这两个版本本身就对不上),librosa==0.6.0、numpy==1.19.0 在今天装都装不上。装当前版本,然后只改两处调用:inference.ipynb 里的 mel_basis = librosa_mel_fn(22050, 1024, 80, 0, 8000) 在 librosa 0.10+ 必须改成关键字写法 librosa.filters.mel(sr=22050, n_fft=1024, n_mels=80, fmin=0, fmax=8000);librosa.core.load 与 librosa.core.stft 换成 librosa.load 与 librosa.stft。模型代码本身是纯 PyTorch 加 einops,在 torch 2.x 上零改动。

    pip install torch torchaudio einops 'librosa>=0.10' numpy scipy webrtcvad tgt tqdm
  3. 03

    补齐两个 checkpoint,第三个仓库自带

    checkpts/spk_encoder/pretrained.pt 随仓库下发,不用管。要下的是 checkpts/vc/ 下的转换模型(LibriTTS 版 Drive ID 18Xbme0CTVo58p2vOHoTQm8PBGW7oEjAy,VCTK 版 12s9RPmwp9suleMkBCVetD8pub7wsDAy4)和 checkpts/vocoder/ 下的 HiFi-GAN 通用声码器(Drive ID 10khlrM645pTbQ4rc2aNEYPba8RFDBkW-)。声码器那份解开后要让 checkpts/vocoder/ 里同时有 config.json 和 generator 两个文件,notebook 是按这两个名字读的。想自己重训解码器的话,编码器权重 Drive ID 是 1JdoC5hh7k6Nz_oTcumH0nXNEib-GDbSq,放进 logs_enc/。

    pip install gdown && mkdir -p checkpts/vc checkpts/vocoder && gdown 18Xbme0CTVo58p2vOHoTQm8PBGW7oEjAy -O checkpts/vc/vc_libritts_wodyn.pt
  4. 04

    跑一次转换,然后修掉 notebook 里那行 bug

    推理是两次前向:DiffVC 出 mel,HiFi-GAN 出波形,源音频和参考音频各走一遍 get_mel,参考音频还要多走一遍 get_embed 拿 256 维说话人向量。跑通之后一定要回头看转换那个 cell——mel_synth_np 和 mel_source_np 两行取的都是 mel_,后一行本该是 mel_source。结果就是紧接着的 mel_spectral_subtraction 拿合成 mel 去减它自己,那步底噪抑制完全空转。把它改成 mel_source.cpu().detach().squeeze().numpy() 再听一遍,沙沙声会明显收敛。

    mel_encoded, mel_ = generator.forward(mel_source, mel_source_lengths, mel_target, mel_target_lengths, embed_target, n_timesteps=30, mode='ml')

算笔账:两小时转完 1000 句,和一周复现官方训练

先说便宜的一头。论文在 GPU 上给出 ML-30 的 RTF 约 0.5,也就是 10 秒音频大约占 5 秒 GPU 时间;1000 条 10 秒语音的纯转换约 5000 秒,加上 mel 与 speaker embedding 预处理、模型加载,按 2 小时算——Tesla V100 32GB 是 2 × $0.188 = $0.376。 再说重的一头。train_dec.py 默认 epochs=110、batch_size=32、learning_rate=1e-4,在 RTX 3090 24GB 上按 72 小时(3 天)估:72 × $0.193 = $13.90。数据是大头:论文说训练用了约 1100 位说话人,而 LibriTTS 的 train-clean-100 加 train-clean-360 正好 1151 位、约 245 小时;重采样到 22.05kHz 的 wavs 约 39GB,预先算好的 mel(80 × T 的 float32)约 24GB,speaker embeds 可以忽略,合计约 65GB。按 $0.414/GB·月 存一周是 65 × 0.414 × 7/30 ≈ $6.28。 还有一笔最容易被忽略的。train_dec.py 里 save_every=1,每个 epoch 都会 torch.save 一份完整 state_dict,一份约 0.5GB,110 个 epoch 就是 55GB,一周存储 55 × 0.414 × 7/30 ≈ $5.31。一周总账 $13.90 + $6.28 + $5.31 ≈ $25.49,训练算力只占五成半。这也正是 NexGPU 计费上要提醒的一点:实例一停,算力立刻停止计费,但存储卷会一直计到你销毁为止——训练跑完记得只留最后几个 checkpoint,把数据卷清掉再走。

04 —

常见问题

DiffVC 本地部署需要多大显存?24GB 的卡够不够?

推理绰绰有余。DiffVC 本体约 1.26 亿参数,加上 HiFi-GAN 与说话人编码器,fp32 权重合计不到 0.6GB;10 秒音频、30 步 ml 采样峰值约 2GB,30 秒长句 3~4GB。因为 U-Net 把 80×T 的 mel 当二维图处理,显存随片长线性增长,真正的上限是你一次喂多长。训练是另一回事:官方默认 batch_size=32、train_frames=128(约 1.49 秒的 mel 片段)、全程 fp32,24GB 刚好够,16GB 卡要把 batch_size 降到 8~12。NexGPU 上 Tesla V100 32GB $0.188/卡·时 跑推理、RTX 3090 24GB $0.193/卡·时 跑训练,按秒计费,直接开机验证比估算更快。

DiffVC 是不是已经过时了?现在还有必要自己部署吗?

它没有被官方废弃,Speech-Backbones 仓库至今没有归档。后来的工作确实更强,但授权都更紧:AAAI 2024 的 DDDM-VC 在致谢里明写扩散部分的代码取自 DiffVC,可它是 CC BY-NC-SA 4.0,商用不行;Seed-VC 更热闹,v1 有 25M/98M/200M 三档、v2 是 157M 的 hubert-bsqvae-small,但它是 GPL-3.0,而且仓库已经转成 Public archive。DiffVC 这边,本体、HiFi-GAN、说话人编码器三块在 THIRD_PARTY_NOTICE 里逐条列明全是 MIT,是同类里最好落地的一份。要做基线对比、要改架构、要拿去商用,它仍然是最省事的起点。在 NexGPU 上开一张卡验证一晚,成本比读一晚上 issue 低得多。

照着 requirements.txt 装完跑不起来,librosa 和 torch 一直报错怎么办?

那份依赖是 2022 年钉的,torchaudio==0.5.1 本来就不是 torch==1.7.1 的配对版本,librosa==0.6.0 在今天的 numba/numpy 上根本装不上。正确做法是装当前版本的 torch 与 librosa,然后只改两处调用:mel_basis = librosa_mel_fn(22050, 1024, 80, 0, 8000) 要改成关键字写法 librosa.filters.mel(sr=22050, n_fft=1024, n_mels=80, fmin=0, fmax=8000),librosa.core.load 与 librosa.core.stft 换成 librosa.load 与 librosa.stft。模型代码是纯 PyTorch + einops,torch 2.x 下不用动。NexGPU 有 2000+ 预置镜像,直接选 PyTorch 那档,环境这一层基本已经替你铺好了。

为什么在 RTX 4090/5090/H100 上装 torch 1.7.1 直接报 no kernel image?

因为 torch 1.7.1 的 cu110 wheel 最高只编到 sm_80。Tesla V100 是 sm_70、Tesla T4 是 sm_75、A100 是 sm_80,都在覆盖范围内;RTX 3090/A10/A6000 是 sm_86,RTX 4090 是 sm_89,H100/H200 是 sm_90,RTX 5090 是 sm_120,全都不在。要么老老实实用 V100/T4 跑原始 pinned 环境,要么把 torch 升上去——后者更推荐,DiffVC 的模型代码在 torch 2.x 下零改动。另外提醒一句:这个模型才 1.26 亿参数、峰值 2GB 显存,租 H100 SXM 80GB $3.582/卡·时 跑它是纯粹烧钱。NexGPU 有 75 种 GPU 型号、2498 张卡分布在 51 个国家和地区,选对档远比选贵的重要。

DiffVC 支持中文吗?拿中文语料做私有化部署效果怎么样?

语音转换本身是声学层面的操作,不做文本理解,所以中文音频喂进去能出东西。但要有心理准备:官方权重训练数据是 LibriTTS 与 VCTK,全是英语;那个平均音色编码器的监督信号来自 Montreal Forced Aligner 在英语音素上的对齐结果,中文的声调和音节结构不在它的先验里,跨语种转换会有可闻的口音漂移。想要正经中文效果,路径是拿自己的中文多说话人语料重训:数据准备成 wavs/mels/embeds 三个按说话人分的子目录,编码器要么下官方版要么自己训,再跑 train_dec.py 训解码器。这一步在 NexGPU 的 RTX A6000 48GB $0.817/卡·时 上最省心,48GB 让你不必为了显存去砍 batch。

转出来的声音有底噪、沙沙声,是模型本身的问题吗?

一半是,一半是 notebook 的锅。扩散解码器天然会往 mel 上带一点残余噪声,官方给了 mel_spectral_subtraction 做谱减;但 inference.ipynb 里 mel_synth_np 和 mel_source_np 两行取的都是 mel_,后一行本该是 mel_source,等于拿合成 mel 减自己,那步降噪空转了——先把这行改对。还不够就把 n_timesteps 从 30 往上调(论文里 EM solver 比到了 100 步,ML 与 PF 各比了 6 步和 30 步,步数越多越干净但 RTF 线性上升),train_dec.py 自带的验证推理用的就是 100 步;或者换 mode='pf' 的确定性采样试试。这类调参就是开一张卡反复听,NexGPU 按秒计费、没有最低消费、不用申请配额,试十组参数的开销不到一杯咖啡;V100 临时紧张时,Tesla P40 24GB $0.214/卡·时 也是这套 fp32 管线的现成替补。

同类模型 · 声音克隆 / 声音转换

全部模型部署指南

开始使用 NexGPU

无论你是企业研发团队还是独立开发者,都可以在几分钟内跑起第一个任务。

注册即可浏览全网实时价格,无需绑定支付方式。