WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点的连接,实现视频流和音频流或者其他任意数据的传输。使用WebRTC完成音视频通话需要了解四个模块:音视频采集、STUN/TURN 服务器、信令服务器、端与端之间 P2P 连接,本文主要介绍使用 WebRTC 的 API 完成音视频采集。
获取可用的音视频设备
获取音视频设备可以使用enumerateDevices
API,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中有两个重要的概念,即MediaStream
和MediaStreamTrack
。MediaStreamTrack
称为“轨”,表示单一类型的媒体源,比如从摄像头采集到的视频数据就是一个MediaStreamTrack
,而从麦克风采集的音频又是另外一个MediaStreamTrack
。MediaStreamTrack
中包含如下属性:
enabled
,布尔值,为 true 时表示轨道有效,并且可以被渲染。为 false 时表示轨道失效,只能被渲染为静音或黑屏。id
,轨道的唯一标识。kind
,轨道的类型,如果为“audio”表示轨道为音频轨道,为“video”则为视频轨道。readyState
,表示轨道的当前状态。”live”表示当前输入已经连接并且在尽力提供实时数据。在这种情况下,输出数据可以通过操作 MediaStreamTrack.enabled 属性进行开关。“ended”表示这个输出连接没有更多的数据了,而且也不会提供更多的数据了。
MediaStream
称为“流”,它可以包括0个或多个MediaStreamTrack
。MediaStream
有两个重要作用,一是可以作为录制或者渲染的源,可以将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 举报,一经查实,本站将立刻删除。