{"record":{"id":"1f4b40eb92b6f329","repo":"iflytek/astron-agent","slug":"pcm-pcmsamplerate-testsamplerate-record","errorCode":null,"errorMessage":"不应该出现pcm采样率{pcmSampleRate}和需要的采样率{testSampleRate}不一致","messagePattern":"不应该出现pcm采样率(.+?)和需要的采样率(.+?)不一致","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"console/frontend/src/utils/record/record.js","lineNumber":100,"sourceCode":"\n        //清理已处理完的缓冲数据，释放内存以支持长时间录音，最后完成录音时不能调用stop，因为数据已经被清掉了\n        for (\n          var i = this.realTimeSendTryChunk\n            ? this.realTimeSendTryChunk.index\n            : 0;\n          i < chunk.index;\n          i++\n        ) {\n          buffers[i] = null;\n        }\n        this.realTimeSendTryChunk = chunk; //此时的chunk.data就是原始的音频16位pcm数据（小端LE），直接保存即为16位pcm文件、加个wav头即为wav文件、丢给mp3编码器转一下码即为mp3文件\n\n        pcm = chunk.data;\n        pcmSampleRate = chunk.sampleRate;\n\n        if (pcmSampleRate != testSampleRate)\n          //除非是onProcess给的bufferSampleRate低于testSampleRate\n          throw new Error(\n            '不应该出现pcm采样率' +\n              pcmSampleRate +\n              '和需要的采样率' +\n              testSampleRate +\n              '不一致'\n          );\n      }\n\n      //将pcm数据丢进缓冲，凑够一帧发送，缓冲内的数据可能有多帧，循环切分发送\n      if (pcm.length > 0) {\n        this.realTimeSendTryChunks.push({\n          pcm: pcm,\n          pcmSampleRate: pcmSampleRate,\n        });\n      }\n\n      //从缓冲中切出一帧数据\n      var chunkSize = SendFrameSize / (testBitRate / 8); //8位时需要的采样数和帧大小一致，16位时采样数为帧大小的一半","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/frontend/src/utils/record/record.js#L82-L118","documentation":"Identical sample-rate invariant check to the one in media.js, thrown from RealTimeSendTry in record.js. Recorder.SampleData must produce PCM at testSampleRate; when the output chunk's sampleRate differs the record wrapper treats it as a programming/config error and throws instead of emitting bad frames.","triggerScenarios":"bufferSampleRate supplied to RealTimeSendTry differs from testSampleRate (e.g. onProcess delivering native-rate buffers while testSampleRate is fixed at 16000), or recorder config changed between recording sessions leaving stale buffers.","commonSituations":"Hardcoded testSampleRate not matching the actual device capture rate; mixing chunks from two recorder instances; upgrading recorder-core so SampleData behavior/rate negotiation changed.","solutions":["Align testSampleRate with the bufferSampleRate reported by onProcess buffers","Discard stale realTimeSendTryChunk/buffer state when restarting or reconfiguring the recorder","Create a fresh Recorder instance per configuration rather than mutating sample-rate config at runtime","Log the actual buffer sampleRate from onProcess to confirm what the device produces"],"exampleFix":"// before\nif (pcmSampleRate != testSampleRate)\n  throw new Error('不应该出现pcm采样率' + pcmSampleRate + '和需要的采样率' + testSampleRate + '不一致');\n// after\nif (pcmSampleRate != testSampleRate) {\n  console.warn('sampleRate mismatch, dropping chunk', { pcmSampleRate, testSampleRate });\n  return;\n}","handlingStrategy":"validation","validationCode":"const rates = buffers.map((b) => b.sampleRate);\nif (rates.some((r) => r !== bufferSampleRate)) {\n  console.warn('mixed buffer sample rates', rates);\n  return;\n}","typeGuard":"function sameRate(chunk, target) { return chunk && chunk.sampleRate === target; }","tryCatchPattern":"try {\n  realTimeSendTry(buffers, bufferSampleRate, isClose);\n} catch (e) {\n  console.warn('sample-rate mismatch, frame skipped:', e.message);\n}","preventionTips":["Always pass the bufferSampleRate reported by onProcess","Clear stale chunk state when restarting recordings","Use one Recorder instance per configuration"],"tags":["audio","sample-rate-mismatch","internal-invariant","webm-recording"],"backgroundTag":"internal-invariant-violation","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}