Three.js WebXR场景下canvas captureStream()生成空白视频问题求助
解决Three.js WebXR模式下canvas.captureStream()捕获流空白的问题
当Three.js开启WebXR模式后,直接捕获原canvas的流会显示空白,核心原因是WebXR激活时,渲染输出不再指向DOM里的canvas元素——Three.js会切换到WebXR提供的离屏帧缓冲区(FBO)进行渲染,原canvas只是作为非XR模式的占位符,此时它不会被实时更新,自然捕获不到画面。
下面是可行的解决办法:
实现思路
创建一个隐藏的辅助canvas,在每一帧将WebXR的渲染内容从离屏FBO复制到这个辅助canvas,然后从辅助canvas捕获流,这样video就能拿到实时的XR画面了。
修改后的代码示例
let helperCanvas = null; let helperCtx = null; function captureVideo() { const overlay = document.getElementById('overlay'); // 初始化辅助canvas if (!helperCanvas) { helperCanvas = document.createElement('canvas'); helperCanvas.style.display = 'none'; document.body.appendChild(helperCanvas); helperCtx = helperCanvas.getContext('webgl', {preserveDrawingBuffer: true}); } // 设置辅助canvas尺寸匹配XR渲染目标 const xrFbo = renderer.xr.getFbo(); helperCanvas.width = xrFbo.width; helperCanvas.height = xrFbo.height; // 捕获辅助canvas的流 const stream = helperCanvas.captureStream(); const video = document.createElement('video'); video.controls = true; video.muted = true; video.height = 200; video.width = 200; video.style.border = '1px solid red'; overlay.append(video); video.srcObject = stream; video.play(); // 持续复制XR渲染内容到辅助canvas function copyXRFrame() { if (renderer.xr.isPresenting) { const xrFbo = renderer.xr.getFbo(); // 将离屏FBO的内容复制到辅助canvas helperCtx.bindFramebuffer(helperCtx.FRAMEBUFFER, xrFbo); helperCtx.drawImage(helperCanvas, 0, 0); helperCtx.bindFramebuffer(helperCtx.FRAMEBUFFER, null); } requestAnimationFrame(copyXRFrame); } copyXRFrame(); }
关键细节说明
renderer.xr.getFbo():获取WebXR当前使用的离屏帧缓冲区,这才是实际渲染XR画面的地方。preserveDrawingBuffer: true:保证辅助canvas的内容不会在每帧后被清除,确保捕获流时能拿到完整画面。- 用
requestAnimationFrame持续复制:因为XR画面是实时更新的,需要每帧都把FBO内容同步到辅助canvas,才能让video流保持实时。
内容的提问来源于stack exchange,提问作者MR_AMDEV
相关产品推荐
相关产品推荐

