让 AI 自己去面试
让 AI 自己去面试 · 第二季 · 音频工程专题 · EP09

静默的 blob,一段 URL 如何骗过了整个系统

时长 14 分 44 秒 · 单人旁白 · 8 个章节 · 147 条滚动字幕
听众:AI / 自动化开发者为主,PM 与泛科技读者可无障碍收听

一句话概要

系统告诉你的「完成」,和世界真的发生变化,是两件不同的事。这一集讲同一家族的三种失败,播完了但没播出来。

本集要点

一、什么叫静默的失败

代码认为自己把活干完了,日志正常,连播放结束事件都老实触发了,而另一端一个比特的声音都没有。

共同性格是不报错,日志正常,让人先去怀疑硬件和别人。

二、声音是怎么被塞进那根线的

答案文本切句,并行合成,多段连续无缝播放,全程定向到同一张卡。

必须显式指定的原因是,默认设备上坐着的是面试官通道。指错或没指定成,答案会跑到面试官那条路上,那边的人听得一清二楚,而本该听到答案的平台什么都收不到。

三、给一段音频起名字的两种方式

方式做法特点
data 形式把整段字节编码成文本,直接拼进地址字符串极长,抄一份多占一份地方
blob 形式先申请一块临时空间放字节,拿到临时地址短,用完必须显式释放

普通页面里两者常被当作等价互换,也确实表现一致。但这是一个只在自动化环境现身的坑,而自动化环境恰恰最缺人耳朵。

四、播完了,但电平是零

现象是,文本正常、段数正常、每段都触发了播放结束事件、调用方认为播完了,而同时测着的目标线电平恒为零。

症状与虚拟线坏了一模一样,于是第一反应全跑到硬件那边去查驱动、查格式、查端点,全部白查。

当场能排除硬件的依据是,那几根虚拟线在此前一天刚做完完整验收,证据目录里明确写着有信号,面试官线 0.1905、答案线 0.1892。同样的音频、同样的播放代码,只是换了内容,方向就该换。

代码留了一段长注释写死结论,必须用 blob 形式,不能用 data 形式。诚实边界是,机制层面属于推理而非读源码得出,且由于错误与结束走同一分支,当时其实分不清它是真播完还是走了错误分支。

五、第二种静默:卡住的等待

停止播报时只调用暂停,音频既没播完也没出错,于是结束与出错两个事件都不会再触发,外层的等待永远等不到回音。

后果链条:监听循环永久卡住,表示正在说话的标志恒为真,后面排队的所有句子一句都不再播。日志上文字照常进来、照常切句、照常入队,一切正常,只是没有一句说出口。平台随后必然问出那句话。

修法只有一行却很关键,停止时除了暂停,还要把等待着的那个兑现函数调用掉。

通用规则:取消语义必须包含兑现,而不只是包含终止。暂停某个异步操作时先问,谁在等它的结果,我要不要替它把结果交出去。

六、第三种形态:播不结束的段

实测有一段 5.57 秒的音频,47 秒才报告结束。症状与上一种完全一样,外层被永久挂住。

对策是逐段看门狗,超时值按实测时长乘以三再加十秒计算。到点未结束就暂停该段、标记停滞、跳过剩余段落交给调用方记账。

取舍在于,剩余句子是被放弃而不是重试,因为被拖死的代价大于少说几句。另外要把被打断与被判停滞区分开,前者是外部主动、属正常交互,后者是内部发现的异常,二者的改进方向完全不同。

七、带走的判断

素材锚点

AGENTS.md 陷阱节(data 形式静默不出声、停止播报必须连带兑现);autobot/lib/assistant.js 的 playSegments 与 stopPlayback 实现及其注释。

实测锚点:2026-10-07 data 形式静默不出声;sim7 / sim8 场次卡在等待;某段 5.57 秒音频 47 秒才结束。

《让 AI 自己去面试》第二季 · 音频工程专题 · 单人旁白 · 蓝灰主题
本集音频由 edge-tts 合成,字幕时间戳对齐到毫秒。
← 上一期EP08 装了驱动不重启:最阴险的一种故障下一期 →EP10 打断的艺术:平台说「没听到」时你在干什么