采集音视频数据
通过 enumerateDevices()
接口获得音视频设备后,就可以选择其中的设备进行数据采集了。在浏览器下采集音视频数据也很方便,调用 getUserMedia()
这个 API
就可以采集到。getUserMedia
的接口格式如代码 5.4 所示。
navigator.mediaDevices.getUserMedia(MediaStreamConstrains);
该接口有一个 MediaStreamConstrains
类型的输入参数,可以用来控制从哪个设备上采集音视频数据,以及限制采集到的数据的格式,如限制采集到的视频分辨率、音频数据的采样率、采样大小等。其结构如代码 5.5 所示。
dictionary MediaStreamConstrains {
(boolean) or (MediaTrackConstrains) video = false;
(boolean) or (MediaTrackConstrains) audio = false;
}
从上面 MediaStreamConstrains
类型的定义可以看出,video
和 audio
属性既可以是 boolean
类型,也可以是 MediaTrackConstrains
类型(只有像 JavaScript
这种弱类型语言才可以做这一点)。因此,我们既可以直接给 video
和 audio
赋值 true/false
,简单地指明是否采集视频或音频数据,也可以给它赋值一个 MediaTrackConstrains
类型的值,对音视频设备做更精准的设置。
如果直接给 video/audio
属性赋值 true
,则浏览器会使用默认设备和默认参数采集音视频数据,否则如果给 video/audio
赋值 MediaTrackConstrains
类型值,则浏览器会按 MediaTrackConstrains
中的限制,从指定的设备中采集音视频数据。MediaTrackConstrains
结构如代码 5.6 所示。
dictionary MediaTrackConstraintSet {
// 视频相关
ConstrainULong width;
ConstrainULong height;
ConstrainDouble aspectRatio; // 宽高比
ConstrainDouble frameRate;
ConstrainDOMString facingMode; // 前置/后置摄像头
ConstrainDOMString resizeMode; // 缩放或裁剪
// 音频相关
ConstrainULong sampleRate;
ConstrainULong sampleSize;
ConstrainBoolean echoCancellation;
ConstrainBoolean autoGainControl;
ConstrainBoolean noiseSuppression;
ConstrainDouble latency; // 目标延迟
ConstrainULong channelCount;
// 设备相关
ConstrainDOMString deviceId;
ConstrainDOMString groupId;
};
从上面的代码片段中可以看到,MediaTrackConstrains
结构由三部分组成,即视频相关属性、音频相关属性以及设备相关属性。视频属性中包括分辨率、视频宽高比、帧率、前置/后置摄像头、视频缩放;音频属性包括采样率、采样大小、是否开启回音消除、是否开启自动增益、是否开启降噪、目标延迟、声道数;设备相关属性包括设备ID、设备组ID。
我们来看一个具体的例子,看看如何通过 getUserMedia()
接口来采集音视频数据。具体代码参见代码 5.7。
// 采集到某路流
function gotMediaStream(stream) {
// ...
}
// 从设备选项栏里选择某个设备
var deviceId = xxx;
// 设置采集限制
var constraints = {
video: {
width: 640,
height: 480,
frameRate: 15,
facingMode: 'environment',
deviceId: deviceId ? { exact: deviceId } : undefined
},
audio: false
};
// 开始采集数据
navigator.mediaDevices.getUserMedia(constraints)
.then(gotMediaStream)
.catch(handleError);
// ...
在上面的代码片段中,首先执行第 22 行代码,即调用 getUserMedia()
接口,然后根据 constraints
中的限制获取音视频数据。在这个例子中,getUserMedia()
从指定设备(deviceId
)上按指定参数采集视频数据,具体参数如下:分辨率为 640×480、帧率为 15 帧/秒、使用后置摄像头(environment
)。因为 audio
属性为 false
,所以此例中仅采集视频数据而不采集音频数据。
此外,从上面的代码中还可以看到,调用 getUserMedia()
接口的方式与调用 enumerateDevices()
接口的方式是一样的,也是使用 Promise
方式。当调用 getUserMedia()
成功时,会回调 gotMediaStream()
函数,该函数的输入参数 MediaStream
里存放的就是音视频数据流。当获得音视频数据后,既可以把它作为本地预览,也可以将它传送给远端,从而实现一对一通信。如果调用 getUserMedia()
接口失败,则调用错误处理函数 handleError
。