You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:22:57