# WebRTC(四)视频的录制
# 服务端录制和客户端录制
- 服务端录制:优点是不用担心客户因自身电脑问题造成录制失败(如磁盘空间不足),也不会因录制时抢占资源(CPU 占用率过高)而导致其他应用出现问题等;缺点是实现的复杂度很高。
- 客户端录制:优点是方便录制方(如老师)操控,并且所录制的视频清晰度高,实现相对简单。这里可以和服务端录制做个对比,一般客户端摄像头的分辨率都非常高的(如 1280x720),所以客户端录制可以录制出非常清晰的视频;但服务端录制要做到这点就很困难了,本地高清的视频在上传服务端时由于网络带宽不足,视频的分辨率很有可能会被自动缩小到了 640x360,这就导致用户回看时视频特别模糊,用户体验差。不过客户端录制也有很明显的缺点,其中最主要的缺点就是录制失败率高。因为客户端在进行录制时会开启第二路编码器,这样会特别耗 CPU。而 CPU 占用过高后,就很容易造成应用程序卡死。除此之外,它对内存、硬盘的要求也特别高。
# 如何录制本地音视频
WebRTC 为我们提供了一个非常方便的类,即 MediaRecorder。创建 MediaRecorder 对象的格式如下:
var mediaRecorder = new MediaRecorder(stream[, options]);
1
其参数含义如下:
- stream,通过 getUserMedia 获取的本地视频流或通过 RTCPeerConnection 获取的远程视频流。
- options,可选项,指定视频格式、编解码器、码率等相关信息,如 mimeType: 'video/webm;codecs=vp8'。
MediaRecorder 对象还有一个特别重要的事件,即 ondataavailable 事件。当 MediaRecoder 捕获到数据时就会触发该事件。通过它,我们才能将音视频数据录制下来。
# 视频录取
# 1.创建html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>视频录取</title>
</head>
<body>
<video id="recvideo"></video>
<button id="record">Start Record</button>
<button id="recplay">Play</button>
<button id="download">Download</button>
<video autoplay playsinline id="vi"></video>
<script src="./js/video.js"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 2.创建js
var buffer;
// stream,通过 getUserMedia 获取的本地视频流或通过 RTCPeerConnection 获取的远程视频流。
// options,可选项,指定视频格式、编解码器、码率等相关信息,如 mimeType: 'video/webm;codecs=vp8'。
// MediaRecorder 对象还有一个特别重要的事件,即 ondataavailable 事件。当 MediaRecoder 捕获到数据时就会触发该事件。通过它,我们才能将音视频数据录制下来。
//当该函数被触发后,将数据压入到blob中
function handleDataAvailable(e){
if(e && e.data && e.data.size > 0){
buffer.push(e.data);
}
}
let mediaRecorder;
function startRecord(){
buffer = [];
//设置录制下来的多媒体格式
var options = {
mimeType: 'video/webm;codecs=vp8'
}
//判断浏览器是否支持录制
if(!MediaRecorder.isTypeSupported(options.mimeType)){
console.error(`${options.mimeType} is not supported!`);
return;
}
try{
//创建录制对象
mediaRecorder = new MediaRecorder(window.stream, options);
}catch(e){
console.error('Failed to create MediaRecorder:', e);
return;
}
//当有音视频数据来了之后触发该事件
mediaRecorder.ondataavailable = handleDataAvailable;
//开始录制
mediaRecorder.start(10);
recvideo = null
}
function stopRecord(){
mediaRecorder.stop();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
当你点击 Record 按钮的时候,就会调用 startRecord 函数。在该函数中首先判断浏览器是否支持指定的多媒体格式,如 webm。 如果支持的话,再创建 MediaRecorder 对象,将音视频流录制成指定的媒体格式文件。
实际存储时,是通过 ondataavailable 事件操作的。每当 ondataavailable 事件触发时,就会调用 handleDataAvailable 函数。该函数的实现就特别简单了,直接将数据 push 到 buffer 中,实际在浏览器底层使用的是 Blob 对象。
另外,在开启录制时,可以设置一个毫秒级的时间片,这样录制的媒体数据会按照你设置的值分割成一个个单独的区块,否则默认的方式是录制一个非常大的整块内容。分成一块一块的区块会提高效率和可靠性,如果是一整块数据,随着时间的推移,数据块越来越大,读写效率就会变差,而且增加了写入文件的失败率。
# 2. 回放录制文件
# 添加js代码
下面的 JavaScript 是将录制内容与标签联接到一起:
var blob = new Blob(buffer, {type: 'video/webm'});
recvideo.src = window.URL.createObjectURL(blob);
recvideo.srcObject = null;
recvideo.controls = true;
recvideo.play();
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 下载录制好的文件
tnDownload.onclick = ()=> {
var blob = new Blob(buffer, {type: 'video/webm'});
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.style.display = 'none';
a.download = 'aaa.webm';
a.click();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
← 三-利用浏览器实现拍照功能 五-桌面抓取 →