WebRTC技术入门——视频的采集、录制和下载

WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点的连接,实现视频流和音频流或者其他任意数据的传输。 使用WebRTC完成音视频通话需要了解四个模块:音视频采集、STUN/TURN 服务器、信令服务器、端与端之间 P2P 连接,本文主要介绍使用 WebRTC 的 API 完成音视频采集。

获取可用的音视频设备

获取音视频设备可以使用enumerateDevicesAPI,enumerateDevices会请求一个可用的媒体输入和输出设备的列表,例如麦克风,摄像机,耳机设备等。 会返回一个带有一个描述设备的 MediaDeviceInfo的数组。比如:

navigator.mediaDevices.enumerateDevices().then(function(devices) {
 devices.forEach(function(device) {
   if (device.kind === 'audioinput') { //音频输入设备
  } else if (device.kind === 'videoinput') {//视频输入设备
  } else if (device.kind === 'audiooutput') { //音频输出设备
  });
})

MediaDeviceInfo包括4个属性,分别是deviceId、kind、label和groupId。 deviceId表示每个设备的唯一编号。 kind表示设备的种类。音视频设备包括三种类型:音频输入设备、音频输出设备以及视频输入设备。音频的输入设备和输出设备是两种不同类型的设备。而对于视频设备来说,它只有输入设备,视频的输出则是由显示器完成的。 label是设备的名字。 groudId表示组Id。如果两个设备是在同一个硬件上,则它们属于同一组,因此它们的groupId是一致的,例如音频的输入与输出设备就是集成到一起的。

MediaStream与MediaStreamTrack简介

在WebRTC中有两个重要的概念,即MediaStreamMediaStreamTrackMediaStreamTrack称为“轨”,表示单一类型的媒体源,比如从摄像头采集到的视频数据就是一个MediaStreamTrack,而从麦克风采集的音频又是另外一个MediaStreamTrackMediaStreamTrack中包含如下属性:

  1. enabled,布尔值,为 true 时表示轨道有效,并且可以被渲染。为 false 时表示轨道失效,只能被渲染为静音或黑屏。
  2. id,轨道的唯一标识。
  3. kind,轨道的类型,如果为“audio”表示轨道为音频轨道,为“video”则为视频轨道。
  4. readyState,表示轨道的当前状态。”live”表示当前输入已经连接并且在尽力提供实时数据。在这种情况下,输出数据可以通过操作 MediaStreamTrack.enabled 属性进行开关。“ended”表示这个输出连接没有更多的数据了,而且也不会提供更多的数据了。

MediaStream称为“流”,它可以包括0个或多个MediaStreamTrackMediaStream有两个重要作用,一是可以作为录制或者渲染的源,可以将Stream中的数据通过浏览器中的<video>标签播放出来;二是在同一个MediaStream中的MediaStreamTrack数据会进行同步(比如同一个MediaStream中的音频轨和视频轨会进行时间同步),而不同MediaStream中的MediaStreamTrack之间不进行时间同步。”

音视频的采集

通过navigator.mediaDevices.getUserMedia()方法来获取音视频,该方法会请求访问摄像头。如果是第一次请求摄像头,浏览器会向用户弹出提示窗口,让用户决定是否可以访问摄像头。它返回一个 Promise对象,成功后会resolve回调一个MediaStream对象。 若用户拒绝了使用权限,或者需要的媒体源不可用,promise会reject回调一个 PermissionDeniedError 或者 NotFoundError 。

const constraints = { video: true };
navigator.mediaDevices.getUserMedia(constraints)
.then(function(mediaStream) {
 const video = document.querySelector('video');
 video.srcObject = mediaStream;
 video.onloadedmetadata = function(e) {
   //当视频的元数据已加载时,会触发loadedmetadata事件,开始播放视频
   video.play();
};
})
.catch(function(err) { console.log(err.name + ": " + err.message); });

上面这个例子,我们使用了constraints告诉浏览器获取当前设备的视频,我们还可以对音视频数据进行约束,比如请求不带任何参数的音频和视频:{ audio: true, video: true } video还支持设置分辨率,比如获取1280×720 的摄像头分辨率:

{ audio: true, video: { width: 1280, height: 720 }}

需要注意的是设置的分辨率不一定会生效,浏览器会试着满足这个请求参数,但是如果无法准确满足此请求中参数要求的参数时,有可能返回其它的分辨率。 设置帧率:

{ video: { frameRate: { ideal: 10, max: 15 } } };

ideal表示理想的帧率是10,max表示最大帧率是15 video还支持其他参数的设置,比如在移动设备上面,如下的例子表示优先使用前置摄像头:

{ audio: true, video: { facingMode: "user" } }

强制使用后置摄像头:

{ audio: true, video: { facingMode: { exact: "environment" } } }

在线demo:https://webrtc.github.io/samples/src/content/devices/input-output/

屏幕分享

屏幕分享是通过navigator.mediaDevices.getDisplayMedia()方法来实现,会提示用户去选择和授权捕获展示的内容或部分内容,核心代码如下:

let displayMediaOptions = {
 video: {
   width: {max: 1280},
   height: {max: 720},
   frameRate: {ideal: 15}
}
};  
navigator.mediaDevices.getDisplayMedia(displayMediaOptions)
    .then(handleSuccess);

function handleSuccess(stream) {
 const video = document.querySelector('video');
 video.srcObject = stream;
 //当用户结束屏幕共享时
 stream.getVideoTracks()[0].addEventListener('ended', () => {

});
}

调用之后会出现类似下面的弹窗,可以选择分享屏幕、窗口或者chrome的标签页

在线demo:https://webrtc.github.io/samples/src/content/getusermedia/getdisplaymedia/

实现视频录制和下载

视频录制需要用 MediaRecorder 的 api,它可以监听流中的数据,我们可以把获取到的数据保存到数组中。然后回放的时候设置到另一个video的 src 属性就可以了。 下载也是基于 MediaRecorder 录制的数据,转成 blob 后通过 a 标签触发下载。 MediaRecorder用法如下: const mediaRecorder = new MediaRecorder(stream, {mimeType : 'video/webm'}),MediaRecorder会创建一个新的MediaRecorder对象,对指定的stream对象进行录制,mimeType表示 MediaRecorder 录制容器的 MIME 类型 从摄像头获取媒体流并进行录制:

const recordedBlobs = []  
navigator.mediaDevices.getUserMedia({video: true})
.then(function(stream) {
   const mediaRecorder = new MediaRecorder(stream, {type : 'video/webm'});
   //监听录制结束事件
   mediaRecorder.onstop = (event) => {
     console.log('录制结束: ', event);
  };
   // 处理 dataavailable 事件,该事件可用于获取录制的媒体资源
   mediaRecorder.ondataavailable = (event) => {
     console.log('handleDataAvailable', event);
     if (event.data && event.data.size > 0) {
       //吧获取的媒体数据放在数组中
       //event.data是一个Blob对象,Blob 对象表示一个不可变、原始数据的类文件对象。
       recordedBlobs.push(event.data);
    }
  };
   //开始录制
   mediaRecorder.start();
})

结束录制: mediaRecorder.stop(); 播放录制的视频:

  //将获取的recordedBlobs转成Blob类型
 const blob = new Blob(recordedBlobs, {type : 'video/webm'});
 //获取video元素
 const recordedVideo = document.querySelector('video');
 //blob 要经过 URL.createObjectURL 的处理,才能被播放。
 recordedVideo.src = window.URL.createObjectURL(blob);
 recordedVideo.play();

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

download.addEventListener('click', () => {
 const blob = new Blob(recordedBlobs, {type: 'video/webm'});
 const url = URL.createObjectURL(blob);

 const a = document.createElement('a');
 a.href = url;
 a.style.display = 'none';
 a.download = 'record.webm';
 a.click();
});

生成一个隐藏的 a 标签,设置 download 属性就可以支持下载,然后触发 click 事件就可以下载视频 在线demo:https://webrtc.github.io/samples/src/content/getusermedia/record/

参考文章: https://developer.mozilla.org/zh-CN/docs/Web/API/MediaStreamTrack https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia https://developer.mozilla.org/zh-CN/docs/Web/API/Blob 《webRTC音视频实时互动技术》

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇