使用MediaRecorder录制WebGL2 Canvas时ondataavailable未触发问题
针对你遇到的ondataavailable仅在停止录制时触发且缓冲区为空、最终生成0大小WebM文件的问题,结合你的场景(代码在其他Canvas游戏正常运行),可以从以下几个方向排查:
1. 优先排查Canvas跨域污染问题
如果当前Canvas绘制了跨域资源(比如来自其他域名的图片、视频),即使captureStream()生成的流能在video元素播放,MediaRecorder也可能因为Canvas被污染而无法正确编码数据,导致录制出空文件。
检查方法:
在获取stream前执行以下代码,若抛出SecurityError则说明Canvas被污染:
try { canvas.toDataURL(); console.log('Canvas未被污染'); } catch (e) { console.error('Canvas跨域污染:', e); }
解决方法:
- 确保所有绘制到Canvas的资源(图片、视频)都配置了正确的CORS响应头;
- 加载图片时添加
crossOrigin="anonymous"属性:const img = new Image(); img.crossOrigin = 'anonymous'; img.src = 'https://example.com/image.png';
2. 验证MIME类型兼容性
硬指定video/webm可能存在编码格式不兼容的问题,不同浏览器对WebM的编码支持(VP8/VP9)有差异,导致MediaRecorder无法生成有效数据。
优化代码:
先检测浏览器支持的MIME类型,选择兼容的格式:
function getSupportedMimeType() { const candidateTypes = [ 'video/webm;codecs=vp9', 'video/webm;codecs=vp8', 'video/webm' ]; return candidateTypes.find(type => MediaRecorder.isTypeSupported(type)); } // 在startRecording中替换原options function startRecording() { const supportedMimeType = getSupportedMimeType(); if (!supportedMimeType) { console.error('当前浏览器不支持WebM录制'); return; } let options = {mimeType: supportedMimeType}; recordedBlobs = []; mediaRecorder = new MediaRecorder(stream, options); // 后续代码保持不变... }
3. 处理录制流程的异步问题
mediaRecorder.stop()是异步操作,ondataavailable和onstop事件会在停止后延迟触发。如果直接在stopRecording()后调用download(),此时recordedBlobs可能还未被填充。
优化流程:
将下载逻辑绑定到onstop事件,或者用Promise封装录制流程:
// 修改handleStop函数,加入下载逻辑 function handleStop(event) { console.log('Recorder stopped: ', event); download(); // 录制停止后自动下载 } // 或者用Promise封装,确保异步顺序 async function runRecording() { startRecording(); await new Promise(resolve => setTimeout(resolve, 5000)); // 录制5秒 mediaRecorder.stop(); await new Promise(resolve => mediaRecorder.onstop = resolve); download(); }
4. 确保Canvas有持续帧更新
如果录制期间Canvas没有新的帧绘制(比如游戏暂停、动画停止),MediaRecorder可能因为没有新数据而无法生成Blob片段。可以检查:
- 游戏的
requestAnimationFrame循环是否在录制期间正常运行; - 尝试在录制期间手动触发Canvas重绘(比如调用
canvas.getContext('2d').fillRect(0,0,1,1))。
5. 浏览器版本兼容性测试
部分旧版本浏览器的MediaRecorder存在Canvas流录制的bug,尝试更新浏览器到最新稳定版,或换用Chrome/Firefox等主流浏览器测试。
内容的提问来源于stack exchange,提问作者user1617735

