WebRTC: Web Real-Time Communications, WebRTC允许两个设备之间进行实时,点对点的数据交换. 目前主要应用场景有: 音视频通话, 屏幕共享等
名词
- ICE
Interactive Connectivity Establishment, 交互式连接建立. 用于让两端互相找到对方并建立连接. - NAT
Network Address Translation - STUN
Session Traversal Utilities for NAT, 用来获取用户IP地址 - TURN
Traversal Using Relays around NAT, 在STUN失败的时候使用, 作为中继服务器 - SDP
Session Description Protocol, 是点对点连接的标准 - Signaling(信令)
WebRTC使用RTCPeerConnection在浏览器之间进行流式数据通信,但也需要一种机制来协调通信并发送控制信息,这一过程被称为信令。
主要接口
下面接口使用的都是 navigator.mediaDevices 下的方法, 直接使用navigator的方式已被标记为废弃.
EnumerateDevices
用于获取用户媒体设备信息, 可以获取当前用户环境可用的所有媒体设备列表.
// 可以得到用户的媒体设备信息, 返回用户可用媒体设备列表(输入设备与输出设备)
const devices = await navigator.mediaDevices.enumerateDevices()

每个设备对象都有4个属性
deviceId: 设备id, 在获取媒体流(getUserMedia)时候可以指定设备groupId: 设备组idkind: 设备类型(音频|视频, 输入|输出)label: 设备名称
MediaStream(getUserMedia())
用于获取媒体流(通过媒体设备输入或输出的二进制数据)
使用方法:
navigator.mediaDevices.getUserMedia(constraints):Promise<MediaStream>
下面为老方法: MDN标记已废弃, 不推荐使用
navigator.getUserMedia(constraints, successCallback, errorCallback):void
该方法接收参数constraints为请求媒体设备的设置,其中包含音频轨道(audio) 与 视频轨道(video)设置, 会返回一个包含所请求轨道的媒体流(MediaStream).
音频与视频轨道的通用配置有
deviceId: 使用指定的媒体设备groupId: 使用指定设备组
音视频特定配置如下, 其中每个配置项都支持详细配置与简洁配置
详细配置: 支持期望值(ideal) 与 精准值(extra) 或者 最大(max)最小(min)值配置, 如果请求的精准值系统无法满足则会报错.
简洁配置: 直接指定一个值, 由系统判断来使用最接近这个值的设备.
在不使用extra的情况下, 请求返回的媒体流的各项参数配置并不一定等于你的配置值
在用户环境不满足你所请求的设备要求时, 系统会将你所请求的值设置为系统支持的最大值
音频与视频配置的每个属性的默认值以及可接受配置值可能会根据设备环境的不同而不同.
以下设置的默认值为 2019 Macbook Pro环境下测试结果.
audio
该属性可以直接写 true(全部系统默认设置) 或者对以下某些属性进行单独配置.
autoGainControl:boolean默认true
是否开启音频自动增益(开启后声音会大一些). safari不支持true: 开启false: 关闭
channelCount:number, 默认1
声道数, 支持 max, min 设置. firefox不支持1: 单声道2: 立体声
echoCancellation:boolean,默认true
回声消除(减少回音收集)latency:number, 默认0.01
延迟, 以秒为单位noiseSuppression:boolean, 默认true
噪音抑制(会减少环境声干扰). safari不支持sampleRate:number, 默认48000(48kHz)
音频采样率. firefox不支持sampleSize:number, 默认16(16bit)
音频线性采样大小. firefox不支持
video
width:number
视频宽度height:number
视频高度frameRate:number, 默认30
视频帧数facingMode:string
摄像头'user': 前置摄像头'environment': 后置摄像头
aspectRatio:number
视频宽高比, 比如1920/1080, 也可以直接写计算结果1.7777777777777777
例子
// 获取 1080P 画质 60帧 的音视频媒体流
const stream = await navigator.mediaDevices.getUserMedia({
video: {
width: 1920,
height: 1080,
frameRate: 60,
},
audio: true
})
获取当前环境支持的配置项
我们可以使用 navigator.mediaDevices.getSupportedConstraints() 来获取当前浏览器环境所支持的媒体设置.

获取音视频配置取值范围
也可以使用媒体流(MediaStream)来获取音频或视频轨道, 然后来获取对应音视频配置项的支持范围
const stream = await navigator.mediaDevices.getUserMedia({
video: {
width: 1920,
height: 1080,
frameRate: 60,
},
audio: true
})
// 获取视频轨道
const videoTrack = stream.getVideoTracks()[0]
// 获取音频轨道
const audioTrack = stream.getAudioTracks()[0]
console.log(videoTrack.getCapabilities())
console.log(audioTrack.getCapabilities())


MediaRecorder
十分简单的用来录制媒体的接口.
兼容性问题: Safari 与 Opera 不支持.
使用
构造函数:
const mediaRecorder = new MediaRecorder(MediaStream, [options])
MediaStream: 需要录制的媒体流options: 可选, 可以配置音频和视频的录制码率以及格式
为什么说这是个十分简单的接口, 因为它提供了直观且简单的调用方法来让我们进行音视频录制.
mediaRecorder.start(): 开始录制mediaRecorder.stop(): 停止录制mediaRecorder.pause(): 暂停录制mediaRecorder.resume(): 继续录制mediaRecorder.requestData(): 请求从调用start到调用该方法之间的录制结果, 返回 BlobmediaRecorder.isTypeSupported(mimeType): 判断当前环境是否支持传入的mime类型
该接口也提供了一些便捷的事件
onndataavaliable: 在stop()之后可用, 可以获得录制的媒体数据(Blob)onstart: 开始时调用onstop: 结束时调用onpause: 暂停时调用onresume: 恢复录制时调用onerror: 错误
例子
const videoEl = document.createElement('video')
document.body.appendChild(videoEl)
videoEl.autoplay = true
const mediaStream = navigator.mediaDevices.getUserMedia({ video: true, audio: true })
videoEl.srcObject = mediaStream
const recorder = new MediaRecorder(mediaStream, { type: 'video/webm;codecs=vp9,opus' })
const recordData = []
// 存储录制数据
recorder.ondataavailable = ({ data }) => {
recordData.push(data)
}
recorder.start()
// 录制5s
setTimeout(() => {
recorder.stop()
download()
}, 5 * 1000)
// 下载录制视频
function download () {
const downloadLink = document.createElement('a')
a.download = 'demo.webm'
a.url = URL.createObjectURL(new Blob(recordData, { type: recorder.mimeType }))
a.click()
URL.revokeObjectURL(a.url)
}