PlayVoice / vits_chinese

Best practice TTS based on BERT and VITS with some Natural Speech Features Of Microsoft; Support ONNX streaming out!
https://huggingface.co/spaces/maxmax20160403/vits_chinese
MIT License
1.16k stars 167 forks source link

请教支持流式输出吗? #46

Open kendo6666 opened 1 year ago

kendo6666 commented 1 year ago

请教在推断时,支持实时的流式输出吗?在一些应用中,例如聊天程序,需要支持实时的流式输出,否则等待推断的时间太长,交互体验不佳。

MaxMax2016 commented 1 year ago

现在不支持,但是可以做,要不要做做?

kendo6666 commented 1 year ago

@MaxMax2016 期待大神的更新

kendo6666 commented 1 year ago

@MaxMax2016 你有提到微软的NaturalSpeech,是指"NaturalSpeech: End-to-End Text to Speech Synthesis with Human-Level Quality"。是哪些地方跟论文相关呢?刚巧正开始看这篇论文,它的英文演示效果真的很棒。

MaxMax2016 commented 1 year ago

红色圈圈里面 natrual_loss https://github.com/PlayVoice/vits_chinese/blob/master/train.py#L267

kendo6666 commented 1 year ago

@MaxMax2016 感谢指点,正好对着代码学习了。 期待对流式语音的支持,这个应用还是挺广泛的!!

MaxMax2016 commented 1 year ago

@kendo6666 分块流式 https://github.com/PlayVoice/vits_chinese/blob/master/models.py#L931~L970 hop_frame有个最小值,这个值是试出来的

kendo6666 commented 1 year ago

@MaxMax2016 这么快就实现了?太牛逼了。只是影响输出,用预训练模型就可以体验,还是要重新训练模型呢?

MaxMax2016 commented 1 year ago

用预训练模型,只影响输出

kendo6666 commented 1 year ago

太棒了,立即体验一下,到时候给你反馈!!

kendo6666 commented 1 year ago

@MaxMax2016 对于结束的处理似乎有bug, 测试了4句, 遥望星空作文独自坐在乡间的小丘上,看着阳光渐渐变暗,听着鸟鸣渐渐变弱,触着清风渐渐变凉 时光总是慢慢地偷走我们的容颜,渐渐地有些人终将离我们而远去 白色的樱花纯洁高尚,红色的樱花热烈奔放,绿色的樱花清晰澹雅,花开的美丽与快乐,花落的烂漫与潇洒都蕴藏着樱花的人生智慧 汽车文化节是学校校园文化的浓缩,是学校办学特色的呈现,是全体师生魅力展现的一个平台。它进一步丰富校园文化生活,营造积极向上、清新高雅、健康文明的校园文化氛围,展现同学们积极向上的精神风貌,文化节又为同学们提供了一个发现自我、充实自我、展现自我的舞台,是我校全面实施全素质教育的又一次展示,同时也是搭建校企合作的良好平台。

前三句都是最后一个字出不来,最后一句是正确的。

MaxMax2016 commented 1 year ago

好的,等我有空的时候再看看,还有其他问题没有呢,主要是和非流式效果的差异?

MaxMax2016 commented 1 year ago

@MaxMax2016 对于结束的处理似乎有bug, 测试了4句, 遥望星空作文独自坐在乡间的小丘上,看着阳光渐渐变暗,听着鸟鸣渐渐变弱,触着清风渐渐变凉 时光总是慢慢地偷走我们的容颜,渐渐地有些人终将离我们而远去 白色的樱花纯洁高尚,红色的樱花热烈奔放,绿色的樱花清晰澹雅,花开的美丽与快乐,花落的烂漫与潇洒都蕴藏着樱花的人生智慧 汽车文化节是学校校园文化的浓缩,是学校办学特色的呈现,是全体师生魅力展现的一个平台。它进一步丰富校园文化生活,营造积极向上、清新高雅、健康文明的校园文化氛围,展现同学们积极向上的精神风貌,文化节又为同学们提供了一个发现自我、充实自我、展现自我的舞台,是我校全面实施全素质教育的又一次展示,同时也是搭建校企合作的良好平台。

前三句都是最后一个字出不来,最后一句是正确的。

@kendo6666 最后那句有句号,你看看是不是这个原因

kendo6666 commented 1 year ago

@MaxMax2016 是的,默认的测试用例没有句号,加上后就完整了。^。^ 另外,流式和非流式声音质量没有影响。

我看到流式实现,在text encoder/时长预测/ResidualCouplingBlock等处理与非流式都是相同的,在音频解码时按chunk输出。这意味着vits-chinese中的text encoder/时长预测/ResidualCouplingBlock等处理都是可以重入的,对吧? 我指的重入是,在处理当前这一句的音频解码时,就可以同时处理下一句的text encoder了,对吧?

MaxMax2016 commented 1 year ago

@MaxMax2016 是的,默认的测试用例没有句号,加上后就完整了。^。^ 另外,流式和非流式声音质量没有影响。 我看到流式实现,在text encoder/时长预测/ResidualCouplingBlock等处理与非流式都是相同的,在音频解码时按chunk输出。这意味着vits-chinese中的text encoder/时长预测/ResidualCouplingBlock等处理都是可以重入的,对吧? 我指的重入是,在处理当前这一句的音频解码时,就可以同时处理下一句的text encoder了,对吧?

@kendo6666 这个想法非常不错,其实流式实现本来就要把VITS拆解为两个部分,decoder和其他。你的想法是对的,很赞的想法。编码部分用GPU处理,然后解码部分用CPU解码、流式输出,极大的合理利用计算资源。

ScottXiao233 commented 1 year ago

很抱歉,因为查了很多资料都没能找到,希望能得知怎样操作才能实时播放流式输出的音频呢?

MaxMax2016 commented 1 year ago

很抱歉,因为查了很多资料都没能找到,希望能得知怎样操作才能实时播放流式输出的音频呢?

具体我也没实际做过,查了下资料,可能是这样实现:

import pyaudio

# 初始化播放器
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(2), channels=1, rate=16000, output=True)

# 将 pcm 数据直接写入 PyAudio 的数据流
# with open("f1.pcm", "rb") as f:
#    stream.write(f.read())

# vits 生成 pcm 然后写入 PyAudio 的数据流
o_chunk = self.dec(z_chunk, g=g)[0, 0].data.cpu().float().numpy()
o_chunk = o_chunk[cut_s_wav:cut_e_wav]
# 还需要 float 转 int16?
stream.write(o_chunk)

stream.stop_stream()
stream.close()
p.terminate()
ben-8878 commented 1 year ago

很抱歉,因为查了很多资料都没能找到,希望能得知怎样操作才能实时播放流式输出的音频呢?

@ScottXiao233 请问你按照https://github.com/PlayVoice/vits_chinese/issues/46#issuecomment-1553907433 这个是可以实现你说的那个效果吗。

wbjnpu commented 1 year ago

好的,等我有空的时候再看看,还有其他问题没有呢,主要是和非流式效果的差异?

这么看的话,onnx分别导出为两个模块,generator之前手写一部分代码,可以实现C端的流式?我看了一下比较可行

liroda commented 1 year ago

好的,等我有空的时候再看看,还有其他问题没有呢,主要是和非流式效果的差异?

您好,试了一下最近更新的onnx stream这边,发现stream 流式的话生成整体音频正常,就是里面有些地方会有"哒"的音混在里面,按您这边默认参数跑的,飞流式音频是正常的,是flow模块引入的吗?看设置50帧的话与Generator训练是一致的。

MaxMax2016 commented 1 year ago

@liroda hop_frame = 9 修改为 hop_frame = 12 https://github.com/PlayVoice/vits_chinese/blob/bert_vits/vits_infer_onnx_stream.py#L191

liroda commented 1 year ago

@liroda hop_frame = 9 修改为 hop_frame = 12 https://github.com/PlayVoice/vits_chinese/blob/bert_vits/vits_infer_onnx_stream.py#L191

您好,还是会有,是里面音频偶尔位置混合能听到"噔",声音很小,但还是能听出来的,我这边是训练的8k 采样率模型,hop_length=100,试了hop_frame=20 也还是会存在这种情况,请教大佬这块调试思考改怎么弄呢?

MaxMax2016 commented 1 year ago

要不把flow放在encoder里面试试?

liroda commented 1 year ago

要不把flow放在encoder里面试试?

嗯,encoder加入flow 模块也也存在偶尔位置处的"噔"声音,后来根据打印shape 发现生成的o_chunk = o_chunk[cut_s_wav:cut_e_wav] 生成shape,我这边是大于5000的(stream_chunk(50) * hope_length(100)) 这里选取5000个样点,生成音频就正常了, 第二种方法:Generator 生成代码中设置,上采样这边按 for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)): self.ups.append( weight_norm( ConvTranspose1d( upsample_initial_channel // (2i), upsample_initial_channel // (2 (i + 1)), k, u, padding=(k - u) // 2 + (k-u)%2, output_padding = (k-u) %2, ) ) ) 修改后生成的o_chunk 就是5000样点了