如何在JavaScript的getDisplayMedia屏幕录制中隐藏鼠标光标?
解决getDisplayMedia录制时隐藏视频中光标的问题
针对cursor: "never"约束不生效、本地隐藏光标不符合需求的问题,以下是几个可行的变通方案:
方案1:通过Canvas合成媒体流(最可靠)
核心思路是将捕获的屏幕流先渲染到Canvas,绘制时自动忽略系统光标,再从Canvas生成新的媒体流用于录制。这样最终录制的视频里不会出现光标,同时本地光标正常可见。
代码示例:
async function startScreenRecording() { try { const displayMediaOptions = { video: true, audio: true }; const displayStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); // 创建用于渲染的video元素 const videoEl = document.createElement('video'); videoEl.srcObject = displayStream; videoEl.play().catch(err => console.error('播放视频失败:', err)); // 创建Canvas并设置尺寸 const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // 监听视频尺寸变化,同步Canvas尺寸 videoEl.addEventListener('loadedmetadata', () => { canvas.width = videoEl.videoWidth; canvas.height = videoEl.videoHeight; }); // 实时将视频帧绘制到Canvas(自动忽略光标) function drawFrame() { if (!videoEl.paused && !videoEl.ended) { ctx.drawImage(videoEl, 0, 0, canvas.width, canvas.height); requestAnimationFrame(drawFrame); } } drawFrame(); // 从Canvas获取新的媒体流(用于录制) const canvasStream = canvas.captureStream(); // 将原音频轨道添加到新流中(如果需要录制音频) displayStream.getAudioTracks().forEach(track => { canvasStream.addTrack(track); }); // 处理合成后的流(替换原来的handleMediaStream) handleMediaStream(canvasStream); // 记得在录制结束时清理资源 // displayStream.getTracks().forEach(track => track.stop()); // videoEl.remove(); // canvas.remove(); } catch (error) { console.error("捕获媒体失败:", error); } } function handleMediaStream(stream) { // 这里处理录制逻辑,比如用MediaRecorder } document.addEventListener("DOMContentLoaded", () => { startScreenRecording(); });
方案2:尝试动态应用Track约束
虽然getSupportedConstraints()显示不支持cursor,但部分浏览器可能仍支持通过applyConstraints设置该属性,可以尝试在获取流后单独对视频轨道设置:
async function startScreenRecording() { try { const displayMediaOptions = { video: true, audio: true }; const displayStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); // 获取视频轨道并尝试应用cursor约束 const videoTrack = displayStream.getVideoTracks()[0]; try { await videoTrack.applyConstraints({ cursor: "never" }); console.log("成功应用cursor约束"); } catch (constraintErr) { console.warn("无法应用cursor约束:", constraintErr); // 这里可以回退到方案1 } handleMediaStream(displayStream); } catch (error) { console.error("捕获媒体失败:", error); } }
方案3:临时隐藏本地光标(备选)
如果上述方案都不可行,可在录制期间临时隐藏本地光标,录制结束后恢复。虽然本地看不到光标,但能保证录制视频无光标:
let originalCursor = ''; async function startScreenRecording() { try { // 保存原始光标样式 originalCursor = document.body.style.cursor; // 隐藏本地光标 document.body.style.cursor = 'none'; const displayMediaOptions = { video: true, audio: true }; const displayStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); // 监听流结束事件,恢复光标 displayStream.getTracks().forEach(track => { track.addEventListener('ended', () => { document.body.style.cursor = originalCursor; }); }); handleMediaStream(displayStream); } catch (error) { console.error("捕获媒体失败:", error); // 出错时也恢复光标 document.body.style.cursor = originalCursor; } }
内容的提问来源于stack exchange,提问作者Sounav Saha
相关产品推荐
相关产品推荐

