回声待处理
This commit is contained in:
parent
d385333e0f
commit
0ab8e49ba5
89
recorder.py
89
recorder.py
@ -100,7 +100,8 @@ class EnergyBasedRecorder:
|
||||
|
||||
# 状态变量
|
||||
self.audio = None
|
||||
self.stream = None
|
||||
self.input_stream = None # 输入流(录音)
|
||||
self.output_stream = None # 输出流(播放)
|
||||
self.running = False
|
||||
self.recording = False
|
||||
self.recorded_frames = []
|
||||
@ -484,19 +485,14 @@ class EnergyBasedRecorder:
|
||||
# 如果强制重置,先完全释放资源
|
||||
if force_reset:
|
||||
self._force_close_audio_stream()
|
||||
if self.audio:
|
||||
try:
|
||||
self.audio.terminate()
|
||||
except:
|
||||
pass
|
||||
self.audio = None
|
||||
# 不终止整个PyAudio实例,只重置输入流
|
||||
|
||||
# 创建新的PyAudio实例
|
||||
# 创建新的PyAudio实例(如果不存在)
|
||||
if not self.audio:
|
||||
self.audio = pyaudio.PyAudio()
|
||||
|
||||
# 创建音频输入流
|
||||
self.stream = self.audio.open(
|
||||
self.input_stream = self.audio.open(
|
||||
format=self.FORMAT,
|
||||
channels=self.CHANNELS,
|
||||
rate=self.RATE,
|
||||
@ -510,8 +506,8 @@ class EnergyBasedRecorder:
|
||||
self.audio_device_healthy = False
|
||||
|
||||
def _force_close_audio_stream(self):
|
||||
"""强制关闭音频流,避免阻塞"""
|
||||
if self.stream:
|
||||
"""强制关闭音频输入流,避免阻塞"""
|
||||
if self.input_stream:
|
||||
try:
|
||||
# 尝试优雅关闭,设置超时
|
||||
import signal
|
||||
@ -524,23 +520,23 @@ class EnergyBasedRecorder:
|
||||
signal.alarm(5)
|
||||
|
||||
try:
|
||||
self.stream.stop_stream()
|
||||
self.stream.close()
|
||||
self.input_stream.stop_stream()
|
||||
self.input_stream.close()
|
||||
finally:
|
||||
signal.alarm(0) # 取消超时
|
||||
|
||||
except TimeoutError:
|
||||
print("⚠️ 音频流关闭超时,强制终止")
|
||||
self.stream = None
|
||||
print("⚠️ 音频输入流关闭超时,强制终止")
|
||||
self.input_stream = None
|
||||
except Exception as e:
|
||||
print(f"⚠️ 优雅关闭音频流失败: {e}")
|
||||
print(f"⚠️ 优雅关闭音频输入流失败: {e}")
|
||||
try:
|
||||
# 强制关闭
|
||||
self.stream = None
|
||||
self.input_stream = None
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
self.stream = None
|
||||
self.input_stream = None
|
||||
self.audio_device_healthy = False # 标记设备需要重置
|
||||
|
||||
def calculate_energy(self, audio_data):
|
||||
@ -1192,10 +1188,23 @@ class EnergyBasedRecorder:
|
||||
|
||||
# 等待音频播放完成后再重新开启音频输入
|
||||
print("⏳ 等待音频播放完成...")
|
||||
while not self.audio_playback_queue.empty() or self.currently_playing:
|
||||
queue_size = self.audio_playback_queue.qsize()
|
||||
playing_status = "播放中" if self.currently_playing else "等待播放"
|
||||
print(f"\r🔊 {playing_status}... 队列: {queue_size}", end='', flush=True)
|
||||
|
||||
# 检查多个队列的状态
|
||||
tts_queue_size = self.tts_task_queue.qsize()
|
||||
playback_queue_size = self.audio_playback_queue.qsize()
|
||||
|
||||
while tts_queue_size > 0 or playback_queue_size > 0 or self.currently_playing:
|
||||
tts_queue_size = self.tts_task_queue.qsize()
|
||||
playback_queue_size = self.audio_playback_queue.qsize()
|
||||
|
||||
if tts_queue_size > 0:
|
||||
status = f"🎵 TTS生成中... TTS队列: {tts_queue_size} 播放队列: {playback_queue_size}"
|
||||
elif self.currently_playing:
|
||||
status = f"🔊 正在播放... 播放队列: {playback_queue_size}"
|
||||
else:
|
||||
status = f"⏳ 等待播放... 播放队列: {playback_queue_size}"
|
||||
|
||||
print(f"\r{status}", end='', flush=True)
|
||||
time.sleep(0.1)
|
||||
|
||||
# 额外等待1秒,确保音频设备完全停止
|
||||
@ -1245,7 +1254,7 @@ class EnergyBasedRecorder:
|
||||
|
||||
def run(self):
|
||||
"""运行录音系统"""
|
||||
if not self.stream:
|
||||
if not self.input_stream:
|
||||
print("❌ 音频设备未初始化")
|
||||
return
|
||||
|
||||
@ -1275,42 +1284,50 @@ class EnergyBasedRecorder:
|
||||
try:
|
||||
while self.running:
|
||||
# 检查音频流是否可用
|
||||
if self.stream is None:
|
||||
if self.input_stream is None:
|
||||
print("\n❌ 音频流已断开,尝试重新连接...")
|
||||
self._setup_audio(force_reset=True)
|
||||
if self.stream is None:
|
||||
if self.input_stream is None:
|
||||
print("❌ 音频流重连失败,等待...")
|
||||
time.sleep(1)
|
||||
continue
|
||||
|
||||
# 读取音频数据
|
||||
try:
|
||||
data = self.stream.read(self.CHUNK_SIZE, exception_on_overflow=False)
|
||||
data = self.input_stream.read(self.CHUNK_SIZE, exception_on_overflow=False)
|
||||
except Exception as e:
|
||||
print(f"\n❌ 读取音频数据失败: {e}")
|
||||
self.stream = None
|
||||
self.input_stream = None
|
||||
continue
|
||||
|
||||
if len(data) == 0:
|
||||
continue
|
||||
|
||||
# 检查设备健康状态和播放冷却期 - 防止回声
|
||||
# 检查设备健康状态、TTS状态和播放冷却期 - 防止回声
|
||||
current_time = time.time()
|
||||
time_since_last_play = current_time - self.last_playback_time
|
||||
in_cooldown = time_since_last_play < self.playback_cooldown_period
|
||||
|
||||
# 如果设备不健康、正在播放、播放队列不为空、或在冷却期内,完全跳过音频处理
|
||||
if not self.audio_device_healthy or self.is_playing or self.currently_playing or not self.audio_playback_queue.empty() or in_cooldown:
|
||||
# 检查TTS和播放队列状态
|
||||
tts_active = not self.tts_task_queue.empty()
|
||||
playback_active = not self.audio_playback_queue.empty() or self.currently_playing
|
||||
|
||||
# 如果设备不健康、正在播放、TTS生成中、播放队列不为空、或在冷却期内,完全跳过音频处理
|
||||
if not self.audio_device_healthy or self.is_playing or tts_active or playback_active or in_cooldown:
|
||||
# 显示播放状态
|
||||
tts_queue_size = self.tts_task_queue.qsize()
|
||||
queue_size = self.audio_playback_queue.qsize()
|
||||
|
||||
if not self.audio_device_healthy:
|
||||
status = f"🔧 设备重置中... 队列: {queue_size}"
|
||||
status = f"🔧 设备重置中... TTS: {tts_queue_size} 播放: {queue_size}"
|
||||
elif tts_active:
|
||||
status = f"🎵 TTS生成中... TTS: {tts_queue_size} 播放: {queue_size}"
|
||||
elif in_cooldown:
|
||||
cooldown_time = self.playback_cooldown_period - time_since_last_play
|
||||
status = f"🔊 播放冷却中... {cooldown_time:.1f}s 队列: {queue_size}"
|
||||
status = f"🔊 播放冷却中... {cooldown_time:.1f}s TTS: {tts_queue_size} 播放: {queue_size}"
|
||||
else:
|
||||
playing_status = "播放中" if self.currently_playing else "等待播放"
|
||||
status = f"🔊 {playing_status}... 队列: {queue_size}"
|
||||
status = f"🔊 {playing_status}... TTS: {tts_queue_size} 播放: {queue_size}"
|
||||
print(f"\r{status}", end='', flush=True)
|
||||
time.sleep(0.1) # 播放时增加延迟减少CPU使用
|
||||
continue
|
||||
@ -1427,9 +1444,9 @@ class EnergyBasedRecorder:
|
||||
self.audio_playback_queue.put(None) # 发送结束信号
|
||||
self.playback_worker_thread.join(timeout=3.0)
|
||||
|
||||
if self.stream:
|
||||
self.stream.stop_stream()
|
||||
self.stream.close()
|
||||
if self.input_stream:
|
||||
self.input_stream.stop_stream()
|
||||
self.input_stream.close()
|
||||
|
||||
if self.audio:
|
||||
self.audio.terminate()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user