优秀的编程知识分享平台

网站首页 > 技术文章 正文

前端录屏黑科技:几行 JS 代码就能实现!

nanyue 2025-08-03 06:53:59 技术文章 2 ℃

在过去,想要在网页上实现“录屏”功能,往往需要借助复杂的浏览器插件、桌面应用或者付费的第三方服务。这不仅增加了用户的操作成本,也给开发者带来了不小的挑战。但如今,随着 Web API 的不断发展,一个强大的原生工具已经悄然来到了我们身边——MediaRecorder API

什么是 MediaRecorder API?

MediaRecorder 是 WebRTC(Web Real-Time Communication)技术栈的一部分。简单来说,它是一个可以接收媒体流(MediaStream),并将其编码成特定格式(如 WebM 或 MP4),然后以数据块(Blobs)的形式输出的接口。

这里的媒体流来源非常广泛,可以是:

  • 用户的摄像头和麦克风 (navigator.mediaDevices.getUserMedia)
  • 用户的屏幕、窗口或浏览器标签页 (navigator.mediaDevices.getDisplayMedia)
  • 网页中的 <video><audio> 元素
  • 甚至是一个动态生成的 Canvas 画布

而我们要实现的“录屏”功能,正是利用了第二种来源——getDisplayMedia API。

实现一个基础的录屏功能:三步走

实现一个基础的录屏功能,核心逻辑可以分为三步:获取流 -> 录制流 -> 处理结果

第一步:获取屏幕共享的媒体流

首先,我们需要向用户申请权限,以获取他们屏幕内容的媒体流。getDisplayMedia API 会弹出一个浏览器原生的对话框,让用户选择要共享的屏幕、窗口或标签页。

// 1. 获取屏幕共享流的函数
async function getScreenStream() {
    try {
        // 提示用户选择要共享的屏幕或窗口
        const stream = await navigator.mediaDevices.getDisplayMedia({
            video: true, // 必须,表示我们要捕获视频
            audio: true // 可选,表示我们想同时捕获该屏幕播放的音频
        });
        return stream;
    } catch (error) {
        console.error("获取屏幕共享失败:", error);
        alert("您取消了屏幕共享或发生了错误。");
        return null;
    }
}

注意getDisplayMedia 必须由用户交互(如点击按钮)触发,否则浏览器会出于安全考虑而阻止它。

第二步:创建 MediaRecorder 实例并开始录制

获取到 MediaStream 对象后,我们就可以用它来创建一个 MediaRecorder 实例。

let mediaRecorder;
let recordedChunks = []; // 用于存储录制的数据块

// 2. 开始录制的函数
function startRecording(stream) {
    if (!stream) return;

    // 配置录制选项,例如 MIME 类型
    const options = { mimeType: 'video/webm; codecs=vp9' };
    try {
        mediaRecorder = new MediaRecorder(stream, options);
    } catch (e) {
        console.error("创建 MediaRecorder 失败:", e);
        return;
    }

    // 当有数据块可用时触发
    mediaRecorder.ondataavailable = (event) => {
        if (event.data.size > 0) {
            recordedChunks.push(event.data);
        }
    };

    // 当录制停止时触发
    mediaRecorder.onstop = () => {
        console.log("录制已停止。");
        // 在这里处理最终的录制文件
        handleRecordingStop();
    };

    // 开始录制
    mediaRecorder.start();
    console.log("录制已开始!");

    // 当用户手动停止屏幕共享时,也停止录制
    stream.getVideoTracks()[0].onended = () => {
        stopRecording();
    };
}

第三步:停止录制并处理结果

当用户点击停止按钮或关闭屏幕共享时,我们调用 mediaRecorder.stop()。录制的数据块会汇集在 recordedChunks 数组中,我们只需将它们整合成一个 Blob 对象,就可以生成最终的视频文件。

// 3. 停止录制的函数
function stopRecording() {
    if (mediaRecorder && mediaRecorder.state !== 'inactive') {
        mediaRecorder.stop();
    }
}

// 4. 处理录制结果
function handleRecordingStop() {
    // 将所有数据块合并成一个 Blob
    const recordedBlob = new Blob(recordedChunks, { type: 'video/webm' });

    // 创建一个 URL,用于预览或下载
    const videoUrl = URL.createObjectURL(recordedBlob);

    // 例如,创建一个下载链接
    const downloadLink = document.createElement('a');
    downloadLink.href = videoUrl;
    downloadLink.download = `recording-${new Date().toISOString()}.webm`;
    downloadLink.textContent = '下载录屏';
    document.body.appendChild(downloadLink);
    
    // 或者创建一个 video 元素进行预览
    const previewVideo = document.createElement('video');
    previewVideo.src = videoUrl;
    previewVideo.controls = true;
    document.body.appendChild(previewVideo);

    // 清空数据块,为下一次录制做准备
    recordedChunks = [];
}

将这三步与 UI 按钮(开始、停止)结合起来,一个完整的网页录屏应用就诞生了!

MediaRecorder 的应用场景远不止于此,比如可以用它来实现:用户反馈与 Bug 复现、在线教育与演示等。

注意事项与最佳实践

  1. 浏览器兼容性MediaRecorder API 在现代浏览器(Chrome, Firefox, Edge, Safari)中得到了广泛支持,但仍需检查兼容性,并为不支持的浏览器提供优雅降级。
  2. MIME 类型:不同的浏览器支持不同的 mimeType。可以使用 MediaRecorder.isTypeSupported() 方法来检查支持情况,并选择最合适的格式。video/webm 是最广泛支持的。
  3. 用户授权:始终在用户明确操作后才调用 getDisplayMedia,并清晰地告知用户为何需要此权限。
  4. 资源管理:录制完成后,记得使用 URL.revokeObjectURL() 释放由 createObjectURL 创建的 URL,避免内存泄漏。同时,确保停止媒体流(stream.getTracks().forEach(track => track.stop())),关闭摄像头或屏幕共享的指示灯。
  5. 性能考量:长时间或高分辨率的录制会消耗大量内存和 CPU。对于需要上传的场景,可以考虑分片上传,而不是等待整个文件录制完毕。
最近发表
标签列表