Skip to content

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会话、打断与服务端历史截断。

用心记录每一步成长