前言
WebRTC 是一种支持网页浏览器进行实时语音视频通话的技术,于2011年6月1日开源并在 Google、Mozilla、Opera 的支持下被纳入万维网联盟的 W3C 推荐标准。
这是我第一次接触该技术,因此在正式使用之前先对该技术进行基本的学习。
获取音视频流
要开发音视频通话功能,首先我们需要获取到音视频流。现代浏览器基本已经实现了 WebRTC 的 API,我们可以通过调用这些 API 实现最基本的功能。首先我们来认识一下如何通过 WebRTC 的 API 获取用户的默认麦克风的音频流,用到的代码很简单:
navigator.mediaDevices.getUserMedia({
audio: true
}).then((stream) => {
console.log(stream.getTracks());
})
我们通过调用 navigator.mediaDevices.getUserMedia()
方法,获取到了一个 Promise<MediaStream>
对象,通过 then
方法得到了一个媒体流,而这个媒体流中包含着一个 kind
为 “audio” 的媒体流轨道。当你将这个媒体流作为 srcObject
赋给某个 <audio />
DOM 对象时,你就能听到自己麦克风的声音了。
接下来我们也可以仿照上面的写法,同时获取麦克风的音频和摄像头的视频,代码也很简单,只要向入参中加一条 video: true
就可以了:
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then((stream) => {
console.log(stream.getTracks());
})
这回我们就会看到,这次获取到的流中多了一条视频轨道,其内容即是我们的摄像头所拍摄到的数据。
学会了基本的媒体流获取操作后,我们还可以添加更多的约束来根据需要获取不同的流,比如下面这样:
navigator.mediaDevices.getUserMedia({
audio: {
noiseSuppression: true,
echoCancellation: true,
},
video: {
width: 1920,
height: 1080,
frameRate: {
max: 30
}
}
}).then((stream) => {
console.log(stream.getTracks());
})
在这个例子中,我们给 getUserMedia
方法传入了一些特殊的约束,下面我们来逐个介绍一下这些约束所代表的含义:
- noiseSuppression:表示噪音抑制,默认值为
true
。 - echoCancellation:表示回声消除,默认值为
true
。 - width、height:表示获取的视频流的宽高。
- frameRate:表示获取的视频流的帧数,max表示最大值,min表示最小值,exact表示确切值。
除了上述的几个约束外还有其他更多的约束,可以自行查阅手册进行学习,本文不做过多赘述。
捕获桌面流
类似腾讯会议,我们也想在我们的产品中加入屏幕共享的功能,类似的桌面捕获功能 WebRTC 也有为我们实现,我们可以通过下面这个 API 进行调用:
navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true
}).then((stream) => {
console.log(stream.getTracks());
})
通过这种方式,我们可以选择捕获不同的窗口并分享其中的画面和音频。
选择不同的设备
当然,为了满足不同用户的需要,有时我们还需要让用户自行选择需要使用的音视频设备。要做到这一点,我们首先得将用户当前设备上的所有音视频设备都列举出来。
navigator.mediaDevices.enumerateDevices().then((devices) => {
for (const device of devices) {
console.log(device);
}
})
通过这个调用,我们能够获取到当前用户的机器上所连接的所有音视频设备。并可以通过设备的 kind
属性判断出这是什么类型的设备。
- audioinput 是音频输入设备,即麦克风一类;
- audiooutput 是音频输出设备,即扬声器一类;
- videoinput 是视频输入设备,即摄像头一类。
显然,我们需要的就是 audioinput
和 videoinput
两类输入设备,而且通过上面的方法调用,我们也可以获取到设备的 deviceId
,通过 deviceId
便可以指定使用的输入设备。
举个例子,假设我并不想使用电脑中的默认麦克风,而是选择另一个 deviceId
为 cc7f8d6ec7b6764d8ad8b8a737dde5b0a54943816b950bef56c00a289d1180d2
的设备,那么我就可以通过添加下面的约束来手动指定我需要的设备:
navigator.mediaDevices.getUserMedia({
audio: {
deviceId: {
exact: 'cc7f8d6ec7b6764d8ad8b8a737dde5b0a54943816b950bef56c00a289d1180d2',
},
noiseSuppression: true,
echoCancellation: true,
}
}).then((stream) => {
console.log(stream.getTracks());
})
这样我就可以拿到属于这台麦克风的音频流输入。