如何在Python中实现不阻塞主线程的文本转语音功能
如何在Python中实现不阻塞主线程的文本转语音功能
我完全懂你的困扰——用pyttsx3做文本转语音时,engine.runAndWait()是同步执行的,它会一直卡着主线程,直到语音播放完毕才会继续往下走,这对需要同时处理其他任务的程序来说太影响体验了。
其实解决思路很简单:把文本转语音的操作放到子线程里执行,让主线程和语音播放线程各自跑各自的,互不干扰。我给你调整了代码,你可以直接用:
import pyttsx3 import threading class TextToSpeech: def __init__(self): # 把引擎初始化放到构造方法里,只初始化一次,避免重复创建浪费资源 self.engine = pyttsx3.init() def _play_speech(self, text): # 私有方法,负责实际执行语音播放的逻辑 self.engine.say(text) self.engine.runAndWait() def textToSpeech(self, text): # 创建子线程来执行语音播放,主线程调用后会立刻返回,完全不阻塞 speech_thread = threading.Thread(target=self._play_speech, args=(text,)) speech_thread.start() # 测试效果 t2s = TextToSpeech() t2s.textToSpeech("Hello") t2s.textToSpeech("How are you") t2s.textToSpeech("I am fine") # 这里加个主线程的任务,验证不会被阻塞 print("主线程正在处理其他任务,完全没被语音播放卡住!")
给你拆解下这个方案的关键点:
- 优化引擎初始化:原来的代码每次调用
textToSpeech都重新创建引擎,既浪费资源又容易出问题,现在只初始化一次,效率更高。 - 拆分播放逻辑:把实际的语音播放放到私有方法
_play_speech里,对外的textToSpeech只负责创建和启动子线程,职责更清晰。 - 子线程异步执行:主线程调用
textToSpeech后,会立刻启动子线程去处理语音播放,自己继续执行后续代码,完全不会被卡住。
如果之后你需要等待所有语音都播放完再结束程序(比如脚本最后要做收尾工作),可以把创建的线程保存下来,最后调用join()方法等待所有线程完成,示例如下:
# 保存线程并等待所有语音播放完毕的例子 t2s = TextToSpeech() threads = [] threads.append(threading.Thread(target=t2s._play_speech, args=("Hello",))) threads.append(threading.Thread(target=t2s._play_speech, args=("How are you",))) threads.append(threading.Thread(target=t2s._play_speech, args=("I am fine",))) # 启动所有线程 for thread in threads: thread.start() # 等待所有语音播放完毕 for thread in threads: thread.join() print("所有语音都播放完了,主线程可以收尾了")
这样就完美解决了阻塞的问题,而且代码结构也更合理。
备注:内容来源于stack exchange,提问作者questp
相关产品推荐
相关产品推荐

