设备正在播报“客厅的灯已经打开”,下一轮识别却把这句话当成用户输入。你检查配置,发现 AEC 已启用,于是准备把抑制强度调高。

先停一下。AEC 开关只能说明算法进入了处理链,不能证明它拿到了与这次扬声器播放对应的参考音频。 如果参考缺失或通道顺序错了,调参数只会让排障变得更难。这是一个排障假设场景,以下方法来自官方资料和工程推导,尚未在某块实体板卡上实测。

AEC 已启用仍需核对播放参考

先确认 AEC 收到的到底是哪几路音频

乐鑫 ESP-SR 的 AFE 文档对输入格式的定义很具体:M 是麦克风通道,R 是播放参考,N 是未用或未知通道;MMNR 表示两路麦克风、一路未用和一路播放参考。送入 AFE 的数据还必须按配置的通道顺序交织。单麦场景也可以是 MR,官方基准就列出了这样的管线。

乐鑫 AFE 输入格式官方要点摘录

这些字段把一个常见误会暴露出来:服务端知道 TTS 文本,或设备拿到过一段待播音频,都不等于 AEC 的 R 通道收到了本次实际播放的参考样本。应用要沿实际路径核对:解码后的音频从哪里进功放和扬声器?哪一路同时间的样本进 R?麦克风样本在哪一路进 M?AFE 的 input_format 与数据交织顺序是否一致?

如果参考取自错误的播放缓冲、对应了上一段语音,或音量变化发生在参考分支之后,AEC 可能面对与麦克风回声不匹配的输入。这里是需要用录音证实的可能故障机制,不是仅凭配置文件就能宣告的现场原因。

实际播放与 R 参考同源的作者示意

把通道配置翻成可以核对的样本顺序

先不要从文件名判断哪一路是参考。沿软件实际调用查输入缓冲:单次送入 AFE 的数据包含几路、每路对应哪个硬件或软件源、通道交织怎样排列。对于 MR,可以用概念上的 M0、R0、M1、R1 表示连续两个时刻的顺序;对于 MMNR,则每个时刻都应包含对应的四路样本。这个符号只是检查顺序的示意,不是新增的乐鑫接口或固定样本格式。实际位宽、块长和采样率仍按所用版本配置核对。

若采集得到的是多通道数据,应用只截取前半段就当单麦输入,可能改变样本时间顺序;若配置声明参考在第四路,实际却把参考拼到第二路,也可能让算法读到另一种信号。排查时把通道解交织后分别保存,先确认 M 是可听的麦克风、R 是当前播放、N 的内容符合实际用途。不能因为总字节数对上,就认为各路语义也对上。

参考的来源也要追到样本级。TTS 文本不是波形,服务端压缩音频还需要设备解码,待播缓冲又不一定全部真正送到扬声器。用户打断、播放队列丢弃或解码失败时,计划播放与实际播放会分叉。参考分支若持续送计划音频,而扬声器已经停止,便存在需要检查的不匹配。反过来,扬声器在继续放而参考先停止,也不能只靠开启 AEC 修复。

因此画通道图时,把解码、重采样、音量调整、排队、实际写播放接口以及参考取样位置都标清楚。不是每一块板都经过全部环节,有哪个就画哪个。每个可能改变音频的操作同时问两件事:它发生在参考分支之前还是之后;它如何影响参考与实际播放对应关系。图画完之后,再用短样本确认,避免仅凭设计图推断运行正确。

参考同源也不等于参考与麦克风完全同时。声音从扬声器传播到麦克风,录放链路还有自己的缓冲。需要确认三路样本的时序关系稳定,并记录实际延迟变化;不能用 TTS 开始事件的一个时间戳替代持续样本对齐。本文没有测得某板卡延迟,也不为算法给统一容忍阈值。

如果参考对应上一段语音,观察内容就能帮助定位。播放本次不同的短句,检查保存的 R 能否听到它,与 M 中回声是否同一段。若 R 仍是旧句子,先修队列或缓冲身份;若内容正确但开始与结束明显错位,再看录放时序。内容身份和时间对齐先分开查,比直接调抑制参数更容易解释结果。

再检查录放链路,别先把抑制开到最大

乐鑫 FAQ明确指出,AEC 效果不仅取决于软件参数,还取决于无失真播放、无噪声录音和有效的回声参考;表现差时应先检查硬件录放路径。扬声器削顶、麦克风饱和、持续底噪、参考缺失,都应该在换模式之前排除。

乐鑫 FAQ 录放硬件与有效参考要点摘录

最有用的做法,是在同一块板、同一固件、固定音量下留下三组短录音。每组同时保存播放参考 R、原始麦克风 M 和 AEC 输出,并记录时间标记。这是本文设计的排障实验,不是乐鑫的统一验收标准。

场景应看见什么主要定位的问题
仅设备播放R 有本次播报;M 能听到被扬声器拾回的声音;比较 AEC 输出参考是否存在、是否对应当前播放,回声是否下降
仅真人近讲R 应无这次设备播报;比较原始 M 与输出算法是否错误削弱近端人声
设备播放时真人插话三路都留样本,听输出中设备声与真人声双讲时能否压低回声,同时保留用户讲话

三段录音分别定位回声和人声问题

录音旁边至少记下板卡、麦克风/功放/codec、AFE 输入格式、采样率、AEC 模式、音量和录制位置。只保存处理后的输出,听出问题后也很难分清是参考通道、原始录音还是算法参数。三路录音要能在同一时间线上对齐;“波形看起来差不多”不能证明同步正确。允许的参考延迟取决于实际算法版本和板卡测试,本文不编一个通用毫秒阈值。

让录音能定位原因,而不是增加另一个负载

三路录音应尽量保持采集方式一致。若为排障新增同步写盘,把实时音频任务阻塞,录音本身可能改变队列节奏或造成样本丢失。可以沿现有缓冲和异步记录路径留证据,同时记录丢块计数与采集开关;若不能避免负载变化,就说明样本可能受记录过程影响,之后在轻量方式下复测。这个提醒是工程推导,没有断言当前固件存在写盘阻塞。

文件头和播放解释也要与真实样本一致。采样率、位宽、通道数写错,听到的速度、音调或杂音可能来自文件解释错误,而不是 AEC。保留采集配置和原始数据,在分析前确认解码方式;若转换为方便听审的格式,转换参数也保存。否则“原始录音很脏”的判断可能连输入格式都没有核实。

仅设备播放的样本里,R 应包含这次播报,M 应包含环境中的播放回声。AEC 输出与原始 M 比较,才能说明播放分量是否下降。若 M 本来就几乎听不到设备声,输出干净并不能证明算法消得很好;若输出全静音,也要核对是不是输入链路断了,不能直接当极佳抑制。

仅真人近讲时,确认设备没有同步播音,再听原始 M 与输出的人声差异。原始 M 已经含削顶、爆音或明显底噪,应先把这些写为输入问题;原始 M 清楚而输出损伤,才更有理由检查处理模式与参数。这样把硬件输入和算法输出放在同一段样本里,对照会更明确。

双讲录音最关键的不是“还有没有一点设备声”,而是用户插话是否仍可理解。可以选择与设备播报明显不同的短句,标出用户开始和结束时间,分别听设备声残留与近端语音保留。不要因听起来更安静就宣布自然打断通过;把真人也压没了,语音 Agent 反而更难知道用户在说话。

音量对照一次只改一个条件。固定板卡、固件、位置与文本,先留一组正常音量,再逐步改变播放音量,记录每档三路样本。若同时改变距离与音量,回声路径和信号幅度一起变化,很难解释某次退步。这里不提供推荐档位,实际范围由硬件和使用场景决定。

外壳和摆位也属于条件。裸板测得的录放关系不能直接保证装壳后的声学表现;麦克风和扬声器的距离、开孔以及表面反射都会改变实际观察。先在固定摆位验证输入路径,再在目标外壳和常用距离下重复三组录音。路径验证与产品效果验证分阶段进行,才能知道哪个条件带来了新问题。

根据三组结果决定下一步

仅设备播放时仍残留大量播报声,先查 R 是否缺失、错通道、截断,或者落在上一段播放上,再核对录放是否失真。仅真人近讲时人声被削弱,就需要检查抑制模式与强度。只有双讲失败时,不要拿“单独播放时回声消掉了”当作自然打断通过。

乐鑫 ESP32-S3 AEC 文档把识别、全双工和通话模式分开,还提醒全双工模式下更激进的非线性抑制可能损伤近端语音。于是“更强”并不是单调更好:回声变少的同时,真人插话可能更难听清。官方基准表也只对应特定板卡和配置,不能把其中的 CPU、内存或唤醒数据直接套在另一块设备上。

按结果修路径调参数或检查上层回送

最后要分清三个问题。AEC 尝试从麦克风录音中去掉设备播放声;VAD 判断是否有人声活动;Agent 打断还要停止旧播放并处理旧轮次。一段 AEC 输出干净,并不能证明完整打断链路正确。 如果三组录音正常,但 Agent 仍把自己的声音当成用户输入,再查播放尾音、VAD/ASR 输入位置和轮次取消时序。

修一处之后,重跑能推翻它的样本

假设找到 R 通道取错缓冲,修复后应重新做仅播放、仅近讲和双讲三组。仅播放改善支持参考修复有作用,但近讲或双讲若退步,仍不能宣布整个前端已可用。修复前后保持相同文本、音量和位置,把三路录音按同一时间线比较;不要拿不同场景的最佳样本作为前后证据。

若 R 内容、通道和时序都能核实,录放也没有明显失真,再做模式或抑制强度对照。每次保留生效配置与完整录音,先看目标问题是否改善,再看近端语音是否损伤。强参数可能减少残留,却不能因此自动满足双讲需求。官方关于非线性抑制代价的提醒,正适合在这一步转成可检验的取舍。

对参数对照,也不要混用不同 SDK、模型或输入格式。一个版本的默认值与另一个版本的行为不一定一致,保存实际固件构建信息和配置摘要,才可以让后来的开发者复现。本文不要求无必要重新 build;要的是从当前已运行固件或既有构建记录确认版本,缺少信息就注明未知。

如果三路音频合理而 ASR 仍识别设备声,先核 ASR 实际读取的是原始 M 还是 AFE 输出。存在旁路或旧缓冲时,AEC 即使工作,也没有作用到识别入口。再看 VAD 取点、播放停止后残留音频、以及旧轮次的发送缓冲。把每段样本附上所属会话与播放身份,能判断是不是旧音频晚到,而不把所有“听到自己”都归为声学回声。

轮次取消也不等于音频样本立即消失。停止 TTS 生成、清掉待播队列、停止硬件播放、清理旧识别输入,各自有实际边界。若用户打断发生在这些边界之间,旧播报尾部可能仍进入下一次上传。此时要追从播放尾部到 VAD/ASR 的时间线,不能凭 AEC 配置替上层取消完成背书。

可在排障记录里写出每一种假设的反证。R 缺失假设可由当前播放参考录音证伪;通道错序可由解交织后的分路信号证伪;抑制伤人声可由原始近讲和处理输出比较;上层旁路可由识别入口数据来源核实。结果支持哪个假设就修哪一处,不同时修改全部环节后再称定位完成。

最后的结论最好分三层:输入路径是否核实、三组离线样本是否满足当前观察目标、真实设备在目标使用条件下是否完成验收。前两层可以帮助排障,第三层还需要实际用户距离、音量、外壳和对话流程。本文只提供待运行的方法与公开资料依据,不填写任何一层的实测通过。

避免用一个指标覆盖不同问题

回声降低、近端语音保留、识别正确和自然打断是不同结果。仅播放时输出中的设备声变弱,支持这一段回声处理改善;仅真人时人声仍清楚,支持近端损伤没有在这组样本中出现;双讲时用户短句可辨,才有双讲保留证据;Agent 停止旧播放并接受新意图,则属于完整交互。不要用其中一个结果替全部环节盖章。

如果计划量化,也先说明指标怎样算、在哪些片段上算。整段输出能量变小可能来自静音,也可能来自人声一并被抑制;总平均值无法指出双讲中的用户声是否丢失。需要按仅播放、近讲、双讲的时间范围分别观察,并保留可听原片。本文没有测量数据,所以不给任何衰减数值或推荐合格线。

识别结果也要附音频输入位置。同一句 TTS 被 ASR 转写出来,既可能是实际回声泄漏,也可能是上层直接回送了播放音频。只有保留 ASR 收到的音频与三路录音,才能比较内容和时序,判断它是否来自麦克风链路。不要因文字相同就断言硬件回声路径出了问题。

对用户插话,先确认真实人声进入了 M。若原始麦克风本身就没有这段话,后续输出或 ASR 没检出不能归因于 AEC 抑制。若 M 有、处理输出无,才缩小到前端;若处理输出有、ASR 输入无,则继续追后续队列与上传。逐层比较同一段内容,比每层分别截一张开启日志更有力。

播放结束后的尾音还可以单独观察。R 已停止而环境中仍有残留声音时,要记录这一段与下一轮语音活动的关系;设备上层若直接开启新轮次,尾音可能影响判断。是否需要延后切换、怎样处理尾部,都应由目标设备实际效果决定,不能编一个固定等待值当通用修复。

给下一位排障者保留可复查的交付

每个样本附一个简短身份:场景、板卡、固件版本、输入格式、音量、位置、录音起止与丢块情况。文件名只用于方便寻找,真正判断依靠清单中的配置和样本 SHA。修复前后分别保留,不覆盖原始失败证据。后续若换外壳或参数,可以知道对照对象究竟有没有变化。

通道图则附上真实取点和未确认位置。例如“参考来自播放提交缓冲,是否对应硬件实际消费尚未核实”,就比画一条无条件的同步箭头准确。某一处没有工具可观察,明确写未知,并设计下一段能缩小问题的录音或日志;不要把图上的理想路径当成已经发生的运行事实。

最终报告可以很短:确认了哪些输入、发现哪个具体分歧、改了哪一处、哪些三组样本复测改善、还有哪层缺证据。设备若仍在回声或近端保留上不满足需求,就停在排障进行中。过程里成功导出录音或更新配置,不是自然打断已经通过。

交付排障结果时,请留下输入通道图、三组原始及输出录音、配置和复测结论:R 错了先修路径,输入可信后再比较参数,音频正常后再追 Agent 上层。真实使用效果仍须在目标板卡、外壳、音量和距离下验证;本文没有这一步的实测证据。