彻底解决回声问题:实现设备分离播放
- 播放时完全关闭音频输入流 - 使用系统播放器(aplay)避免设备冲突 - 添加安全的播放方式play_audio_safe - 播放前后增加延迟确保设备状态切换 - 完全解决硬件串扰和声学回声问题
This commit is contained in:
parent
e6341b8620
commit
072bb0e6b0
@ -169,20 +169,31 @@ class EnergyBasedRecorder:
|
||||
def play_audio(self, filename):
|
||||
"""播放音频文件"""
|
||||
try:
|
||||
# 立即停止当前录音并清空缓冲区
|
||||
print("🔇 准备播放,完全停止音频输入")
|
||||
|
||||
# 立即停止当前录音并清空所有缓冲区
|
||||
if self.recording:
|
||||
print("🔇 播放开始,停止当前录音")
|
||||
self.recording = False
|
||||
self.recorded_frames = []
|
||||
self.recording_start_time = None
|
||||
self.last_sound_time = None
|
||||
|
||||
# 清空预录音缓冲区,避免录制播放的音频
|
||||
# 清空所有缓冲区
|
||||
self.pre_record_buffer = []
|
||||
self.energy_history = []
|
||||
|
||||
# 完全关闭输入流
|
||||
if self.stream:
|
||||
self.stream.stop_stream()
|
||||
self.stream.close()
|
||||
self.stream = None
|
||||
|
||||
# 设置播放状态
|
||||
self.is_playing = True
|
||||
|
||||
# 等待一小段时间确保音频设备完全停止输入
|
||||
time.sleep(0.5)
|
||||
|
||||
with wave.open(filename, 'rb') as wf:
|
||||
channels = wf.getnchannels()
|
||||
width = wf.getsampwidth()
|
||||
@ -209,7 +220,7 @@ class EnergyBasedRecorder:
|
||||
)
|
||||
|
||||
print(f"🔊 开始播放: {filename}")
|
||||
print("🚫 暂停录音处理,避免回声")
|
||||
print("🚫 音频输入已完全关闭")
|
||||
|
||||
# 分块播放音频
|
||||
for chunk in frames:
|
||||
@ -219,7 +230,7 @@ class EnergyBasedRecorder:
|
||||
playback_stream.close()
|
||||
|
||||
print("✅ 播放完成")
|
||||
print("🔄 恢复录音监听")
|
||||
print("🔄 重新开启音频输入")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 播放失败: {e}")
|
||||
@ -227,8 +238,16 @@ class EnergyBasedRecorder:
|
||||
finally:
|
||||
# 恢复播放状态
|
||||
self.is_playing = False
|
||||
# 重置状态,准备重新监听
|
||||
|
||||
# 等待播放完全结束
|
||||
time.sleep(0.3)
|
||||
|
||||
# 重新开启输入流
|
||||
self._setup_audio()
|
||||
|
||||
# 重置所有状态
|
||||
self.energy_history = []
|
||||
print("📡 音频输入已重新开启")
|
||||
|
||||
def play_with_system_player(self, filename):
|
||||
"""使用系统播放器播放音频"""
|
||||
@ -236,11 +255,65 @@ class EnergyBasedRecorder:
|
||||
import subprocess
|
||||
cmd = ['aplay', filename] # Linux系统
|
||||
print(f"🔊 使用系统播放器: {' '.join(cmd)}")
|
||||
print("🚫 系统播放器播放中,音频输入保持关闭")
|
||||
subprocess.run(cmd, check=True)
|
||||
print("✅ 播放完成")
|
||||
print("📡 音频输入已保持关闭状态")
|
||||
except Exception as e:
|
||||
print(f"❌ 系统播放器也失败: {e}")
|
||||
|
||||
def play_audio_safe(self, filename):
|
||||
"""安全的播放方式 - 使用系统播放器"""
|
||||
try:
|
||||
print("🔇 准备播放,完全停止音频输入")
|
||||
|
||||
# 立即停止当前录音并清空所有缓冲区
|
||||
if self.recording:
|
||||
self.recording = False
|
||||
self.recorded_frames = []
|
||||
self.recording_start_time = None
|
||||
self.last_sound_time = None
|
||||
|
||||
# 清空所有缓冲区
|
||||
self.pre_record_buffer = []
|
||||
self.energy_history = []
|
||||
|
||||
# 完全关闭输入流
|
||||
if self.stream:
|
||||
self.stream.stop_stream()
|
||||
self.stream.close()
|
||||
self.stream = None
|
||||
|
||||
# 设置播放状态
|
||||
self.is_playing = True
|
||||
|
||||
# 等待确保音频设备完全停止
|
||||
time.sleep(0.5)
|
||||
|
||||
print(f"🔊 开始播放: {filename}")
|
||||
print("🚫 使用系统播放器,音频输入已完全关闭")
|
||||
|
||||
# 使用系统播放器
|
||||
self.play_with_system_player(filename)
|
||||
|
||||
print("🔄 准备重新开启音频输入")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 播放失败: {e}")
|
||||
finally:
|
||||
# 恢复播放状态
|
||||
self.is_playing = False
|
||||
|
||||
# 等待播放完全结束
|
||||
time.sleep(0.5)
|
||||
|
||||
# 重新开启输入流
|
||||
self._setup_audio()
|
||||
|
||||
# 重置所有状态
|
||||
self.energy_history = []
|
||||
print("📡 音频输入已重新开启")
|
||||
|
||||
def update_pre_record_buffer(self, audio_data):
|
||||
"""更新预录音缓冲区"""
|
||||
self.pre_record_buffer.append(audio_data)
|
||||
@ -284,7 +357,8 @@ class EnergyBasedRecorder:
|
||||
if success and filename:
|
||||
print("=" * 50)
|
||||
print("🔊 播放刚才录制的音频...")
|
||||
self.play_audio(filename)
|
||||
# 优先使用系统播放器避免回声
|
||||
self.play_audio_safe(filename)
|
||||
print("=" * 50)
|
||||
|
||||
self.recording = False
|
||||
|
||||
Loading…
Reference in New Issue
Block a user