快速入门 WebRTC:屏幕和摄像头的录制、回放、下载

开发 前端
今天我们就来实现下采集的部分,来快速入下门,直观感受下 WebRTC 能做什么吧。我们会实现屏幕的录制、摄像头的录制,并且能够回放录制的内容,还支持下载。

[[441095]]

不知你是否用过 web 版的视频面试,或者 web 版在线会议,它们都支持分享屏幕、也能开启摄像头。这些都是浏览器上实现的,作为前端开发,是否好奇过这些功能的实现原理呢?

浏览器上的音视频通信相关的能力叫做 WebRTC(real time communication),是随着网速越来越快、音视频需求越来越多,而被浏览器所实现的音视频的标准 API。

音视频通信的流程有五步:采集、编码、通信、解码、渲染。

这五步比较好理解,但是每一步都有挺多内容的。

今天我们就来实现下采集的部分,来快速入下门,直观感受下 WebRTC 能做什么吧。

我们会实现屏幕的录制、摄像头的录制,并且能够回放录制的内容,还支持下载。

那我们开始吧。

思路分析

浏览器提供了 navigator.mediaDevices.getDisplayMedia 和 navigator.mediaDevices.getUserMedia 的 api,分别可以用来获取屏幕的流、麦克风和摄像头的流。

从名字就可以看出来 getDisplayMedia 获取的是屏幕的流,getUserMedia 获取的是和用户相关的,也就是麦克风、摄像头这些的流。

获取流之后设置到 video 的 srcObject 属性上就可以实现播放。

如果想要录制视频,需要用 MediaRecorder 的 api,它可以监听流中的数据,我们可以把获取到的数据保存到数组中。然后回放的时候设置到另一个视频的 srcObject 属性就可以了。

下载也是基于 MediaRecorder 录制的数据,转成 blob 后通过 a 标签触发下载。

大概理清了思路,我们来写下代码。

代码实现

我们在页面放两个 video 标签,一个用于实时的看录制的视频,一个用于回放。

然后放几个按钮。

  1. <selection> 
  2.     <video autoplay id = "player"></video> 
  3.     <video id = "recordPlayer"></video> 
  4. </selection> 
  5. <section>  
  6.     <button id = "startScreen">开启录屏</button> 
  7.     <button id = "startCamera">开启摄像头</button> 
  8.     <button id = "stop">结束</button> 
  9.     <button id = "reply">回放</button> 
  10.     <button id = "download">下载</button> 
  11. </selection> 

 

“开始录屏” 和 “开启摄像头” 按钮点击的时候都开启录制,但是方式不同。

  1. startScreenBtn.addEventListener('click', () => { 
  2.     record('screen'); 
  3. }); 
  4. startCameraBtn.addEventListener('click', () => { 
  5.     record('camera'); 
  6. }); 

一个是用 getUserMedia 的 api 来获取麦克风、摄像头数据,一个是用 getDisplayMedia 的 api 获取屏幕数据。

  1. async function record(recordType) { 
  2.     const getMediaMethod = recordType === 'screen' ? 'getDisplayMedia' : 'getUserMedia'
  3.     const stream = await navigator.mediaDevices[getMediaMethod]({ 
  4.         video: { 
  5.             width: 500, 
  6.             height: 300, 
  7.             frameRate: 20 
  8.         } 
  9.     }); 
  10.  
  11.     player.srcObject = stream; 

指定下宽高和帧率等参数,把返回的流设置到 video 的 srcObject 属性上,就可以实时看到对应的音视频。

然后,还要做录制,需要用 MediaRecorder 的 api,传入 stream,然后调用 start 方法,开启录制。

  1. let blobs = [], mediaRecorder; 
  2.  
  3. mediaRecorder = new MediaRecorder(stream, { 
  4.     mimeType: 'video/webm' 
  5. }); 
  6. mediaRecorder.ondataavailable = (e) => { 
  7.     blobs.push(e.data); 
  8. }; 
  9. mediaRecorder.start(100); 

start 的参数是分割的大小,传入 100 代表每 100ms 保存一次数据。

监听 dataavailable 事件,在其中把获取到的数据保存到 blobs 数组中。

之后根据 blobs 数组生成 blob,就可以分别做回放和下载了:

回放:

  1. replyBtn.addEventListener('click', () => { 
  2.     const blob = new Blob(blobs, {type : 'video/webm'}); 
  3.     recordPlayer.src = URL.createObjectURL(blob); 
  4.     recordPlayer.play(); 
  5. }); 

blob 要经过 URL.createObjectURL 的处理,才能作为 object url 来被播放。

下载:

  1. download.addEventListener('click', () => { 
  2.     var blob = new Blob(blobs, {type: 'video/webm'}); 
  3.     var url = URL.createObjectURL(blob); 
  4.  
  5.     var a = document.createElement('a'); 
  6.     a.href = url; 
  7.     a.style.display = 'none'
  8.     a.download = 'record.webm'
  9.     a.click(); 
  10. }); 

生成一个隐藏的 a 标签,设置 download 属性就可以支持下载。然后触发 click 事件。

目前为止,我们已经实现了麦克风、摄像头、屏幕的录制,支持了回放和下载。

这里也贴一份:

  1. <html> 
  2. <head> 
  3.         <title>录屏并下载</title> 
  4. </head> 
  5. <body> 
  6.         <selection> 
  7.                 <video autoplay id = "player"></video> 
  8.                 <video id = "recordPlayer"></video> 
  9.         </selection> 
  10. <section>  
  11.     <button id = "startScreen">开启录屏</button> 
  12.     <button id = "startCamera">开启摄像头</button> 
  13.     <button id = "stop">结束</button> 
  14.     <button id = "reply">回放</button> 
  15.     <button id = "download">下载</button> 
  16.         </selection> 
  17.  
  18. <script> 
  19.     const player = document.querySelector('#player'); 
  20.     const recordPlayer = document.querySelector('#recordPlayer'); 
  21.     let blobs = [], mediaRecorder; 
  22.  
  23.     async function record(recordType) { 
  24.         const getMediaMethod = recordType === 'screen' ? 'getDisplayMedia' : 'getUserMedia'
  25.         const stream = await navigator.mediaDevices[getMediaMethod]({ 
  26.             video: { 
  27.                 width: 500, 
  28.                 height: 300, 
  29.                 frameRate: 20 
  30.             } 
  31.         }); 
  32.         player.srcObject = stream; 
  33.  
  34.         mediaRecorder = new MediaRecorder(stream, { 
  35.             mimeType: 'video/webm' 
  36.         }); 
  37.         mediaRecorder.ondataavailable = (e) => { 
  38.             blobs.push(e.data); 
  39.         }; 
  40.         mediaRecorder.start(100); 
  41.     } 
  42.  
  43.     const downloadBtn = document.querySelector('#download'); 
  44.     const startScreenBtn = document.querySelector('#startScreen'); 
  45.     const startCameraBtn = document.querySelector('#startCamera'); 
  46.     const stopBtn = document.querySelector('#stop'); 
  47.     const replyBtn = document.querySelector('#reply'); 
  48.  
  49.     startScreenBtn.addEventListener('click', () => { 
  50.         record('screen'); 
  51.     }); 
  52.     startCameraBtn.addEventListener('click', () => { 
  53.         record('camera'); 
  54.     }); 
  55.  
  56.     stopBtn.addEventListener('click', () => { 
  57.         mediaRecorder && mediaRecorder.stop(); 
  58.     }); 
  59.  
  60.     replyBtn.addEventListener('click', () => { 
  61.         const blob = new Blob(blobs, {type : 'video/webm'}); 
  62.         recordPlayer.src = URL.createObjectURL(blob); 
  63.         recordPlayer.play(); 
  64.     }); 
  65.  
  66.     download.addEventListener('click', () => { 
  67.         var blob = new Blob(blobs, {type: 'video/webm'}); 
  68.         var url = URL.createObjectURL(blob); 
  69.  
  70.         var a = document.createElement('a'); 
  71.         a.href = url; 
  72.         a.style.display = 'none'
  73.         a.download = 'record.webm'
  74.         a.click(); 
  75.     }); 
  76. </script> 
  77. </body> 
  78. </html> 

总结

音视频通信分为 采集、编码、通信、解码、渲染 这五步,浏览器的音视频通信相关的 API 叫做 WebRTC。

我们实现了下采集的部分来入门了下 WebRTC,还支持了回放和下载。

涉及到的 api 有 3 个:

  • navigator.mediaDevices.getUserMedia:获取麦克风、摄像头的流
  • navigator.mediaDevices.getDisplayMedia:获取屏幕的流
  • MediaRecorder:监听流的变化,实现录制

我们分别用前两个 api 获取到了屏幕、麦克风、摄像头的流,然后用 MediaRecorder 做了录制,把数据保存到数组中,之后生成了 Blob。

video 可以设置 srcObject 属性为一个流,这样能直接播放,如果设置 Blob 的话需要用 URL.createObjectURL 处理下。

下载的实现是通过 a 标签指向 Blob 对象的 object url,通过 download 属性指定下载行为,然后手动触发 click 来下载。

我们学会了如何用 WebRTC 来采集数据,这是音视频通信的数据来源,之后还要实现编解码和通信才能是完整 RTC 流程,这些后续再深入。

我们直观的感受了下 WebRTC 能做什么,是不是感觉这个领域也挺有趣的呢?

 

责任编辑:姜华 来源: 神光的编程秘籍
相关推荐

2009-10-22 09:00:10

Windows 7摄像工具

2017-06-20 11:45:52

2021-03-11 10:21:55

特斯拉黑客网络攻击

2013-03-21 09:56:09

2012-06-23 20:13:44

HTML5

2011-04-25 09:16:10

Windows 8

2022-05-12 09:25:19

Python播放视频摄像头

2023-01-13 08:00:00

人工智能摄像头人脸识别

2009-06-17 11:52:01

Linux

2009-08-21 17:24:18

C#控制摄像头

2011-09-08 13:53:20

Linux摄像头

2023-05-26 16:42:28

2022-04-15 11:30:59

代码,Python保存视频

2018-06-20 11:54:54

2020-06-04 10:59:10

JavaScript开发技术

2011-09-13 15:51:11

PhoneGap AP

2014-07-16 13:36:30

MotionLinux监控

2019-05-20 09:42:04

2013-11-20 11:24:05

AndroidAPI

2020-12-01 13:08:21

物联网物联网安全
点赞
收藏

51CTO技术栈公众号