You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

额外提示

  1. 一定要补上import vlc,否则你的代码会因为找不到模块报错;
  2. 避免全局异常捕获,明确捕获speech_recognition的特定异常(比如UnknownValueError和RequestError),这样更容易排查问题;
  3. 时间格式改成%H:%M比%H%M更符合自然语言读法,gTTS会处理得更流畅。

内容的提问来源于stack exchange,提问作者Scott Rowley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 23:17:49