WebRTC 之数据采集 — 认识 MediaDevices

1,545 阅读4分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

WebRTC 是一些列用于实时通信的 API 集合,使用 WebRTC API 可以快速搭建实时音视频应用。WebRTC 虽然是 web API,但是它也提供了 native 工具库,在 native 程序中引入 WebRTC 可以实现多端通信。因此 WebRTC 是实时音视频应用必备的底层技术。

浏览器的 WebRTC API 提供了三部分能力:

  • MediaDevices
  • PeerConnections
  • DataChannels

其中 MediaDevices 负责数据采集,PeerConnections 负责音视频流传输,DataChannels 提供了数据通道。

本篇为 WebRTC 系列第一篇,这篇文章主要看一下 MediaDevices 部分。与其他 native 端不同,在 WebRTC 之前浏览器没有调用摄像头麦克风等用户媒体的能力,因此对浏览器端 WebRTC 而言,MediaDevices 是必不可少的一部分。

在浏览器中我们通过 window.navigator.mediaDevices 来获取 MediaDevices 对象,看下 mediaDevices 对象上的几个重要方法:

getUserMedia

getUserMedia 是 WebRTC 中最重要的 API,它给浏览器访问用户音视频的能力,它是浏览器访问用户媒体信息的唯一方式,因此即使在非实时音视频场景,只要涉及到用户摄像头和麦克风的操作都离不开这个 API。

使用 getUserMedia:

navigator.mediaDevices.getUserMedia({ audio: true, video: true })

调用 API 后浏览器会向用户请求需要的摄像头麦克风权限,此函数会返回 Promise,当用户同意授权后开始采集,resolve 采集到的 MediaStream,想要在本地预览 MediaStream 很简单,只需要创建一个 video 标签,把 MediaStream 赋值给 video 的 srcObject 即可:

<video id="preview"></video>
<script>
	const preview = document.getElementById('preview');
	navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(
		stream => preview.srcObject = stream;
	);
</script>

getUserMedia 的参数是 MediaStreamConstraints 类型,它可以指定采集到流的条件,可以只采集音频或视频轨道,可以指定视频大小,指定采集设备等,详见文档

采集到的 MediaStream 对象实际上是由多条轨道(tracks)组成的,video、audio 分别有自己的轨道,使用 getVideoTracks,getAudioTracks 可以分别获取视频音频轨道,也可以使用 getTracks 获取全部轨道。

音视频轨道对象为 MediaStreamTrack,在音视频应用中,虽然我们最终看到的是以一个带有音频和视频的 video 资源,但是实际上从采集到处理音视频都是分开的,因此在这里我们可以对音视频的处理和发送都是针对 MediaStreamTrack 对象来做的,我们可以把 track 数据传入其他处理程序如 MediaStreamTrackProcessor 等,也可以把 track 传入 PeerConnections 进行发送。

getDisplayMedia

getDisplayMedia 用于屏幕录制或共享的场景,它采集的是用户屏幕的数据,桌面、应用、标签页等都可以作为采集对象,采集到的数据封装位一个 MediaStream 对象,可供后续处理。getDisplayMedia 的使用方法和 getUserMedia 非常相似:

<video id="preview"></video>
<script>
	const preview = document.getElementById('preview');
	navigator.mediaDevices.getDisplayMedia({ video: true, audio: true }).then(
		stream => preview.srcObject = stream;
	);
</script>

这里依旧使用一个 video 作为预览窗口,当调用 getDisplayMedia 时浏览器会弹出共享内容选择窗口,当用户选择共享区域后 resolve 采集到的 MediaStream ,这里比较特殊的一点是 getDisplayMedia 至少需要有一个 video 轨道数据。之后拿到 MediaStream 对象就可以根据需要执行后续的操作。

enumerateDevices

enumerateDevices 可以获取可用的媒体输入和输出设备列表信息,在实际应用中,用户设备上看有多个摄像头和麦克风,这时可以通过 enumerateDevices 拿到全部的设备信息,每个设备有一个 id 标识,这个 id 可以作为 getUserMedia 的参数传入来指定采集设备。

devicechange

devicechange 是一个事件,可以通过 ondevicechange 或 addEventlistener 来监听,当用户的设备信息发生变化时会触发,可以在 devicechange 后重新获取设备列表更新设备信息。

以上几个就是 mediaDevices 中比较重要的方法。mediaDevices API 是构建多媒体应用的基础 API,它们提供了浏览器访问摄像头麦克风和屏幕录制的能力,给 web 端应用带来了更多可能,本文是 WebRTC 系列文章第一篇,接下来会看到更完整的实时音视频应用是如何构建的。