Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

加速合成的一点小思路,长语句,按 , 。 ! 进行分割,在读第一句的时候,利用这个时间合成下一句。 #208

Closed
prairiewolf11 opened this issue Mar 15, 2023 · 11 comments
Assignees
Labels
enhancement 好想法,以后考虑跟进

Comments

@prairiewolf11
Copy link

确认已寻找过答案

问题描述
加速合成的一点小思路,“分段合成”。长语句,按 , ; 。 ! 进行分割,在读第一句的时候,利用这个时间合成下一句。
优点:加快了反应速度。
缺点:消耗更多的API调用量。

可以加一个参数,由用户根据自己的情况,是否启用“分段合成”功能。

@prairiewolf11 prairiewolf11 added the bug 我的锅 label Mar 15, 2023
@wzpan
Copy link
Owner

wzpan commented Mar 15, 2023

谢谢你的建议,这是一个非常好的想法。只是目前 wukong 的 Player 默认是非阻塞的,所以当我拆分句子后得小心做好 onCompleted 的衔接,否则就会出现一堆句子同时播放的问题。

要解决这个问题,我需要把 Player 的播放机制从单任务做成一个队列,顺便干掉 wait 参数。这样才能简单而优雅的实现你的想法。

我近期会考虑对 Player 做个重构支持这个 feature 。

@wzpan wzpan added this to wukong Mar 15, 2023
@github-project-automation github-project-automation bot moved this to To do in wukong Mar 15, 2023
@wzpan wzpan added enhancement 好想法,以后考虑跟进 and removed bug 我的锅 labels Mar 15, 2023
@prairiewolf11
Copy link
Author

prairiewolf11 commented Mar 16, 2023

1.先计算总共拆分成几句,然后每句一个序号。
player按序号播放,播放前还可以检查是否有丢句,如有丢句补发个合成。
就像迅雷下载文件那样的流程。

2.我已经碰到过一堆句子同时播放的情况了。有时会唤醒2次,然后对2次都回答,就同时播放了。这种情况很少。

3.如果按方法1搞,说不定能顺便就解决情况2了。

@wzpan
Copy link
Owner

wzpan commented Mar 16, 2023

需要先实现好 Player 的子线程播放队列,才能考虑做这个 feature 。否则要么在播放声音过程中无法唤醒(阻塞了主线程),要么就会很容易出现多段语音同时播放的问题(不阻塞,但是异步同时叠加播放了音频)。

@prairiewolf11
Copy link
Author

优化一下我最早的思路:
为减少多次合成造成的API的调用量大增的缺点,可以把长内容拆分成2段,第1段只有1句,播放这句的时间内,把剩下的第2段也完成合成并下载下来。然后再播放第2段。这样的合成,只调用了2次API。(大致思路)

详细思路:
如果要更精细的控制,可以计算合成第一句并下载所用的时间t1,再计算播放这句所用的时间t2,用t1(包含API调用速度与网络速度有关的不可控因素)预估剩下的内容合成并下载所用的时间t3,如果t2-t3>0,拆分成2段就没问题;如果t2-t3<0,说明播放第一句的时间不够剩下的内容合成,所以剩下的内容还要拆分;重复执行,直到最后一段内容的时间小于前一句的播放时间,就结束拆分。另外,还应该考虑一点提前量,以应对网络波动。

@wzpan
Copy link
Owner

wzpan commented Mar 21, 2023

不需要这么复杂,我的想法是全部句子丢线程池里消化。文本生产者-TTS 消费者/播放队列生产者-播放队列消费者的方式。

@wzpan wzpan moved this from To do to In progress in wukong Mar 25, 2023
wzpan added a commit that referenced this issue Mar 26, 2023
…th` 选项。

1. 增加了线程池来进行并行 TTS ,以优化合成速度,并解决了文本超长可能导致 TTS 失败的问题;
2. 由于文本超长导致TTS的问题已经被解决,废弃了 `trim_too_long_text` 和 `max_text_length` 选项。
wzpan added a commit that referenced this issue Mar 26, 2023
使用线程池来进行 TTS ,优化合成速度(#208)。
@wzpan wzpan closed this as completed Mar 26, 2023
@github-project-automation github-project-automation bot moved this from In progress to Done in wukong Mar 26, 2023
@wzpan wzpan reopened this Mar 26, 2023
@github-project-automation github-project-automation bot moved this from Done to In progress in wukong Mar 26, 2023
@wzpan
Copy link
Owner

wzpan commented Mar 26, 2023

3.4.0版本 已实现了多线程TTS加速合成的能力。

@wzpan wzpan closed this as completed Mar 26, 2023
@github-project-automation github-project-automation bot moved this from In progress to Done in wukong Mar 26, 2023
@prairiewolf11
Copy link
Author

大神辛苦了,感谢能百忙之中更新软件。
从版本3.4.0的日志看,貌似是先一个个的合成,都合完了,再一个个播放的。截图里,第一句话的语音晚播放了0.5秒,应该在18:38:41,851播放才对,读取音频文件大概需要0.003秒的样子。
是不是应该是把播放的优先级提到最高,只要是按顺序合成完就立刻播放。
比如有4句话,都送到线程池里去合成,然后有一个线程等第1句的合成结果,只要第1句合成成功就立刻播放,然后等第2句……
日志

@wzpan
Copy link
Owner

wzpan commented Mar 26, 2023

做是可以做,不过代码可能就会写的很难看。
这个等我后面再看看。

@wzpan
Copy link
Owner

wzpan commented Mar 26, 2023

优化了一把。这次一旦合成 TTS ,会立马按顺序进入播放,而不会等到所有 TTS 合成完成。代码提交到了主干。

@prairiewolf11
Copy link
Author

牛。

@prairiewolf11
Copy link
Author

prairiewolf11 commented Mar 27, 2023

我统计了一下,合成一句话用时大约是0.4+秒,播放一句话大约是6秒。所以在播放第1句话的时候,剩下的所有内容均已合成成功。
说明:所有内容拆分成2段就足够。这样能节省API调用量。至少能省一半。
不是啥问题,我自己改改就行了,刚发现按.拆分会把小数也拆坏了。

分拆成2行,分别进行TTS

lines = re.split(",|。|!|?|!|?|\n", msg ,maxsplit=1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement 好想法,以后考虑跟进
Projects
Status: Done
Development

No branches or pull requests

2 participants