Python语音程序:从listen函数调用say时音频播放不完整
gTTS Audio Cuts Off When Called From Speech Listener, Works Manually
你遇到的这个问题我之前也碰到过——手动调用process("what time is it")时音频能完整播放,但通过listen()触发的话,刚听到开头就被截断,哪怕加了time.sleep()也没用。我来帮你拆解原因并给出可行的修复方案。
问题根源
核心问题出在异步播放的生命周期上:vlc.MediaPlayer.play()是异步执行的,调用后函数会立刻返回,不会等待音频播放完成。当listen()调用process()再触发say()时,say()执行完就返回了,此时语音识别的上下文(比如麦克风监听的线程)会抢占资源,甚至当前函数栈结束后会间接终止音频播放进程,导致音频被截断。
修复方案
下面提供两种靠谱的解决方式,你可以根据需求选择:
方案1:等待音频播放完成再返回
修改say()函数,添加逻辑等待播放结束,确保音频完整播放后再释放相关资源:
from gtts import gTTS import speech_recognition as rs import pyaudio import audioop import os import math from os import system import threading from datetime import datetime import vlc # 注意:你之前的代码遗漏了这个导入! def say(text): filename = 'speak.mp3' language = 'en' myobj = gTTS(text=text, lang=language, slow=False) myobj.save(filename) player = vlc.MediaPlayer(filename) player.play() # 循环等待播放完成 while player.is_playing(): continue # 可选:播放完成后删除临时音频文件 os.remove(filename) def listen(x): r=rs.Recognizer() with rs.Microphone() as source: # 新增:调整环境噪音,提升识别准确率 r.adjust_for_ambient_noise(source) audio=r.listen(source) try: text = r.recognize_google(audio) process(text.lower()) except rs.UnknownValueError: # 明确捕获识别失败的异常,避免全局捕获隐藏问题 system('say I did not get that. Please say again.') listen(0) except rs.RequestError as e: system(f'say Sorry, my speech service is unavailable. Error: {e}') def process(text): print(text) if 'what time is it' in text: # 把时间格式改成带冒号的,gTTS会读得更自然(比如17:06会读成"seventeen oh six") say(datetime.now().strftime("%H:%M")) return
方案2:用独立线程播放音频(不阻塞主线程)
如果你的程序需要同时处理其他任务,不想因为播放音频阻塞主线程,可以把播放逻辑放到独立线程中:
def say(text): def play_audio_task(): filename = 'speak.mp3' language = 'en' myobj = gTTS(text=text, lang=language, slow=False) myobj.save(filename) player = vlc.MediaPlayer(filename) player.play() while player.is_playing(): continue os.remove(filename) # 启动独立线程执行播放任务 threading.Thread(target=play_audio_task).start()
额外提示
- 一定要补上
import vlc,否则你的代码会因为找不到模块报错; - 避免全局异常捕获,明确捕获
speech_recognition的特定异常(比如UnknownValueError和RequestError),这样更容易排查问题; - 时间格式改成
%H:%M比%H%M更符合自然语言读法,gTTS会处理得更流畅。
内容的提问来源于stack exchange,提问作者Scott Rowley
相关产品推荐
相关产品推荐

