iflytek/astron-agent · error
未开始录音
Error message
未开始录音${isCtxWait ? ',开始录音前无用户交互导致AudioContext未运行' : ''} What it means
Recorder-Core's stop() fails because recording never actually started: This.state is 0 (never opened/started) or 3 (open succeeded but the AudioContext is suspended because the browser requires a user gesture before audio processing). The isCtxWait suffix clarifies that user interaction was missing, so the AudioContext never left the 'suspended' state.
Solutions
- Ensure rec.start() is called inside a direct user-gesture handler (click/touchend) so the AudioContext resumes.
- Guard stop() calls: only invoke when recording state confirms start succeeded.
- If you defer start, prompt the user to interact (e.g. 'Tap to start recording') and call start() in that handler.
- Check mic permission was granted; a pending/denied permission can leave state unresolved.
- After resume() on the AudioContext, verify rec.state before stopping.
Example fix
// before
rec.open(function() { /* waiting... */ });
rec.stop(); // state==3 -> error
// after
rec.open(function() {
startBtn.onclick = function() {
rec.start();
};
});
stopBtn.onclick = function() {
if (rec.state === 1) rec.stop();
}; Defensive patterns
Strategy: validation
Validate before calling
function canStop(rec) {
return rec && typeof rec.state === 'number' && rec.state === 1;
}
if (!canStop(rec)) return; // don't call stop unless recording Type guard
function isRecording(rec) { return !!rec && rec.state === 1; } Try / catch
try { rec.stop(onDone); } catch (e) {
if (String(e).includes('未开始录音')) {
showToast('Please start recording first (tap to allow audio)');
}
} Prevention
- Always call start() inside a user-gesture handler.
- Check rec.state before calling stop().
- Never attempt to auto-start recording on page load without interaction.
- Handle permission prompts asynchronously and start after grant.
When it happens
Trigger: Calling Recorder.stop() when This.state is falsy (recorder never opened) or state==3; state 3 arises when rec.open() succeeded but rec.start() was deferred waiting for a user gesture and none occurred, leaving the browser AudioContext suspended.
Common situations: Calling stop() without a prior start(); attempting to auto-start recording on page load without a click/tap (Chrome/Safari autoplay policy); an async permission prompt consumed the gesture window; SPA navigated away before start was triggered.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/43625beefb79db82.
Report an issue: GitHub.
Appendix: source
Thrown at console/frontend/src/utils/record/recorder-core.js:1373
if (set.takeoffEncodeChunk) {
//接管了输出,此时blob长度为0
This.CLog(
'启用takeoffEncodeChunk后stop返回的blob长度为0不提供音频数据',
3
);
} else if (blob.size < Math.max(100, duration / 2)) {
//1秒小于0.5k?
err('生成的' + set.type + '无效');
return;
}
True &&
True(blob, duration, originBUffers || [], originSampleRate || 44100);
end();
};
if (!This.isMock) {
var isCtxWait = This.state == 3;
if (!This.state || isCtxWait) {
err(
'未开始录音' +
(isCtxWait ? ',开始录音前无用户交互导致AudioContext未运行' : '')
);
return;
}
This._stop(true);
}
var size = This.recSize;
if (!size) {
err('未采集到录音');
return;
}
if (!This.buffers[0]) {
err('音频buffers被释放');
return;
}
if (!This[set.type]) {
err('未加载' + set.type + '编码器');View on GitHub (pinned to 5e758547a8)