Browse Source

fix the bug of pytts in linux

master
JS00000 1 year ago
parent
commit
1cd6a71ce0
1 changed files with 33 additions and 10 deletions
  1. +33
    -10
      voice/pytts/pytts_voice.py

+ 33
- 10
voice/pytts/pytts_voice.py View File

@@ -2,8 +2,9 @@
pytts voice service (offline) pytts voice service (offline)
""" """


import os
import sys
import time import time

import pyttsx3 import pyttsx3


from bridge.reply import Reply, ReplyType from bridge.reply import Reply, ReplyType
@@ -11,7 +12,6 @@ from common.log import logger
from common.tmp_dir import TmpDir from common.tmp_dir import TmpDir
from voice.voice import Voice from voice.voice import Voice



class PyttsVoice(Voice): class PyttsVoice(Voice):
engine = pyttsx3.init() engine = pyttsx3.init()


@@ -20,19 +20,42 @@ class PyttsVoice(Voice):
self.engine.setProperty("rate", 125) self.engine.setProperty("rate", 125)
# 音量 # 音量
self.engine.setProperty("volume", 1.0) self.engine.setProperty("volume", 1.0)
for voice in self.engine.getProperty("voices"):
if "Chinese" in voice.name:
self.engine.setProperty("voice", voice.id)
if sys.platform == 'win32':
for voice in self.engine.getProperty("voices"):
if "Chinese" in voice.name:
self.engine.setProperty("voice", voice.id)
else:
self.engine.setProperty("voice", "zh")
# If the problem of espeak is fixed, using runAndWait() and remove this startLoop()
# TODO: check if this is work on win32
self.engine.startLoop(useDriverLoop=False)


def textToVoice(self, text): def textToVoice(self, text):
try: try:
wavFile = TmpDir().path() + "reply-" + str(int(time.time())) + ".wav"
# avoid the same filename
wavFileName = "reply-" + str(int(time.time())) + "-" + str(hash(text) & 0x7fffffff) + ".wav"
wavFile = TmpDir().path() + wavFileName
logger.info("[Pytts] textToVoice text={} voice file name={}".format(text, wavFile))

self.engine.save_to_file(text, wavFile) self.engine.save_to_file(text, wavFile)
self.engine.runAndWait()
logger.info(
"[Pytts] textToVoice text={} voice file name={}".format(text, wavFile)
)

if sys.platform == 'win32':
self.engine.runAndWait()
else:
# In ubuntu, runAndWait do not really wait until the file created.
# It will return once the task queue is empty, but the task is still running in coroutine.
# And if you call runAndWait() and time.sleep() twice, it will stuck, so do not use this.
# If you want to fix this, add self._proxy.setBusy(True) in line 127 in espeak.py, at the beginning of the function save_to_file.
# self.engine.runAndWait()

# Before espeak fix this problem, we iterate the generator and control the waiting by ourself.
# But this is not the canonical way to use it, for example if the file already exists it also cannot wait.
self.engine.iterate()
while self.engine.isBusy() or wavFileName not in os.listdir(TmpDir().path()):
time.sleep(0.1)

reply = Reply(ReplyType.VOICE, wavFile) reply = Reply(ReplyType.VOICE, wavFile)

except Exception as e: except Exception as e:
reply = Reply(ReplyType.ERROR, str(e)) reply = Reply(ReplyType.ERROR, str(e))
finally: finally:


Loading…
Cancel
Save