Twilio Voice SDK移动端浏览器触发AcquisitionFailedError(31402)报错
问题诱发原因
- 核心原因是安卓端Chrome对麦克风媒体采集设置了严格的用户手势有效期校验:用户点击按钮产生的可信操作链路,会在遇到
await异步等待时失效。你当前的代码逻辑是点击call按钮后先异步请求token,等接口返回后才初始化Twilio设备、发起麦克风采集请求,此时用户手势的可信状态已经过期,安卓系统直接拦截了媒体采集操作,最终抛出31402错误。Windows桌面版Chrome对手势链路的有效期限制更宽松,因此不会触发该问题。 - 次要兼容性问题:你使用的Twilio Voice SDK 2.0.1版本默认的音频采集参数强制开启自动增益控制,部分安卓12设备的系统音频驱动对该配置的支持存在缺陷,即使权限校验通过也会导致媒体流初始化失败。
- 额外逻辑缺陷:你每次发起呼叫都会新建Twilio.Device实例,且错误监听仅绑定在连接建立后的connection对象上,设备初始化阶段的媒体错误无法被正常捕获,会进一步提高问题排查难度。
修复方案
- 调整代码执行顺序,把设备初始化、麦克风权限申请的逻辑放到用户点击call的同步执行链路最前端,在异步请求token之前就完成媒体采集权限申请,保证
getUserMedia调用处于用户手势的有效周期内。 - 显式配置音频采集约束,关闭易触发安卓兼容性问题的强制自动增益配置,指定单声道采集适配移动端音频硬件。
- 给Twilio.Device实例绑定全局错误监听,覆盖初始化、连接全流程的错误场景,呼叫结束后主动销毁Device实例避免内存泄漏。
- 修复后的完整代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Twilio Call Demo</title> <script src="https://cdn.jsdelivr.net/npm/@twilio/voice-sdk@2.0.1/dist/twilio.min.js"></script> <script> let device = null; let connection = null; const call = async () => { const errorDisplay = document.getElementById("error-display"); errorDisplay.innerHTML = ""; try { // 用户点击后同步初始化设备,处于可信手势链路内 device = new Twilio.Device({ audioConstraints: { audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: false, // 关闭强制自动增益,兼容安卓12音频驱动 channelCount: 1 // 强制单声道采集,适配移动端硬件 } } }); // 注册全局错误监听,覆盖全流程错误 device.on("error", (err) => { errorDisplay.innerHTML = err.message; }); // 同步触发麦克风权限申请,在手势有效期内完成媒体获取 await device.register(); // 媒体权限校验通过后,再异步请求token建立连接 const response = await fetch("https://my.token.endpoint/token"); const data = await response.json(); device.updateToken(data.token); connection = await device.connect(); } catch (err) { errorDisplay.innerHTML = err.message; } }; const stop = () => { connection?.disconnect(); connection = null; device?.destroy(); device = null; }; </script> </head> <body> <button onclick="call()">call</button> <button onclick="stop()">stop</button> <p id="error-display"></p> </body> </html>
- 额外校验项:确保访问页面使用的是
https://协议或本地localhost地址,安卓Chrome在非安全上下文的http页面下会直接禁止麦克风权限申请,同样会触发该类媒体获取错误。
内容的提问来源于stack exchange,提问作者Kazuto_Ute
相关产品推荐
相关产品推荐

