首页 > web前端 > js教程 > 正文

js怎么实现屏幕录制

小老鼠
发布: 2025-08-20 08:48:02
原创
606人浏览过

屏幕录制可通过mediarecorder和getdisplaymedia api实现;2. 麦克风权限应先请求屏幕共享,再单独请求音频以避免多次弹窗;3. 优化文件大小可降低分辨率、帧率,选择vp9编码或限制时长;4. 添加水印可用canvas api绘制并捕获流,或录制后用ffmpeg.js处理;5. 错误处理需捕获用户拒绝、api不支持及录制中断等异常并给出提示。完整实现需结合安全策略与用户体验,最终方案在浏览器限制下可行但功能有限。

js怎么实现屏幕录制

屏幕录制在 JavaScript 中实现起来,直接使用原生 API 是比较困难的,因为浏览器出于安全考虑,限制了直接访问底层硬件设备的能力。不过,我们可以借助

MediaRecorder
登录后复制
API 和
getDisplayMedia
登录后复制
API 来实现一个简易的屏幕录制功能。核心思路是:先获取屏幕共享的 MediaStream,然后使用 MediaRecorder 将 MediaStream 中的数据录制下来,最后将录制的数据保存为文件。

js怎么实现屏幕录制

解决方案

以下是一个简单的 JavaScript 屏幕录制示例:

js怎么实现屏幕录制
async function startRecording() {
  try {
    const stream = await navigator.mediaDevices.getDisplayMedia({
      video: { mediaSource: "screen" },
      audio: true, // 可选,如果需要录制音频
    });

    const recorder = new MediaRecorder(stream);
    let data = [];

    recorder.ondataavailable = (event) => data.push(event.data);
    recorder.onstop = () => {
      const blob = new Blob(data, { type: "video/webm" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.style.display = "none";
      a.href = url;
      a.download = "screen-recording.webm";
      document.body.appendChild(a);
      a.click();
      window.URL.revokeObjectURL(url); // 释放 URL 对象
      stream.getTracks().forEach(track => track.stop()); // 停止所有轨道
    };

    recorder.start();
    return recorder;

  } catch (err) {
    console.error("Error accessing screen:", err);
    // 处理用户拒绝共享屏幕的情况
  }
}

async function stopRecording(recorder) {
  recorder.stop();
}

// 使用示例
let recorderInstance = null;

document.getElementById("startBtn").addEventListener("click", async () => {
  recorderInstance = await startRecording();
});

document.getElementById("stopBtn").addEventListener("click", () => {
  if (recorderInstance) {
    stopRecording(recorderInstance);
  }
});
登录后复制

这个代码片段首先定义了

startRecording
登录后复制
函数,它使用
navigator.mediaDevices.getDisplayMedia
登录后复制
获取屏幕共享的 MediaStream。然后,创建一个
MediaRecorder
登录后复制
对象,并设置
ondataavailable
登录后复制
onstop
登录后复制
事件处理程序。
ondataavailable
登录后复制
事件处理程序将录制的数据添加到
data
登录后复制
数组中,
onstop
登录后复制
事件处理程序将
data
登录后复制
数组中的数据合并为一个 Blob 对象,并创建一个下载链接,以便用户可以下载录制的文件。

stopRecording
登录后复制
函数简单地调用
recorder.stop()
登录后复制
来停止录制。

js怎么实现屏幕录制

最后,代码片段添加了两个按钮的事件监听器,分别用于启动和停止录制。

屏幕录制时如何处理麦克风权限请求?

当同时需要录制屏幕和麦克风音频时,需要在

getDisplayMedia
登录后复制
中同时请求视频和音频权限。但是,用户可能会先授权屏幕共享,然后才授权麦克风。在这种情况下,浏览器可能会弹出多个权限请求窗口,这可能会让用户感到困惑。

一种更好的做法是,先请求屏幕共享权限,然后在屏幕共享启动后,再请求麦克风权限。这样可以避免弹出多个权限请求窗口。

async function startRecordingWithAudio() {
    try {
        const stream = await navigator.mediaDevices.getDisplayMedia({
            video: { mediaSource: "screen" },
            audio: false // 先不请求音频
        });

        // 检查是否需要同时录制麦克风
        const shouldRecordAudio = confirm("是否同时录制麦克风?");

        let audioStream = null;
        if (shouldRecordAudio) {
            try {
                audioStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
                // 将麦克风音轨添加到屏幕共享流中
                audioStream.getTracks().forEach(track => stream.addTrack(track));
            } catch (audioErr) {
                console.error("Error accessing microphone:", audioErr);
                alert("无法访问麦克风,将只录制屏幕。");
                // 如果用户拒绝麦克风权限,可以继续只录制屏幕
            }
        }

        const recorder = new MediaRecorder(stream);
        let data = [];

        recorder.ondataavailable = (event) => data.push(event.data);
        recorder.onstop = () => {
            const blob = new Blob(data, { type: "video/webm" });
            const url = URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.style.display = "none";
            a.href = url;
            a.download = "screen-recording.webm";
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
            stream.getTracks().forEach(track => track.stop());
            if(audioStream){
              audioStream.getTracks().forEach(track => track.stop());
            }
        };

        recorder.start();
        return recorder;

    } catch (err) {
        console.error("Error accessing screen:", err);
    }
}
登录后复制

如何优化屏幕录制的文件大小?

录制的文件大小通常取决于多个因素,包括分辨率、帧率、编码格式和录制时长。

快转字幕
快转字幕

新一代 AI 字幕工作站,为创作者提供字幕制作、学习资源、会议记录、字幕制作等场景,一键为您的视频生成精准的字幕。

快转字幕 357
查看详情 快转字幕
  • 降低分辨率: 降低录制的分辨率可以显著减小文件大小。可以在
    getDisplayMedia
    登录后复制
    video
    登录后复制
    选项中设置
    width
    登录后复制
    height
    登录后复制
    属性来降低分辨率。
  • 降低帧率: 降低帧率也可以减小文件大小,但可能会导致录制的视频看起来不流畅。可以在创建
    MediaRecorder
    登录后复制
    对象时,通过设置
    mimeType
    登录后复制
    选项来指定帧率。例如:
    new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp9', videoBitsPerSecond : 1000000 })
    登录后复制
    ,可以尝试调整
    videoBitsPerSecond
    登录后复制
    的值。
  • 选择合适的编码格式: 不同的编码格式具有不同的压缩率。VP9 是一种高效的视频编码格式,可以提供比 VP8 或 H.264 更好的压缩率。
  • 限制录制时长: 避免录制不必要的长时间视频。

屏幕录制过程中如何添加水印?

直接在 JavaScript 中实现复杂的水印功能比较困难,因为

MediaRecorder
登录后复制
API 本身并不提供直接添加水印的接口。不过,可以通过一些间接的方法来实现水印效果。

一种方法是使用 Canvas API 将水印绘制到屏幕共享的 MediaStream 中。首先,创建一个 Canvas 元素,并将水印绘制到 Canvas 上。然后,使用

captureStream
登录后复制
方法从 Canvas 中获取 MediaStream,并将该 MediaStream 作为
MediaRecorder
登录后复制
的输入。

这种方法的缺点是,水印是静态的,不能动态改变。此外,由于水印是直接绘制到屏幕上的,因此可能会影响屏幕的显示效果。

另一种方法是在录制完成后,使用视频编辑库(例如 FFmpeg.js)将水印添加到录制的文件中。这种方法的优点是,水印可以动态改变,并且不会影响屏幕的显示效果。但是,这种方法需要在客户端运行视频编辑库,这可能会增加客户端的负担。

以下是使用 Canvas API 添加水印的示例代码:

async function startRecordingWithWatermark() {
    try {
        const stream = await navigator.mediaDevices.getDisplayMedia({
            video: { mediaSource: "screen" },
            audio: true
        });

        // 创建 Canvas 元素
        const canvas = document.createElement('canvas');
        canvas.width = stream.getVideoTracks()[0].getSettings().width;
        canvas.height = stream.getVideoTracks()[0].getSettings().height;
        const ctx = canvas.getContext('2d');

        // 获取屏幕共享的视频轨道
        const videoTrack = stream.getVideoTracks()[0];

        // 创建一个 Video 元素,用于绘制屏幕共享的内容到 Canvas 上
        const video = document.createElement('video');
        video.srcObject = stream;
        video.muted = true; // 必须设置 muted 为 true,否则会报错
        await video.play(); // 必须 play,否则无法绘制

        // 定时绘制 Canvas
        function drawCanvas() {
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

            // 添加水印
            ctx.font = '30px Arial';
            ctx.fillStyle = 'red';
            ctx.fillText('Watermark', 50, 50);

            requestAnimationFrame(drawCanvas);
        }

        drawCanvas();

        // 从 Canvas 中获取 MediaStream
        const canvasStream = canvas.captureStream();

        // 将屏幕共享的音频轨道添加到 Canvas Stream 中
        const audioTracks = stream.getAudioTracks();
        audioTracks.forEach(track => canvasStream.addTrack(track));

        const recorder = new MediaRecorder(canvasStream);
        let data = [];

        recorder.ondataavailable = (event) => data.push(event.data);
        recorder.onstop = () => {
            const blob = new Blob(data, { type: "video/webm" });
            const url = URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.style.display = "none";
            a.href = url;
            a.download = "screen-recording.webm";
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
            stream.getTracks().forEach(track => track.stop());
            canvasStream.getTracks().forEach(track => track.stop()); // 停止 canvasStream 的所有轨道
        };

        recorder.start();
        return recorder;

    } catch (err) {
        console.error("Error accessing screen:", err);
    }
}
登录后复制

这个示例代码首先创建了一个 Canvas 元素,并将屏幕共享的内容绘制到 Canvas 上。然后,在 Canvas 上添加水印。最后,从 Canvas 中获取 MediaStream,并将其作为

MediaRecorder
登录后复制
的输入。

需要注意的是,使用 Canvas API 添加水印可能会影响性能,特别是当水印比较复杂时。

如何处理屏幕录制过程中的错误?

在屏幕录制过程中,可能会发生各种错误,例如用户拒绝共享屏幕、浏览器不支持

getDisplayMedia
登录后复制
API、录制过程中断等等。为了提高应用程序的健壮性,需要对这些错误进行处理。

  • 处理用户拒绝共享屏幕的错误: 当用户拒绝共享屏幕时,
    getDisplayMedia
    登录后复制
    API 会抛出一个
    DOMException
    登录后复制
    异常。可以在
    try...catch
    登录后复制
    块中捕获该异常,并向用户显示一条友好的错误消息。
  • 处理浏览器不支持
    getDisplayMedia
    登录后复制
    API 的错误:
    某些旧版本的浏览器可能不支持
    getDisplayMedia
    登录后复制
    API。可以在代码中检查
    navigator.mediaDevices.getDisplayMedia
    登录后复制
    是否存在,如果不存在,则向用户显示一条错误消息。
  • 处理录制过程中断的错误: 录制过程中可能会因为各种原因而中断,例如网络连接中断、浏览器崩溃等等。可以在
    MediaRecorder
    登录后复制
    对象的
    onerror
    登录后复制
    事件处理程序中处理这些错误。
async function startRecordingWithErrorHandling() {
    try {
        const stream = await navigator.mediaDevices.getDisplayMedia({
            video: { mediaSource: "screen" },
            audio: true
        });

        const recorder = new MediaRecorder(stream);
        let data = [];

        recorder.ondataavailable = (event) => data.push(event.data);
        recorder.onstop = () => {
            const blob = new Blob(data, { type: "video/webm" });
            const url = URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.style.display = "none";
            a.href = url;
            a.download = "screen-recording.webm";
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
            stream.getTracks().forEach(track => track.stop());
        };

        recorder.onerror = (event) => {
            console.error("MediaRecorder error:", event.error);
            alert("录制过程中发生错误:" + event.error.name);
            // 可以根据 event.error.name 进行更详细的错误处理
        };

        recorder.start();
        return recorder;

    } catch (err) {
        console.error("Error accessing screen:", err);
        if (err.name === 'NotAllowedError') {
            alert("用户拒绝了屏幕共享请求。");
        } else if (err.name === 'NotFoundError') {
            alert("找不到可用的屏幕共享源。");
        } else {
            alert("发生未知错误:" + err.message);
        }
    }
}
登录后复制

总的来说,JavaScript 实现屏幕录制功能依赖于浏览器提供的 API,并且受到安全限制。虽然可以实现基本功能,但在高级功能(例如水印、实时编辑)方面存在一定的局限性。

以上就是js怎么实现屏幕录制的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门推荐
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号