ondataavailable 回调中 event.data 是 Blob 类型,非 ArrayBuffer 或 Uint8Array;需调用 arrayBuffer() 或 text() 读取,拼接时应统一转 ArrayBuffer 后合并为新 Blob。

ondataavailable 回调里拿到的 event.data 是什么类型?
它是一个 Blob,不是 ArrayBuffer 或 Uint8Array。很多开发者误以为能直接用 new Uint8Array(event.data) 解析,结果报错:TypeError: Failed to construct 'Uint8Array': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'。必须先调用 Blob.arrayBuffer() 或 Blob.text()(仅限文本型 blob)来读取内容。
如何安全拼接多个 ondataavailable 数据块?
MediaRecorder 分片输出,每次回调的 event.data 是独立 Blob,不能直接 push 到数组然后 new Blob(chunks) —— 这样会嵌套一层 blob 结构,导致最终文件损坏(比如 Chrome 下录出的 WebM 无法播放)。正确做法是统一转成 ArrayBuffer 后合并:
const chunks = [];
recorder.ondataavailable = async (event) => {
if (event.data.size > 0) {
const buf = await event.data.arrayBuffer();
chunks.push(buf);
}
};
// 录制结束时合并
const fullBuf = new Uint8Array(chunks.reduce((acc, cur) => acc + cur.byteLength, 0));
let offset = 0;
chunks.forEach(buf => {
fullBuf.set(new Uint8Array(buf), offset);
offset += buf.byteLength;
});
const finalBlob = new Blob([fullBuf], { type: recorder.mimeType });
为什么有时 ondataavailable 只触发一次,且 event.data.size === 0?
常见于以下情况:
-
MediaRecorder.start()调用前未确保mediaStream已就绪(例如getUserMedia的 promise 还没 resolve) - 录制目标是静音流或无音频轨道的视频流,某些浏览器(如 Safari)可能不触发非空数据回调
- 未设置
timeslice参数,且在stop()前没手动调用requestData(),导致只在结束时吐出一个 blob(可能为空)
建议显式设置 timeslice(如 recorder.start(1000)),并监听 onstart 确保状态正常。
立即学习“前端免费学习笔记(深入)”;
MediaRecorder.mimeType 和实际 blob 类型不一致怎么办?
浏览器不一定按你传给 MediaRecorder 构造函数的 mimeType 输出数据。例如传 "video/webm;codecs=vp9",但设备不支持 VP9,Chrome 可能降级为 vp8 并仍返回 video/webm 类型 blob —— 此时 event.data.type 才是真实值。务必用 event.data.type 而非构造时的配置来生成最终 Blob:
recorder.ondataavailable = (event) => {
if (event.data.size > 0) {
// ✅ 正确:用 event.data.type
chunks.push({ data: event.data, type: event.data.type });
}
};
// 合并时:
const finalBlob = new Blob(chunks.map(c => c.data), { type: chunks[0]?.type || 'video/webm' });
跨浏览器兼容性差的地方往往藏在这里:Safari 返回 audio/mp4,Chrome 可能是 audio/webm,别硬编码类型。



















