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

Azure Speech翻译在Tkinter中无法接收麦克风输入问题求助

问题描述

单独运行Azure语音识别实验室代码时,麦克风音频输入检测正常且无报错;但集成到Tkinter界面后,调用translator.recognize_once_async().get()时,代码虽按预期阻塞,但无法获取任何语音输入,最终等待15秒超时。已尝试用线程和队列让语音检测后台运行,问题仍存在,且麦克风权限已验证正常。

问题分析

Tkinter的主事件循环是单线程的,即使使用root.after()调度任务,语音识别的阻塞调用recognize_once_async().get()还是会卡住主循环,导致音频捕获无法正常工作——因为麦克风输入的底层处理可能依赖主线程的事件循环响应,或者Azure Speech SDK在阻塞主线程时无法正确获取音频流。

解决方案

核心思路是把语音识别的阻塞逻辑完全放到独立线程中执行,避免阻塞Tkinter主事件循环。同时,线程中不能直接操作Tkinter控件,必须通过root.after()将UI更新任务抛回主线程处理。

以下是修改后的完整代码:

from dotenv import load_dotenv
import os
import azure.cognitiveservices.speech as speech_sdk
import tkinter as tk
from tkinter import ttk
import threading

# 初始化Azure服务
load_dotenv()
ai_key = os.getenv('SPEECH_KEY')
ai_region = os.getenv('SPEECH_REGION')

speech_config = speech_sdk.SpeechConfig(ai_key, ai_region)
translation_config = speech_sdk.translation.SpeechTranslationConfig(ai_key, ai_region)
translation_config.add_target_language('en')
translation_config.add_target_language('zh-Hans')
translation_config.add_target_language('ta')
translation_config.add_target_language('yue')
translation_config.add_target_language('ms')

def reset_application():
    input_lang_combobox.set('')
    output_lang_combobox.set('')
    input_lang_combobox['values'] = languages
    output_lang_combobox['values'] = languages
    status_label.config(text="Status: Waiting for both input and output language to be selected")
    run_button.config(state=tk.DISABLED)

def update_languages(*args):
    input_language = input_lang_combobox.get()
    output_language = output_lang_combobox.get()

    if input_language:
        output_options = [lang for lang in languages if lang != input_language]
        output_lang_combobox['values'] = output_options
        if output_language == input_language:
            output_lang_combobox.set('')
    else:
        output_lang_combobox['values'] = languages

    if output_language:
        input_options = [lang for lang in languages if lang != output_language]
        input_lang_combobox['values'] = input_options
        if input_language == output_language:
            input_lang_combobox.set('')
    else:
        input_lang_combobox['values'] = languages

    if input_language and output_language:
        style.configure('Custom.TButton', foreground='orange', background='white')      
        status_label.config(text=f"Status: Ready to translate from {input_language} to {output_language}\n      "
                                    f"Click button to begin translation service")
        run_button.config(state=tk.NORMAL)
    else:
        status_label.config(text="Status: Waiting for both input and output language to be selected")
        run_button.config(state=tk.DISABLED)

def start_translation():
    run_button.config(state=tk.DISABLED)
    translation_config.speech_recognition_language = 'en-US'
    status_label.config(text="Status: Please speak into the microphone now")
    
    # 启动独立线程执行语音识别
    threading.Thread(target=translate, args=('zh-Hans',), daemon=True).start()

def translate(targetLanguage):
    def recognition():
        audio_config = speech_sdk.AudioConfig(use_default_microphone=True)
        translator = speech_sdk.translation.TranslationRecognizer(translation_config, audio_config=audio_config)
        result = translator.recognize_once_async().get()
        
        # 将结果处理抛回主线程
        root.after(0, process_recognition_result, targetLanguage, result)

    def process_recognition_result(targetLanguage, result):
        print(result.text)
        print(result.translations.get('zh-Hans', ''))
        if result.reason == speech_sdk.ResultReason.TranslatedSpeech:
            status_label.config(text="Status: Valid Input Speech Detected. Translating In Process")
            try:
                translation = result.translations[targetLanguage]
                root.after(1000, complete_translation, targetLanguage, translation)
            except Exception as e:
                show_error_popup(f"Status: An error occurred: {e}, event 'Translation' failed. Restarting Process\nClose the pop-up to proceed")
                reset_application()
        elif result.reason == speech_sdk.ResultReason.NoMatch:
            show_error_popup(f"Status: An error occurred {result.no_match_details}, event 'matching speech with input' failed. Restarting Process\nClose the pop-up to proceed")
            reset_application()
        elif result.reason == speech_sdk.ResultReason.Canceled:
            cancellation_details = result.cancellation_details
            show_error_popup(f"Status: An error occurred {cancellation_details.reason}, event 'input speech' failed. Restarting Process\nClose the pop-up to proceed")
            reset_application()

    def complete_translation(targetLanguage, translation):
        status_label.config(text="Status: Translation Complete")
        voices = {
            "en": "en-SG-WayneNeural",
            "yue": "yue-CN-YunSongNeural",
            "ta": "ta-SG-AnbuNeural",
            "zh-Hans": "zh-CN-YunxiNeural",
            "ms": "ms-MY-OsmanNeural"
        }
        speech_config.speech_synthesis_voice_name = voices.get(targetLanguage)
        speech_synthesizer = speech_sdk.SpeechSynthesizer(speech_config)
        root.after(1000, synthesize_output, translation, speech_synthesizer)

    def synthesize_output(translation, speech_synthesizer):
        status_label.config(text="Status: Producing Output")
        speak = speech_synthesizer.speak_text_async(translation).get()
        if speak.reason != speech_sdk.ResultReason.SynthesizingAudioCompleted:
            print(speak.reason)
        reset_application()

    def show_error_popup(message):
        new_window2 = tk.Toplevel(root)
        new_window2.title("Error Pop-Up")
        translated_text_label = tk.Label(new_window2, text=message, font=("Arial", 12,))
        translated_text_label.pack()

    recognition()

languages = ["English", "Chinese", "Cantonese", "Malay", "Tamil"]

root = tk.Tk()
root.geometry("1200x400")

app_title_label = ttk.Label(root, text="Translation App", font=("LG Smart UI Bold", 56, "bold"), foreground='orange')
app_title_label.grid(row=0, column=0, padx=10, pady=5, columnspan=2)

dropdown_frame = ttk.Frame(root)
dropdown_frame.grid(row=1, column=0, padx=10, pady=10)

input_lang_label = ttk.Label(dropdown_frame, text="Select Input Language", foreground="white",background="orange" ,font=("LG Smart UI Bold", 24, "bold"))
input_lang_label.pack(side=tk.LEFT)
input_lang_combobox = ttk.Combobox(dropdown_frame, values=languages)
input_lang_combobox.pack(side=tk.LEFT, padx=10)
input_lang_combobox.bind('<<ComboboxSelected>>', update_languages)

output_lang_label = ttk.Label(dropdown_frame, text="Select Output Language", foreground="white",background="orange",font=("LG Smart UI Bold", 24, "bold"))
output_lang_label.pack(side=tk.LEFT)
output_lang_combobox = ttk.Combobox(dropdown_frame, values=languages)
output_lang_combobox.pack(side=tk.LEFT)
output_lang_combobox.bind('<<ComboboxSelected>>', update_languages)

button_frame = ttk.Frame(root)
button_frame.grid(row=2, column=0, pady=30)

style = ttk.Style()
style.configure('Custom.TButton', foreground='orange', background='white', font=("LG Smart UI Bold", 12, "bold"), padding=10)

run_button = ttk.Button(button_frame, text="Begin Translation", style='Custom.TButton', command=start_translation, state=tk.DISABLED)
run_button.pack(side=tk.LEFT, padx=10)

reset_button = ttk.Button(button_frame, text="Reset", style='Custom.TButton', command=reset_application)
reset_button.pack(side=tk.LEFT, padx=10)

status_bar = ttk.Frame(root, relief=tk.SUNKEN)
status_bar.grid(row=3, column=0, sticky=tk.W+tk.E, padx=20, pady=50)
status_label = ttk.Label(status_bar, text="Status: Waiting for both input and output language to be selected", anchor=tk.W)
status_label.pack(fill=tk.X)

root.mainloop()
修改要点
  • 将语音识别逻辑recognition()放到独立线程中执行,避免阻塞Tkinter主循环
  • 线程中所有UI更新操作(如修改status_label、弹出错误窗口)都通过root.after()交还给主线程处理,符合Tkinter的线程安全要求
  • 优化了错误处理的代码结构,提取了show_error_popup()函数简化重复代码
  • 使用daemon=True创建线程,确保程序退出时线程自动终止

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:25:56