WebRTC API音视频采集、录制和下载

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表示最大帧率是15video还支持其他参数的设置,比如在移动设备上面,如下的例子表示优先使用前置摄像头:

{ 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

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论