一段285个字符的俄语段落,合成出来约18秒语音。在RTX 3070上预热之后,Silero、XTTS-v2、F5-TTS三款引擎跑同一段文本,速度差距是数量级的:Silero比实时快数百倍,克隆类引擎则要慢上几倍。这些数字来自单机单次运行,不是标准跑分,但量级足够说明问题。

打开网易新闻 查看精彩图片

有人把这三款引擎塞进了一个Windows桌面程序Glasvo:tkinter窗口,MIT许可,支持Windows 10/11。程序最初为俄语而做,英语同样可用——118个英语Silero音色,英语的XTTS与F5克隆也能跑。真正值得看的不是界面,而是磁盘、内存和时间上的实际开销,以及开发过程中踩到的坑。

Silero:快,但会悄悄吞字符

Silero模型是torch.package归档。PyTorch打不开含西里尔字符的路径,而用户的文件夹名什么都有可能,所以代码改成传文件对象进去,再加载模型、搬到CUDA或CPU上,调用apply_tts出wav。语速和音高走SSML,单块文本控制在700字符以内,长文按句子边界切开,再用停顿拼接。

最难受的意外是:Silero的俄语模型会静默跳过数字、丢掉拉丁字母。输出里出现的是空白,不是报错。为此模型前面挂了两个函数——expand_numbers基于num2words把2026这样的数字转成词,latin_to_cyrillic分三级处理拉丁文本:常见词查词典(YouTube变成«ютуб»),全大写和无元音的词按字母逐个读(USB变成«ю-эс-би»),其余走转写。验证方式是合成测试短语,再用Whisper识别回来比对。

克隆:采样、切块与自检

参考音频先经ffmpeg转成单声道24 kHz wav,ffmpeg取自imageio-ffmpeg,不需要系统预装。文件写入临时路径后用os.replace移动,坏文件不会污染上一份样本。XTTS-v2对俄语单块的上限约182字符,所以切块按170来;F5需要参考文本,由Whisper small在本地转写样本,转完即卸载以释放显存。

作者的自检方法很直接:拿一个Silero音色当“样本”,让XTTS和F5用它朗读一段文本,再用Whisper转写结果、比对词句,两者都是100%匹配。

依赖地狱与安装

克隆相关依赖(coqui-tts、f5-tts、transformers)拉进来的东西多到让依赖解析器卡死。被钉死的版本包括:torch==2.5.1+cu121(transformers 5和diffusers 0.43需要torch 2.6+)、transformers<5、huggingface_hub<1.0,以及F5经hydra需要的omegaconf==2.3.1。pip check会对f5-tts的版本钉法报怨,这属于可接受范围;requirements.txt就是可用环境的完整pip freeze。

给没有Python环境的人准备的install.bat会调用install.ps1:下载uv,把Python 3.12装进程序目录,建venv,再执行uv pip install --no-deps -r requirements.txt。没有NVIDIA显卡时,把torch的+cu121换成+CPU版本。uv缓存放在较短的临时路径下,因为antlr4在深层目录里构建失败过。模型不打包进zip,首次使用时通过huggingface_hub.snapshot_download下载。

程序还能自更新:启动时读取GitHub的releases/latest,下载Glasvo.zip,覆盖旧文件,但保留settings.json。

几个小坑

  • 在pythonw下sys.stdout是None,tqdm和print会崩,塞一个devnull顶上。
  • 后台线程不能碰tkinter,所有交互走队列,由主线程定时排空。
  • 鼠标滚轮划过ttk.Combobox会改值,需要拦截。
  • 俄语键盘布局下的Ctrl+C/V/X/A,按keycode匹配。

许可提醒

代码是MIT,但多数模型是非商用:Silero和俄语F5-TTS为CC BY-NC 4.0,XTTS-v2使用Coqui Public Model License。把音频用进带变现的视频前先核对许可,克隆只用自己的声音,或已获对方同意的声音。