0

0

js怎么实现屏幕录制

小老鼠

小老鼠

发布时间:2025-08-20 08:48:02

|

618人浏览过

|

来源于php中文网

原创

屏幕录制可通过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自动作曲工具,集 AI 辅助作词、AI 自动作曲、编曲、混音于一体

下载
  • 降低分辨率: 降低录制的分辨率可以显著减小文件大小。可以在
    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,并且受到安全限制。虽然可以实现基本功能,但在高级功能(例如水印、实时编辑)方面存在一定的局限性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1076

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

169

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1334

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.19

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

510

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5305

2023.08.17

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

9

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 4.9万人学习

麻省理工大佬Python课程
麻省理工大佬Python课程

共34课时 | 5.2万人学习

【李炎恢】ThinkPHP8.x 后端框架课程
【李炎恢】ThinkPHP8.x 后端框架课程

共50课时 | 4.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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