目录
- 一、方法描述
-
- [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配合适当的降级策略通常是最佳选择。
