话不多说,直接上方案~
方案对比
方案 | star | 实现成本 | 原理 | 特点 | live demo |
---|---|---|---|---|---|
原生API | - | 高 | 调用getDisplayMedia和MediaRecorder,手动管理流和数据块如果需要实现区域录屏,需要canvas绘制 | 如果需要区域录屏、将录屏文件转为GIF,需要额外开发 | |
RecordRTC | 6.7k | 需二次封装 | 封装MediaRecorder | 自动合并数据块生成完整视频;支持webm→mp4转换(需集成FFmpeg.js);兼容旧版浏览器(通过adapter.js)如果需要区域录屏、将录屏文件转为GIF,需要额外开发 | www.webrtc-experiment.com/RecordRTC/s…Screen RecordingRecord Cropped Screen |
文件转GIF,可使用 gif.js
技术方案
原生API方案(无第三方依赖)
实现方式:直接调用getDisplayMedia
和MediaRecorder
,手动管理流和数据块。
核心代码(React示例):
import React, { useState, useRef } from 'react';
import { Button, Modal } from 'antd';
const NativeScreenRecorder = () => {
const [isRecording, setIsRecording] = useState(false);
const [previewUrl, setPreviewUrl] = useState('');
const mediaRecorderRef = useRef<MediaRecorder | null>(null);
const chunksRef = useRef<BlobPart[]>([]);
const startRecording = async () => {
try {
// 获取屏幕流(含系统声音)
const stream = await navigator.mediaDevices.getDisplayMedia({
video: { cursor: 'always' },
audio: { echoCancellation: false }
});
// 初始化MediaRecorder
mediaRecorderRef.current = new MediaRecorder(stream);
mediaRecorderRef.current.ondataavailable = (e) => chunksRef.current.push(e.data);
mediaRecorderRef.current.onstop = () => {
const blob = new Blob(chunksRef.current, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
setPreviewUrl(url);
stream.getTracks().forEach(track => track.stop()); // 释放资源
};
mediaRecorderRef.current.start();
setIsRecording(true);
} catch (err) {
console.error('录屏启动失败:', err);
}
};
const stopRecording = () => {
mediaRecorderRef.current?.stop();
setIsRecording(false);
chunksRef.current = []; // 清空数据块
};
return (
<div>
<Button onClick={startRecording} disabled={isRecording}>开始录屏</Button>
<Button onClick={stopRecording} disabled={!isRecording} danger>结束录屏</Button>
<Modal
visible={!!previewUrl}
title="录制预览"
onCancel={() => {
URL.revokeObjectURL(previewUrl);
setPreviewUrl('');
}}
>
<video src={previewUrl} controls autoPlay style={{ width: '100%' }} />
</Modal>
</div>
);
};
优缺点:
优点 | 缺点 |
---|---|
无第三方依赖,体积小 | 需手动处理流管理、错误捕获 |
支持最高质量录制(原始流) | 仅支持WebM格式 |
完全控制录制流程 | 系统声音录制需用户手动启用实验功能 |
RecordRTC
功能:封装MediaRecorder
,支持屏幕/摄像头/音频录制,提供pause
/resume
/格式转换
等功能。
核心特性:
-
自动合并数据块生成完整视频;
-
支持
webm
→mp4
转换(需集成FFmpeg.js); -
兼容旧版浏览器(通过
adapter.js
)。
示例代码:
import RecordRTC from 'recordrtc';
const startRecording = async () => {
const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
const recordRTC = new RecordRTC(stream, {
type: 'video',
mimeType: 'video/webm',
disableLogs: true
});
recordRTC.startRecording();
// 停止录制并获取视频
const stop = () => {
recordRTC.stopRecording(() => {
const videoBlob = recordRTC.getBlob();
const videoUrl = URL.createObjectURL(videoBlob);
// 预览或下载...
});
stream.getTracks().forEach(track => track.stop());
};
};
优缺点:
优点 | 缺点 |
---|---|
简化流管理和数据处理 | 依赖外部库(~30KB) |
支持格式转换(需FFmpeg) | 最新浏览器特性支持滞后 |
面临的挑战
性能与资源问题
问题场景 | 具体表现 | 解决方案 |
---|---|---|
长时间录制内存溢出 | - 数据块(chunks)积累导致内存占用过高- 浏览器崩溃或录制卡顿 | - 分段录制(每5分钟生成一个文件)- 使用WritableStream实时写入磁盘- 实现内存监控与警告机制 |
用户体验问题
问题场景 | 具体表现 | 解决方案 |
---|---|---|
录屏权限弹窗干扰 | - 每次录制都需用户手动授权 | - 缓存用户授权状态?(提供"记住此选择"选项) |
操作反馈不直观 | - 录制中缺少明显状态指示- 暂停/继续操作不流畅 | - 提供快捷键支持 |
开发挑战
问题场景 | 具体表现 | 解决方案 |
---|---|---|
API复杂度高 | - getDisplayMedia/MediaRecorder参数配置复杂- 状态管理困难 | 优先使用成熟框架:如RecordRTC,避免重复造轮子 |
明确功能边界:根据目标用户需求,合理取舍功能
渐进式增强:先实现基础录屏功能,再逐步添加选区录制、编辑等扩展功能