-
Notifications
You must be signed in to change notification settings - Fork 1
Description
WebRTC
WebRTC(Web Real Time Communication)即“网络实时通信”,它最初是为了解决浏览器上视频通话而提出的,即两个浏览器之间直接进行视频和音频的通信,不经过服务器。后来发展到除了音频和视频,还可以传输文字和其他数据。
获取音频和视频
MediaDevices.getUserMedia()
MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个 MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其它轨道类型。
const constraints: MediaStreamConstraints = { audio: true, audio: true };
const $video: HTMLVideoElement;
navigator.mediaDevices.getUserMedia(constraints).then(
(stream: MediaStream) => {
$video.srcObject = stream;
// 或者
$video.src = URL.createObjectURL(stream);
},
(err) => {
// PermissionDeniedError / NotFoundError
}
);其中 audio、audio 均为 MediaTrackConstraints,可以通过指定 deviceId 来使用指定的设备。
MediaDevices.enumerateDevices()
通过 enumerateDevices 就可获取到不同设备的基本信息。
navigator.mediaDevices.enumerateDevices().then((devices: MediaDeviceInfo[]) => {
devices.forEach(({ deviceId, label, kind }) => {
switch (kind) {
case 'audioinput': // 麦克风
case 'videoinput': // 摄像头
case 'audiooutput': // 外放
default:
break;
}
});
});MediaDevices.getDisplayMedia()
navigator.mediaDevices.getDisplayMedia 和 navigator.mediaDevices.getUserMedia 使用方法类似,返回一个窗口内容的 MediaStream。
通过上述方方法获取到 媒体流,可以借助 canvas 来实现拍照/截屏:
async function snapshot(
stream: MediaStream,
ctx: CanvasRenderingContext2D,
video: HTMLVideoElement
) {
video.autoplay = true;
video.srcObject = stream;
await new Promise((resolve, reject) => {
video.onload = resolve;
video.onerror = reject;
});
ctx.drawImage(video, 0, 0);
const $link = document.createElement('a');
$link.download = ctx.canvas.toDataURL('image/webp');
$link.click();
}RTC 通信
使用补充库 Adapter.js 可以抹平浏览器之间的差异。
RTCPeerConnection
RTCPeerConnection 接口代表一个由本地计算机到远端的 WebRTC 连接。该接口提供了创建,保持,监控,关闭连接的方法的实现。
// 这里使用 WebSocket 通信作为例子
let ws: WebSocket, pc: RTCPeerConnection;
async function start(stream: MediaStream, configuration?: RTCConfiguration) {
pc = new RTCPeerConnection(configuration);
pc.onicecandidate = (evt) => {
const { candidate } = evt;
ws.send(JSON.stringify({ candidate }));
};
stream.getTracks().forEach((track) => pc.addTrack(track, stream));
// send
const sdp = await pc.createOffer();
// recv
// const sdp = await pc.createAnswer()
await pc.setLocalDescription(sdp);
ws.send(JSON.stringify({ sdp }));
}
ws.onmessage = (e) => {
const data = JSON.parse(e.data);
pc.addIceCandidate(new RTCIceCandidate(data.candidate));
// recv
pc.setRemoteDescription(new RTCSessionDescription(data.sdp));
};iceServers 可以使用 https://github.com/DamonOehlman/freeice 来提供。
RTCDataChannel
RTCDataChannel 接口代表在两者之间建立了一个双向数据通道的连接。与 WebSocket 类似。
https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel