iflytek/astron-agent · error · Error
code (dynamic; from e.name||e.message, logged as '请求录音权限错误')
Error message
code (dynamic; from e.name||e.message, logged as '请求录音权限错误')
What it means
In recorder-core's getUserMedia permission request path (f2), any exception from navigator.mediaDevices.getUserMedia is converted to code = e.name || e.message || e.code+':'+e, logged as '请求录音权限错误', passed to codeFail ('无法录音:'+code), and thrown as new Error(code). Typical codes are NotAllowedError, NotFoundError, NotReadableError.
Solutions
- Map e.name to a user-facing message: NotAllowedError → enable permission, NotFoundError → connect a mic, NotReadableError → close apps using the mic
- Add allow="microphone" to iframes embedding the console
- Ensure HTTPS origin; getUserMedia is unavailable on insecure pages
- Catch the thrown code and offer a retry (requestPermission again) instead of crashing
Example fix
// before
rec.open(success, fail); // fail receives '无法录音:NotAllowedError'
// after
try {
rec.open(success, (msg) => showMicError(msg));
} catch (code) {
if (code === 'NotAllowedError') promptPermissionFix();
else if (code === 'NotFoundError') promptConnectMic();
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!window.isSecureContext || !navigator.mediaDevices) {
message.error('无法录音:需要 HTTPS 且支持 getUserMedia');
return;
} Type guard
function hasMicAccess() { return !!navigator.mediaDevices?.enumerateDevices; } Try / catch
try {
rec.open(onOk, onFail);
} catch (code) {
switch (code) {
case 'NotAllowedError': showPermissionFix(); break;
case 'NotFoundError': showNoMic(); break;
case 'NotReadableError': showMicBusy(); break;
default: console.error('请求录音权限错误:', code);
}
} Prevention
- Add allow="microphone" to iframes
- Map DOMException names to actionable user messages
- Offer a permission-reset guide (site settings) in the UI
When it happens
Trigger: getUserMedia rejecting: user denied permission (NotAllowedError/SecurityError), no audio input device (NotFoundError), device busy (NotReadableError), or insecure context making mediaDevices undefined.
Common situations: Browser privacy settings blocking mic; external USB mic unplugged mid-session; kiosk browsers without media permissions policy; iframe missing allow="microphone".
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- msg (dynamic; logged as '无法录音:'+msg and shown via…
- msg (dynamic; logged as '无法录音:'+msg and shown via…
- errMsg (dynamic; logged as…
- 未采集到录音
- 不应该出现pcm采样率 和需要的采样率 不一致
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/e86c3576ca8abc8e.
Report an issue: GitHub.
Appendix: source
Thrown at console/frontend/src/utils/record/recorder-core.js:875
Recorder.Stream = stream;
if (lockFail()) return;
if (Recorder.IsOpen()) {
if (oldStream) This.CLog('发现同时多次调用open', 1);
Connect(streamStore, 1);
ok();
} else {
failCall('录音功能无效:无音频流');
}
}, 100);
};
var f2 = function (e) {
var code = e.name || e.message || e.code + ':' + e;
This.CLog('请求录音权限错误', 1, e);
codeFail(code, '无法录音:' + code);
throw new Error(code);
};
var trackSet = {
noiseSuppression: false, //默认禁用降噪,原声录制,免得移动端表现怪异(包括系统播放声音变小)
echoCancellation: false, //回声消除
};
var trackSet2 = This.set.audioTrackSet;
for (var k in trackSet2) trackSet[k] = trackSet2[k];
trackSet.sampleRate = Recorder.Ctx.sampleRate; //必须指明采样率,不然手机上MediaRecorder采样率16k
try {
var pro = Recorder.Scope[getUserMediaTxt]({ audio: trackSet }, f1, f2);
} catch (e) {
//不能设置trackSet就算了
This.CLog(getUserMediaTxt, 3, e);
pro = Recorder.Scope[getUserMediaTxt]({ audio: true }, f1, f2);
}
if (pro && pro.then) {View on GitHub (pinned to 5e758547a8)