101 lines
4.1 KiB
Markdown
101 lines
4.1 KiB
Markdown
# 缓存音频播放完成检测修复总结
|
||
|
||
## 问题描述
|
||
缓存音频播放时,系统在音频还未播放完成时就错误地发送了完成信号。具体表现为:
|
||
- 缓存音频播放到6-7秒时,系统错误地检测到播放完成
|
||
- 发送完成事件并重置播放状态,导致音频被中断
|
||
- 用户听到的是不完整的音频播放
|
||
|
||
## 根本原因分析
|
||
1. 在 `_play_cached_audio()` 方法中,当播放开始时就立即设置了 `tts_generation_complete = True` 和 `llm_generation_complete = True`
|
||
2. `_check_enhanced_playback_completion()` 方法没有区分缓存音频和普通TTS音频
|
||
3. 当主控制系统发送结束信号时,播放完成检测机制错误地认为所有条件都已满足
|
||
|
||
## 修复方案
|
||
|
||
### 1. 添加缓存音频状态标识
|
||
在 `OutputProcess` 类的 `__init__` 方法中添加:
|
||
```python
|
||
self.is_playing_cached_audio = False # 是否正在播放缓存音频
|
||
```
|
||
|
||
### 2. 修改 `_play_cached_audio()` 方法
|
||
- 移除立即设置 `tts_generation_complete` 和 `llm_generation_complete` 的代码
|
||
- 添加缓存音频状态设置:
|
||
```python
|
||
# 设置缓存音频播放状态
|
||
self.is_playing_cached_audio = True
|
||
```
|
||
- 在发送TTS完成信号后,只设置TTS完成状态:
|
||
```python
|
||
# 缓存音频没有真正的TTS过程,所以立即设置TTS完成状态
|
||
# 但不设置LLM完成状态,让缓存音频完成检测逻辑处理
|
||
self.tts_generation_complete = True
|
||
```
|
||
|
||
### 3. 添加专门的缓存音频完成检测方法
|
||
新增 `_check_cached_audio_completion()` 方法:
|
||
```python
|
||
def _check_cached_audio_completion(self):
|
||
"""缓存音频播放完成检测 - 简化逻辑,不依赖LLM和TTS完成状态"""
|
||
# 更新状态变量
|
||
self.pre_buffer_empty = (len(self.preload_buffer) == 0)
|
||
self.playback_buffer_empty = (len(self.playback_buffer) == 0)
|
||
self.no_active_playback = (not self.currently_playing)
|
||
|
||
# 计算时间差
|
||
current_time = time.time()
|
||
time_since_last_chunk = current_time - self.last_audio_chunk_time
|
||
|
||
# 缓存音频完成条件:
|
||
# 1. 缓冲区都为空
|
||
# 2. 没有活跃播放
|
||
# 3. 至少1秒没有新音频播放(确保音频完全播放完成)
|
||
if (self.pre_buffer_empty and
|
||
self.playback_buffer_empty and
|
||
self.no_active_playback):
|
||
|
||
if self.last_audio_chunk_time > 0 and time_since_last_chunk > 1.0:
|
||
print(f"✅ 缓存音频播放完成:缓冲区已清空,播放器空闲,{time_since_last_chunk:.2f}秒无新音频")
|
||
return True
|
||
else:
|
||
return False
|
||
else:
|
||
return False
|
||
```
|
||
|
||
### 4. 修改 `_check_enhanced_playback_completion()` 方法
|
||
在方法开头添加缓存音频检测逻辑:
|
||
```python
|
||
# 如果正在播放缓存音频,使用简化的完成检测逻辑
|
||
if self.is_playing_cached_audio:
|
||
return self._check_cached_audio_completion()
|
||
```
|
||
|
||
### 5. 确保状态正确重置
|
||
在 `_finish_playback()` 方法中添加:
|
||
```python
|
||
self.is_playing_cached_audio = False # 重置缓存音频播放状态
|
||
```
|
||
|
||
## 修复效果
|
||
修复后的系统具有以下特性:
|
||
1. **区分音频类型**:能够区分缓存音频和普通TTS音频
|
||
2. **简化检测逻辑**:缓存音频使用简化的完成检测逻辑,不依赖LLM和TTS完成状态
|
||
3. **确保完整播放**:只有当缓冲区为空、播放器空闲且至少1秒无新音频时才认为播放完成
|
||
4. **状态管理**:正确管理所有相关状态,确保状态一致性
|
||
|
||
## 测试验证
|
||
创建了专门的测试脚本验证修复效果:
|
||
- ✅ 新增状态变量和方法正确
|
||
- ✅ 缓存音频完成检测逻辑正确
|
||
- ✅ 缓存音频播放中检测逻辑正确
|
||
|
||
## 注意事项
|
||
1. 该修复不影响普通TTS音频的播放完成检测
|
||
2. 主控制系统的逻辑保持不变
|
||
3. 缓存音频播放仍然遵循原有的音频播放流程
|
||
4. 修复向后兼容,不会破坏现有功能
|
||
|
||
## 结论
|
||
通过区分缓存音频和TTS音频的播放完成检测逻辑,成功解决了缓存音频提前结束的问题。现在缓存音频能够完整播放,只有在真正播放完成后才会发送完成事件。 |