什么是webrtc?
借助 WebRTC,您可以将实时通信功能添加到基于开放标准运行的应用程序。它支持在对等点之间发送视频、语音和通用数据,允许开发人员构建强大的语音和视频通信解决方案.
重点: 点对点发送视频、语音和数据。
如何在浏览器中使用webrtc?
浏览器中可以通过一下方法判断当前浏览器是否支持webrtc
window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection
简单的Demo
先从最简单的例子开始,我们在一个网页中,通过两个RTCPeerConnection对象来建立一个连接,一个RTCPeerConnection(pc_pub)对象发送视频和语音,另一个RTCPeerConnection(pc_sub)对象接收视频和语音。
效果
此处使用了Safri的虚拟摄像头。可以避免使用真实摄像头还要露脸的尴尬。可以看到左侧是本地采集的画面,右侧是接收到的视频画面。中间有大概几十毫秒的延迟。
流程
sequenceDiagram
Note left of 页面 : 点击打开本地摄像头
页面 ->> 页面: 获取摄像头,并显示
Note left of 页面 : 点击建立连接
pc_pub ->> pc_pub: addEventListener,监听icecandidate
pc_sub ->> pc_sub: addEventListener,监听icecandidate
pc_sub ->> pc_sub: addEventListener,监听track
Note left of pc_pub : 对推流的PeerConnection添加要推流的内容
pc_pub ->> pc_pub: addTrack
Note left of pc_pub : 生成offer
pc_pub ->> pc_pub: createOffer,得到offer
Note left of pc_pub : 将offer的内容设置到浏览器中
pc_pub ->> pc_pub: setLocalDescription,设置offer
Note left of pc_sub : 订阅的PeerConnection将推流的Peerconnection的offer设置到浏览器中
pc_pub ->> pc_sub: setRemoteDescription,设置offer
Note left of pc_sub : 订阅的Peerconnection生成Answer
pc_sub ->> pc_sub: createAnswer,得到answer
Note left of pc_sub : 订阅的Peerconnection将Answer设置到浏览器中
pc_sub ->> pc_sub: setLocalDescription,设置answer
Note left of pc_sub : 推流的Peerconnection将Answer设置到浏览器中
pc_sub ->> pc_pub: setRemoteDescription,设置answer
在上面的流程图中,pub_pc表示推流的对象(PeerConnection), sub_pc表示订阅的对象(PeerConnection)。
-
通过getUserMedia方法来请求使用本地设备,更多关于获取设备的方法可以参考# 获取浏览器麦克风、摄像头和屏幕共享(一)
-
左侧的VideoElement只是用来显示推流内容(本地预览),是否显示都不影响推流效果。
总结
先尝试跑通这个简单的Demo,可以看从页面中看到本地预览、推拉流的效果。如果你是第一次接触webrtc,上面的流程中有很多看不懂的名字和方法可以先忽略它们。
代码
可以直接从gittee获取源代码,也可以直接使用下面的代码
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>webrtc连接</title>
</head>
<body>
<video id="localStream" style="width: 320px; height: 240px;" autoplay muted></video>
<video id="remoteStream" style="width: 320px; height: 240px;" autoplay muted> </video>
<button id="deviceBtn">打开本地摄像头</button>
<button id="startBtn">建立连接</button>
<script>
let localStream = null;
let localVideo = document.getElementById("localStream");
let remoteVideo = document.getElementById("remoteStream")
let deviceBtn = document.getElementById("deviceBtn");
let startBtn = document.getElementById("startBtn");
let pc_pub = new RTCPeerConnection();
let pc_sub = new RTCPeerConnection();
deviceBtn.addEventListener("click", () => {
navigator.mediaDevices.getUserMedia({ video: true }).then((mediastream) => {
localStream = mediastream;
localVideo.srcObject = mediastream;
})
})
startBtn.addEventListener("click", () => {
pc_pub.addTrack(localStream.getVideoTracks()[0], localStream);
pc_pub.createOffer().then((offer) => {
pc_pub.setLocalDescription(offer).then(() => {
pc_sub.setRemoteDescription(offer).then(() => {
pc_sub.createAnswer().then((answer) => {
pc_sub.setLocalDescription(answer).then(() => {
pc_pub.setRemoteDescription(answer).then(() => {
})
})
})
})
})
})
})
pc_pub.addEventListener('icecandidate', (event) => {
if (event.candidate) {
pc_sub.addIceCandidate(event.candidate);
}
})
pc_sub.addEventListener('icecandidate', (event) => {
if (event.candidate) {
pc_pub.addIceCandidate(event.candidate);
}
})
pc_sub.addEventListener('track', (event) => {
remoteVideo.srcObject = event.streams[0];
})
</script>
</body>
其他
如果你也是专注前端多媒体或者对前端多媒体感兴趣,可以关注前端多媒体公众号