导出Coqui-TTS训练的VITS模型为ONNX时存在输入长度固定的问题
导出Coqui-TTS训练的VITS模型为ONNX时存在输入长度固定的问题
我之前踩过这个坑!VITS本身是支持动态输入长度的,但Coqui默认的导出脚本会把输入维度固定死,导致要么短文本生成的音频只有固定长度(比如你碰到的2秒情况),要么用长dummy输入时,短文本后面补的无效token会生成噪音。下面是我亲测有效的解决方法:
问题根源
Coqui自带的export_onnx方法里,默认用固定长度的dummy_input导出模型,而且没有配置动态轴(dynamic axes)。这会让ONNX模型被固化成只能处理和dummy_input长度完全一致的输入序列,短文本会被强制补到固定长度(补的内容无意义,生成噪音),长文本则会被截断。
具体修改步骤
1. 调整ONNX导出代码,开启动态轴
找到Coqui-TTS源码中VITS模型的export_onnx方法(一般在TTS/tts/models/vits.py文件里),修改代码添加动态轴配置:
def export_onnx(self, output_path: str, dummy_input_length: int = 100): self.eval() # 确保模型处于eval模式,避免训练层影响 dummy_input = torch.randint(0, self.config.vocab_size, (1, dummy_input_length)).to(self.device) # 配置动态轴:让模型支持可变的batch和序列长度 dynamic_axes = { "input_ids": {0: "batch_size", 1: "sequence_length"}, # 输入的batch和序列长度动态 "audio": {0: "batch_size", 1: "audio_length"} # 输出的音频长度随输入动态变化 } torch.onnx.export( self, dummy_input, output_path, opset_version=15, # 建议用15及以上版本,兼容动态轴操作 do_constant_folding=True, input_names=["input_ids"], output_names=["audio"], dynamic_axes=dynamic_axes, # 关键:开启动态轴支持 verbose=False )
如果你的VITS模型还有额外输入(比如说话人ID、情感嵌入),也要在dynamic_axes里对应添加这些输入的动态配置,比如:
dynamic_axes = { "input_ids": {0: "batch_size", 1: "sequence_length"}, "speaker_ids": {0: "batch_size"}, # 说话人ID的batch维度动态 "audio": {0: "batch_size", 1: "audio_length"} }
2. 推理时传入对应长度的真实输入
导出完成后,用ONNX Runtime推理时,直接传入和真实文本长度匹配的token序列即可,不需要再对齐dummy_input的长度:
import onnxruntime as ort import torch from TTS.tts.utils.text.tokenizer import TTSTokenizer # 用你训练时用的tokenizer # 加载ONNX模型 sess = ort.InferenceSession("your_trained_vits.onnx") # 处理真实文本 text = "你好,这是一段测试文本" tokenizer = TTSTokenizer(config=your_model_config) # 替换成你的模型配置 input_ids = tokenizer.text_to_ids(text) input_tensor = torch.tensor([input_ids], dtype=torch.int64) # 形状为(1, N),N是文本实际长度 # 执行推理 outputs = sess.run(["audio"], {"input_ids": input_tensor.numpy()}) audio = outputs[0][0] # 得到和文本匹配长度的音频,无多余噪音
额外注意事项
- 确保
opset_version不低于15:低版本ONNX对动态轴的支持有限,可能导致导出失败或推理报错 - 导出前必须切换到eval模式:避免batch normalization、dropout等训练专用层的随机行为影响导出结果
- 如果导出时提示某个算子不支持动态轴,可以尝试升级PyTorch和ONNX的版本,或者在Coqui的GitHub仓库里看最新的修复PR(很多时候社区已经解决了这类算子兼容问题)
我当时改完之后,不管输入是3个词还是30个词,生成的音频长度都完全匹配文本,再也没有多余的噪音了,你可以试试这个方案!




