如何将pyttsx3的TTS输出接入Nvidia Audio2Face?附代码调试
问题解决方案
1. 麦克风错误修复
错误根源
- 函数调用遗漏括号:
ProfileManager.__init__中调用self.adjust_ambient_noise时未加括号,导致方法未执行,触发后续初始化逻辑错误。 - 无效设备索引:硬编码的
device_index=45大概率不存在,麦克风初始化失败,引发stream=None的属性错误。 - Recognizer实例重复创建:
get_voice_input中每次新建sr.Recognizer(),未复用类内已初始化的实例,且未指定设备索引,导致音频源不匹配。
修复步骤
- 修正函数调用:在
__init__中把self.adjust_ambient_noise改为self.adjust_ambient_noise()。 - 获取有效麦克风索引:先运行以下代码列出可用设备,替换为实际存在的索引:
import speech_recognition as sr for index, name in enumerate(sr.Microphone.list_microphone_names()): print(f"麦克风索引 {index}: {name}")
- 复用Recognizer实例:修改
get_voice_input方法,使用类内的self.recognizer并指定设备索引:
def get_voice_input(self): with sr.Microphone(device_index=self.device_index) as source: print("Listening....") self.recognizer.pause_threshold = 1 audio = self.recognizer.listen(source) try: print("Recognizing....") query = self.recognizer.recognize_google(audio, language='en-in') print(f"user said: {query}\n") except Exception as e: print(f"语音识别失败: {e}") self.tts_speak("没听清,请再说一遍。") return self.get_voice_input() # 递归重试 return query
- 增加异常捕获:在
adjust_ambient_noise中处理麦克风初始化失败的情况:
def adjust_ambient_noise(self): try: with sr.Microphone(device_index=self.device_index) as source: print("Adjusting for ambient noise. Please wait...") self.recognizer.adjust_for_ambient_noise(source, duration=2) # 缩短时长提升体验 except OSError as e: print(f"麦克风初始化失败: {e}") self.tts_speak("无法连接麦克风,请检查设备设置。") exit()
2. 代码优化建议
- 配置参数解耦:把设备索引、存储文件路径、语音识别语言等抽离成常量,避免硬编码:
CONFIG = { "DEVICE_INDEX": 0, "PROFILE_FILE": "profiles.json", "RECOGNIZE_LANG": "en-in" }
- 增强错误处理:创建档案时捕获年龄输入非数字的异常:
def create_profile(self): self.tts_speak("Please say your name.") name = self.get_voice_input() while True: self.tts_speak("Please say your age.") age_str = self.get_voice_input() try: age = int(age_str) break except ValueError: self.tts_speak("请说出有效的数字年龄。") self.tts_speak("Please say your interests.") interests = self.get_voice_input() profile = UserProfile(name, age, interests) self.profiles.append(profile) self.save_profiles() self.tts_speak(f"Profile created for {name}.")
- 资源管理优化:程序退出时停止pyttsx3引擎,避免资源泄漏:
def __del__(self): self.tts_engine.stop()
- 代码结构拆分:将创建档案的步骤拆分为小函数,提升可读性:
def _get_user_name(self): self.tts_speak("Please say your name.") return self.get_voice_input() def _get_user_age(self): while True: self.tts_speak("Please say your age.") age_str = self.get_voice_input() try: return int(age_str) except ValueError: self.tts_speak("请说出有效的数字年龄。")
- 日志替代print:使用
logging模块替代print,便于调试和记录:
import logging logging.basicConfig(level=logging.INFO) # 替换所有print为logging.info()/logging.error()
- 扩展命令匹配:支持模糊命令触发,比如"add profile"也能触发创建逻辑:
def process_voice_input(self): spoken_text = self.get_voice_input().lower() if any(cmd in spoken_text for cmd in ["create", "add", "new"]): self.create_profile() elif any(cmd in spoken_text for cmd in ["list", "show", "view"]): self.list_profiles() elif "exit" in spoken_text: self.save_profiles() self.tts_speak("Exiting program. Goodbye!") exit() else: self.tts_speak("Invalid command. Please try again.")
3. pyttsx3接入Nvidia Audio2Face
方法一:生成音频文件导入
pyttsx3支持将TTS内容保存为WAV文件,再导入Audio2Face驱动面部动画:
- 修改
tts_speak方法,增加保存逻辑:
def tts_speak_and_save(self, text, save_path="tts_output.wav"): try: self.tts_engine.save_to_file(text, save_path) self.tts_engine.runAndWait() print(f"音频已保存到 {save_path}") except Exception as e: print(f"TTS保存失败: {e}")
- 在Audio2Face中,打开
Audio2Face Streaming窗口,点击Load Audio File选择生成的WAV文件即可驱动面部动画。
方法二:实时音频流推送
通过Omniverse Kit的Python API实现实时推送,步骤如下:
- 启动Audio2Face,开启
Real-Time Audio Input(在Audio2Face Streaming窗口勾选)。 - 安装Omniverse Python SDK,连接到Audio2Face实例并推送音频流:
from omni.audio2face.player import AudioPlayer import pyttsx3 import pyaudio import numpy as np # 初始化TTS引擎和Audio2Face播放器 engine = pyttsx3.init() player = AudioPlayer() p = pyaudio.PyAudio() # 设置TTS采样率匹配Audio2Face(48000Hz) engine.setProperty('rate', 48000) # 捕获TTS输出并推送到Audio2Face def tts_to_a2f(text): # 创建临时音频流捕获TTS输出 stream = p.open(format=pyaudio.paInt16, channels=1, rate=48000, output=True) def callback(in_data, frame_count, time_info, status): # 将TTS输出转换为numpy数组并推送 audio_data = np.frombuffer(in_data, dtype=np.int16) player.push_audio(audio_data) return (in_data, pyaudio.paContinue) stream.set_callback(callback) stream.start_stream() engine.say(text) engine.runAndWait() stream.stop_stream() stream.close()
注:pyttsx3本身不直接提供音频数据获取接口,需借助pyaudio捕获输出流;也可改用coqui-tts等支持直接输出音频数组的TTS库简化流程。
内容的提问来源于stack exchange,提问作者Owen Tharp
相关产品推荐
相关产品推荐

