Web 视频录制方案解析,轻松实现录屏!

目录

  • 一、方法描述
    • [1.1 原生API (MediaRecorder + getDisplayMedia)](#1.1 原生API (MediaRecorder + getDisplayMedia))
    • [1.2 Canvas API + requestAnimationFrame](#1.2 Canvas API + requestAnimationFrame)
    • [1.3 第三方库方案](#1.3 第三方库方案)
    • [1.4 WebRTC + 服务器录制](#1.4 WebRTC + 服务器录制)
  • 二、方案对比
  • 三、选择建议
    • [3.1 简单录屏需求](#3.1 简单录屏需求)
    • [3.2 高级功能需求](#3.2 高级功能需求)
    • [3.3 专业级应用](#3.3 专业级应用)
  • 四、总结与建议
    • [4.1 技术选型总结](#4.1 技术选型总结)
    • [4.2 关键注意事项](#4.2 关键注意事项)

一、方法描述

1.1 原生API (MediaRecorder + getDisplayMedia)

通过getDisplayMedia获取屏幕流,使用MediaRecorder录制。

优点

  • 原生API,兼容性较好

  • 支持录制系统音频(需用户授权)

  • 相对简单易用

缺点

  • 需要HTTPS环境(本地localhost除外)

  • 部分浏览器不支持录制音频

  • 文件格式受浏览器限制

代码示例

c 复制代码
class ScreenRecorder {
  constructor() {
    this.mediaRecorder = null;
    this.recordedChunks = [];
    this.stream = null;
  }

  async startRecording(options = {}) {
    try {
      // 获取屏幕流
      this.stream = await navigator.mediaDevices.getDisplayMedia({
        video: {
          cursor: options.cursor || "always",
          displaySurface: options.displaySurface || "monitor"
        },
        audio: options.withAudio ? {
          echoCancellation: false,
          noiseSuppression: false,
          sampleRate: 44100
        } : false
      });

      // 创建MediaRecorder
      const mimeType = this.getSupportedMimeType();
      this.mediaRecorder = new MediaRecorder(this.stream, {
        mimeType,
        videoBitsPerSecond: options.bitrate || 2500000
      });

      // 收集数据块
      this.mediaRecorder.ondataavailable = (event) => {
        if (event.data.size > 0) {
          this.recordedChunks.push(event.data);
        }
      };

      // 开始录制
      this.mediaRecorder.start(options.timeSlice || 1000);
      
      return { success: true, stream: this.stream };
    } catch (error) {
      return { success: false, error: error.message };
    }
  }

  stopRecording() {
    return new Promise((resolve) => {
      if (!this.mediaRecorder) {
        resolve(null);
        return;
      }

      this.mediaRecorder.onstop = () => {
        const blob = new Blob(this.recordedChunks, {
          type: this.mediaRecorder.mimeType
        });
        resolve(blob);
        this.cleanup();
      };

      this.mediaRecorder.stop();
    });
  }

  getSupportedMimeType() {
    const types = [
      'video/webm;codecs=vp9,opus',
      'video/webm;codecs=vp8,opus',
      'video/webm;codecs=h264,opus',
      'video/mp4;codecs=h264,aac',
    ];
    
    return types.find(type => MediaRecorder.isTypeSupported(type)) || '';
  }

  cleanup() {
    if (this.stream) {
      this.stream.getTracks().forEach(track => track.stop());
    }
    this.recordedChunks = [];
    this.mediaRecorder = null;
    this.stream = null;
  }
}

// 使用示例
const recorder = new ScreenRecorder();

// 开始录制
const start = async () => {
  const result = await recorder.startRecording({
    withAudio: true,
    cursor: "motion"
  });
  
  if (result.success) {
    console.log("录制开始");
  }
};

// 停止录制并下载
const stop = async () => {
  const blob = await recorder.stopRecording();
  if (blob) {
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `recording-${Date.now()}.webm`;
    a.click();
    URL.revokeObjectURL(url);
  }
};

1.2 Canvas API + requestAnimationFrame

通过Canvas捕获并逐帧绘制。

优点

  • 完全控制录制过程

  • 可添加自定义水印、特效

  • 不依赖MediaRecorder API

缺点

  • 性能开销大

  • 不支持音频录制

  • 实现复杂

代码示例

c 复制代码
class CanvasRecorder {
  constructor(canvas, options = {}) {
    this.canvas = canvas;
    this.frames = [];
    this.recording = false;
    this.fps = options.fps || 30;
    this.chunks = [];
  }

  async start() {
    this.recording = true;
    this.recordFrame();
    
    // 如果需要音频,可以额外获取音频轨道
    if (options.withAudio) {
      this.audioStream = await navigator.mediaDevices.getUserMedia({ audio: true });
    }
  }

  recordFrame() {
    if (!this.recording) return;
    
    // 捕获当前canvas帧
    const dataURL = this.canvas.toDataURL('image/webp', 0.8);
    this.frames.push(dataURL);
    
    setTimeout(() => {
      requestAnimationFrame(() => this.recordFrame());
    }, 1000 / this.fps);
  }

  stop() {
    this.recording = false;
    return this.generateVideo();
  }

  generateVideo() {
    // 这里需要使用第三方库或服务器端将帧序列转换为视频
    // 例如使用whammy.js或ffmpeg.js
    console.log(`录制了 ${this.frames.length} 帧`);
    return this.frames;
  }
}

1.3 第三方库方案

常用库

  • RecordRTC: 功能全面,支持多种媒体类型

  • html-screen-capture: 简化API调用

  • Vidhub: 商业级解决方案

代码示例

c 复制代码
import RecordRTC from 'recordrtc';

async function startRecordingWithRecordRTC() {
  const stream = await navigator.mediaDevices.getDisplayMedia({
    video: true,
    audio: true
  });

  const recorder = RecordRTC(stream, {
    type: 'video',
    mimeType: 'video/webm;codecs=vp9',
    recorderType: RecordRTC.MediaStreamRecorder,
    timeSlice: 1000,
    ondataavailable: (blob) => {
      // 实时上传或处理
    }
  });

  recorder.startRecording();
  
  // 停止录制
  setTimeout(() => {
    recorder.stopRecording(() => {
      const blob = recorder.getBlob();
      // 处理blob
    });
  }, 10000);
}

1.4 WebRTC + 服务器录制

将媒体流通过WebRTC发送到服务器录制。

优点

  • 支持长时间录制

  • 服务器端处理能力强

  • 可实现直播功能

缺点

  • 需要服务器支持

  • 实现复杂

  • 网络依赖

代码示例

c 复制代码
// 客户端发送流
async function streamToServer() {
  const stream = await navigator.mediaDevices.getDisplayMedia({
    video: true,
    audio: true
  });

  const peerConnection = new RTCPeerConnection(configuration);
  
  stream.getTracks().forEach(track => {
    peerConnection.addTrack(track, stream);
  });

  // 创建offer并发送到服务器
  const offer = await peerConnection.createOffer();
  await peerConnection.setLocalDescription(offer);
  
  // 发送offer到信令服务器
  // ... 服务器端录制逻辑
}

二、方案对比

对比图

三、选择建议

3.1 简单录屏需求

推荐方案:MediaRecorder API

  • 现代浏览器基本支持

  • 实现简单,代码量少

  • 性能影响小

3.2 高级功能需求

推荐方案:RecordRTC

  • 需要音频录制

  • 需要更多格式选项

  • 需要更精细的控制

3.3 专业级应用

推荐方案:WebRTC + 服务器

  • 长时间录制

  • 实时直播

  • 需要后处理

四、总结与建议

4.1 技术选型总结

  • 个人项目/简单需求:优先使用原生MediaRecorder API

  • 商业产品:推荐使用RecordRTC,考虑兼容性和功能完整性

  • 专业应用:采用WebRTC+服务器方案,具备扩展性

4.2 关键注意事项

  • HTTPS要求:除localhost外,必须使用HTTPS

  • 用户授权:每次录制都需要用户明确授权

  • 格式兼容:优先使用webm格式,mp4支持有限

  • 内存管理:长时间录制需分片处理

  • 错误处理:充分考虑各种异常情况

根据具体项目需求、目标用户设备和浏览器分布,选择最合适的方案。对于大多数Web应用,MediaRecorder API配合适当的降级策略通常是最佳选择。

相关推荐
发哥来了2 小时前
主流AI视频生成模型商用化能力评测:五大核心维度深度对比
人工智能·音视频
1024小神2 小时前
css主题theme变量切换实现原理学习记录
前端·css·学习
wuhen_n2 小时前
TypeScript工作流深度解析:从.ts到.js发生了什么?
前端·javascript·typescript
小二·2 小时前
Python Web 开发进阶实战:时空数据引擎 —— 在 Flask + Vue 中构建实时地理围栏与轨迹分析系统
前端·python·flask
Hao_Harrision2 小时前
50天50个小项目 (React19 + Tailwindcss V4) ✨ | TodoList(代办事项组件)
前端·typescript·react·tailwindcss·vite7
小二·2 小时前
Python Web 开发进阶实战:可验证网络 —— 在 Flask + Vue 中实现去中心化身份(DID)与零知识证明(ZKP)认证
前端·网络·python
运筹vivo@2 小时前
攻防世界:Web_php_include
前端·web安全·php
Highcharts.js2 小时前
2026年Highcharts迎来系列更新| V12.5 正式发布
javascript·信息可视化·highcharts·12.5·升级发布
weixin_462446232 小时前
使用 Python + FFmpeg 将 MP4 视频与 SRT 字幕无损合并(支持中文)
python·ffmpeg·音视频