VAD、打断与陈旧事件
实时交互不是把完整录音缩短。客户端持续采集,VAD判断语音活动,服务端生成音频,播放端另有缓冲。生成完成不等于用户听完;用户打断时既要取消生成,还要丢弃旧缓冲,并同步服务端对话已播放范围。
下面用generation区分轮次。cancel可能晚到,旧音频仍可能在网络上,因此播放入口还要检查身份。
python
class Player:
def __init__(self):
self.generation = 0
self.queue = []
self.played_ms = 0
def start(self):
self.generation += 1
self.queue.clear()
self.played_ms = 0
return self.generation
def receive(self, generation, duration):
if generation == self.generation:
self.queue.append(duration)
def play_one(self):
if self.queue:
self.played_ms += self.queue.pop(0)
p = Player()
old = p.start(); p.receive(old,100); p.play_one()
heard = p.played_ms
new = p.start()
p.receive(old,200)
p.receive(new,50)
assert heard == 100
assert p.queue == [50]
p.play_one()
assert p.played_ms == 50
print('stale audio rejected')heard记录旧回答实际播出的范围;真实接口可能用conversation.item.truncate截断到音频毫秒位置,使服务端历史不包含用户没听到的部分。Realtime客户端事件区分取消生成与截断会话,两者不可互相替代。具体事件结构随接口版本核对。
VAD的阈值、静音时长和语义端点影响抢话与等待。背景音乐可能触发错误分段,过短静音会把一句话拆成多轮;按设备与场景标注音频评估,不把某个阈值当通用值。push-to-talk仍是清晰可控的备用方式。
工具执行在语音场景同样有副作用:用户打断播报不必然取消已经提交的付款。区分会话轮次、模型response_id和工具operation_id,分别管理取消与幂等。网络重连先恢复已确认状态,不重播已完成的写操作。
练习
连续启动两次新轮次,再送入两个旧轮次的音频,断言队列为空;然后新轮次音频仍能播放。
完成后查看本章答案。
下一篇:真实SDK会话、打断与服务端历史截断。