如何在Three.js的WebXR AR模式中捕获照片/视频?
Three.js AR模式下捕获摄像头+3D对象画面的解决方案
为什么getUserMedia会黑屏?
AR模式中WebXR会独占设备的摄像头流,此时再次调用getUserMedia无法获取到有效画面,因此会出现黑屏问题。
解决方案
方案1:直接捕获Three.js的渲染画布
Three.js在AR模式下已经自动将摄像头画面与3D对象合成渲染到WebGL画布上,直接捕获这个画布就能得到完整的AR画面,是最简便的方案。
捕获照片
// 触发拍照并下载 function captureARPhoto() { const canvas = renderer.domElement; // 将画布内容转为PNG格式的DataURL const photoData = canvas.toDataURL('image/png'); // 创建下载链接 const downloadLink = document.createElement('a'); downloadLink.download = 'ar-capture.png'; downloadLink.href = photoData; downloadLink.click(); }
录制视频
利用canvas.captureStream()将画布转为媒体流,再通过MediaRecorder实现录制:
let mediaRecorder; let recordedChunks = []; // 开始录制 function startARRecording() { const canvas = renderer.domElement; // 以30fps捕获画布流 const stream = canvas.captureStream(30); mediaRecorder = new MediaRecorder(stream); // 收集录制数据 mediaRecorder.ondataavailable = (e) => { e.data.size > 0 && recordedChunks.push(e.data); }; // 录制结束后生成视频并下载 mediaRecorder.onstop = () => { const videoBlob = new Blob(recordedChunks, { type: 'video/webm' }); const videoUrl = URL.createObjectURL(videoBlob); const downloadLink = document.createElement('a'); downloadLink.download = 'ar-recording.webm'; downloadLink.href = videoUrl; downloadLink.click(); recordedChunks = []; URL.revokeObjectURL(videoUrl); }; mediaRecorder.start(); } // 停止录制 function stopARRecording() { mediaRecorder?.stop(); }
方案2:单独获取摄像头纹理(用于自定义合成)
如果需要对摄像头画面和3D对象进行单独处理,可以通过WebXR帧数据获取摄像头纹理,再手动合成画面:
renderer.setAnimationLoop((timestamp, frame) => { if (!frame) return; // 获取WebXR基础层的摄像头纹理 const baseLayer = frame.session.renderState.baseLayer; const cameraTexture = baseLayer.texture; // 将纹理贴到全屏平面作为背景,再叠加3D对象 const cameraPlane = new THREE.Mesh( new THREE.PlaneGeometry(2, 2), new THREE.MeshBasicMaterial({ map: cameraTexture }) ); cameraPlane.position.z = -1; scene.add(cameraPlane); renderer.render(scene, camera); });
注意事项
- 确保页面运行在HTTPS环境下(localhost开发环境不受限制),否则
captureStream和MediaRecorder可能无法正常工作。 - 不同浏览器对MediaRecorder支持的视频格式不同,WebM是兼容性较好的选择,如需MP4可能需要额外转码处理。
- 部分移动设备需要用户手动授权摄像头和录制权限。
内容的提问来源于stack exchange,提问作者Dhruvil Mehta
相关产品推荐
相关产品推荐

