编程 前端录屏黑科技:几行 JS 代码实现网页录屏

2025-08-15 15:19:33 +0800 CST views 15

前端录屏黑科技:几行 JS 代码实现网页录屏

在过去,实现网页录屏通常需要依赖复杂的浏览器插件、桌面应用或付费服务。这不仅增加了用户操作成本,也给开发者带来不小的开发压力。如今,借助现代 Web API,我们可以用原生 JavaScript 简单实现屏幕录制功能。

核心工具:MediaRecorder API


MediaRecorder API 简介

MediaRecorder 是 WebRTC 技术栈的一部分,它可以接收 MediaStream(音视频流),并将其编码成特定格式(如 WebM 或 MP4),输出为数据块(Blobs)。

媒体流来源广泛

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

本篇聚焦于 屏幕录制,通过 getDisplayMedia 获取屏幕流。


基础录屏三步走

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 必须由用户交互(如点击按钮)触发,否则浏览器会阻止调用。


2. 创建 MediaRecorder 实例并开始录制

let recordedChunks = [];
let mediaRecorder;

function startRecording(stream) {
    mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' });

    mediaRecorder.ondataavailable = (event) => {
        if (event.data.size > 0) {
            recordedChunks.push(event.data);
        }
    };

    mediaRecorder.onstop = handleRecordingStop;

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

3. 停止录制并处理结果

function stopRecording() {
    if (mediaRecorder && mediaRecorder.state !== 'inactive') {
        mediaRecorder.stop();
    }
}

function handleRecordingStop() {
    const recordedBlob = new Blob(recordedChunks, { type: 'video/webm' });
    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);

    // 视频预览
    const previewVideo = document.createElement('video');
    previewVideo.src = videoUrl;
    previewVideo.controls = true;
    document.body.appendChild(previewVideo);

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

通过按钮触发 startRecordingstopRecording,即可实现一个完整的网页录屏功能。


MediaRecorder 的应用场景

  • 用户反馈与 Bug 复现
  • 在线教育与演示
  • 屏幕录像或演示教程录制

注意事项与最佳实践

  1. 浏览器兼容性

    • 支持 Chrome、Firefox、Edge、Safari 等现代浏览器
    • 需检查兼容性,为不支持的浏览器提供降级方案
  2. MIME 类型

    • 不同浏览器支持不同格式
    • 使用 MediaRecorder.isTypeSupported() 检查支持
    • video/webm 支持最广
  3. 用户授权

    • 必须在用户明确操作后调用 getDisplayMedia
    • 清晰告知权限用途
  4. 资源管理

    • 录制完成后使用 URL.revokeObjectURL(videoUrl) 释放内存
    • 停止媒体流:stream.getTracks().forEach(track => track.stop())
  5. 性能考量

    • 长时间或高分辨率录制消耗大量内存和 CPU
    • 上传场景可考虑分片上传,而不是一次完成

MediaRecorder API 的出现,让网页录屏变得前所未有的简单:几行 JavaScript 就能搞定完整功能,无需插件或第三方服务。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网页录屏示例</title>
<style>
  body { font-family: "Microsoft YaHei", sans-serif; padding: 20px; background: #f0f2f5; }
  button { padding: 10px 20px; margin: 5px; font-size: 16px; cursor: pointer; }
  video { display: block; margin-top: 20px; max-width: 100%; border: 1px solid #ccc; }
  a { display: block; margin-top: 10px; font-size: 16px; color: #007bff; text-decoration: none; }
</style>
</head>
<body>

<h2>网页录屏示例</h2>
<button id="startBtn">开始录屏</button>
<button id="stopBtn" disabled>停止录屏</button>

<div id="previewContainer"></div>
<div id="downloadContainer"></div>

<script>
let mediaRecorder;
let recordedChunks = [];
let screenStream;

const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const previewContainer = document.getElementById('previewContainer');
const downloadContainer = document.getElementById('downloadContainer');

async function startRecording() {
    try {
        screenStream = await navigator.mediaDevices.getDisplayMedia({
            video: true,
            audio: true
        });

        mediaRecorder = new MediaRecorder(screenStream, { mimeType: 'video/webm' });

        mediaRecorder.ondataavailable = (event) => {
            if (event.data.size > 0) recordedChunks.push(event.data);
        };

        mediaRecorder.onstop = handleRecordingStop;

        mediaRecorder.start();
        console.log('录制已开始');

        startBtn.disabled = true;
        stopBtn.disabled = false;
    } catch (err) {
        console.error('获取屏幕失败:', err);
        alert('获取屏幕失败或用户取消了操作。');
    }
}

function stopRecording() {
    if (mediaRecorder && mediaRecorder.state !== 'inactive') {
        mediaRecorder.stop();
        screenStream.getTracks().forEach(track => track.stop());
        startBtn.disabled = false;
        stopBtn.disabled = true;
    }
}

function handleRecordingStop() {
    const recordedBlob = new Blob(recordedChunks, { type: 'video/webm' });
    const videoUrl = URL.createObjectURL(recordedBlob);

    // 清空之前内容
    previewContainer.innerHTML = '';
    downloadContainer.innerHTML = '';

    // 创建视频预览
    const videoEl = document.createElement('video');
    videoEl.src = videoUrl;
    videoEl.controls = true;
    previewContainer.appendChild(videoEl);

    // 创建下载链接
    const downloadLink = document.createElement('a');
    downloadLink.href = videoUrl;
    downloadLink.download = `recording-${new Date().toISOString()}.webm`;
    downloadLink.textContent = '下载录屏';
    downloadContainer.appendChild(downloadLink);

    // 清空数据块
    recordedChunks = [];
}

// 绑定按钮事件
startBtn.addEventListener('click', startRecording);
stopBtn.addEventListener('click', stopRecording);
</script>

</body>
</html>

复制全文 生成海报 前端开发 Web技术 编程 视频处理

推荐文章

CSS 媒体查询
2024-11-18 13:42:46 +0800 CST
JavaScript中的常用浏览器API
2024-11-18 23:23:16 +0800 CST
CSS 中的 `scrollbar-width` 属性
2024-11-19 01:32:55 +0800 CST
JavaScript设计模式:组合模式
2024-11-18 11:14:46 +0800 CST
15 个 JavaScript 性能优化技巧
2024-11-19 07:52:10 +0800 CST
Python Invoke:强大的自动化任务库
2024-11-18 14:05:40 +0800 CST
Linux 网站访问日志分析脚本
2024-11-18 19:58:45 +0800 CST
nuxt.js服务端渲染框架
2024-11-17 18:20:42 +0800 CST
使用Ollama部署本地大模型
2024-11-19 10:00:55 +0800 CST
Mysql允许外网访问详细流程
2024-11-17 05:03:26 +0800 CST
如何在Rust中使用UUID?
2024-11-19 06:10:59 +0800 CST
MySQL 1364 错误解决办法
2024-11-19 05:07:59 +0800 CST
Vue3中如何处理权限控制?
2024-11-18 05:36:30 +0800 CST
Vue3中的组件通信方式有哪些?
2024-11-17 04:17:57 +0800 CST
Vue3中的事件处理方式有何变化?
2024-11-17 17:10:29 +0800 CST
网站日志分析脚本
2024-11-19 03:48:35 +0800 CST
地图标注管理系统
2024-11-19 09:14:52 +0800 CST
js生成器函数
2024-11-18 15:21:08 +0800 CST
程序员茄子在线接单