webrtc实现
WebRTC APIs
- MediaStream (又称getUserMedia):获取音频和视频
- RTCPeerConnection:进行音频和视频通信
- RTCDataChannel:进行任意数据的通信
实现步骤
1.创建数据源 mediaDevices.getUserMedia
它返回一个Promise对象,成功后会resolve回调一个MediaStream对象。
参数:constraints
constraints 参数是一个包含了video和audio两个成员的MediaStreamConstraints对象
video:true或者对象,对象可以设置更详细的信息
min、max 或者 exact(就是 min == max):强制要求获取特定的尺寸
ideal:应用理想的值(权限更高)
facingMode: “user”:前置摄像头
facingMode: { exact: “environment” }:后置摄像头
代码示例:
// 创建数据源
var localStream = navigator.mediaDevices.getUserMedia({
audio: true,
// 移动设备使用facingMode
video: {
width: { min: 1024, ideal: 1280, max: 1920 },
height: { min: 776, ideal: 720, max: 1080 }
}
})
.then(function(stream) {
/* 使用这个 stream stream */
})
.catch(function(err) {
/* 处理 error */
});
// 显示数据源,localVideo 是 html 中的 video 标签
localVideo.srcObject = localStream;
2.创建发送数据实例RTCPeerConnection
RTCPeerConnection接口代表一个由本地计算机到远端的WebRTC连接。该接口提供了创建,保持,监控,关闭连接的方法的实现
构造方法参数:
iceServers:指定STUN和TURN服务器的数组,用于实现NAT穿越和中继通信。
iceTransportPolicy:指定网络传输协议的首选策略,可以是"all"(尝试使用所有可用的传输方式)或"relay"(只使用中继传输)。
bundlePolicy:指定是否将多个流捆绑在一起,以提高效率。可选值包括"balanced"、“max-compat"和"max-bundle”。
rtcpMuxPolicy:指定是否启用RTP和RTCP复用,以减少带宽消耗和延迟。可选值包括"negotiate"、“require"和"max-compat”。
sdpSemantics:指定SDP协商语义的首选方式,可以是"plan-b"或"unified-plan"。
peerIdentity:指定对等连接的身份验证信息,用于安全目的。
certificates:指定TLS证书链的数组,用于加密和身份验证。
代码示例:
// 本地实例
const pc1 = new RTCPeerConnection();
// 远端实例
const pc2 = new RTCPeerConnection();
3.配置实例
做这一步的目的是为了交换两端的信息:icecandidate和SDP
-
icecandidate:包含通信协议(TCP/UDP)和通信IP,STUN和TURN协议中描述网络信息的格式规范,解决双方网络链接问题;
-
SDP:浏览器能力,包括不限于音视频编码格式,带宽,流控策略等;解决前置思考中,双方能力不匹配问题,通过交换双方 SDP 浏览器会自动选择双方都支持的视频编码格式。
// 告诉对端,本端地址
pc1.addEventListener(‘icecandidate’, async (e) => {
// 发送给对端
// 对端添加本端地址
if (e.candidate) {
await pc2.addIceCandidate(e.candidate);
}
});pc2.addEventListener(‘icecandidate’, async (e) => {
// 发送给本端
// 本端添加对端地址
if (e.candidate) {
await pc1.addIceCandidate(e.candidate);
}
});// 创建本端SDP,告诉本端浏览器支持哪些能力
const offer = await pc1.createOffer();
pc1.setLocalDescription(offer);
// 创建远端SDP,告诉远端浏览器支持哪些能力
const answer = await pc2.createAnswer();
pc2.setLocalDescription(answer);
// 。。。。发送远端SDP给本端
// 接收远端sdp,告诉远端浏览器支持哪些能力
pc1.setRemoteDescription(answer);
// 接收客户端sdp,告诉远端浏览器支持哪些能力
pc2.setRemoteDescription(offer);
4.发送数据
返回一个包含所有轨道的数组,每个轨道都是MediaStreamTrack对象
localStream.getTracks().forEach(
(track) => pc1.addTrack(track, localStream)
);
5.接收远程媒体流
pc2.ontrack = function(event) {
var pc2Stream = event.streams[0];
// 处理远程媒体流
};
6.发送消息createDataChannel或send
在创建数据通道之前需要先建立连接,并确保对等方也已经创建了数据通道以接收消息。
createDataChannel参数:
label:数据通道的名称,用于唯一标识该通道。通常是一个字符串。
options(可选):用于指定一些可选的配置项,例如设置 ordered(是否保证消息的有序传输,默认为 true)和 maxPacketLifeTime(最大包存活时间)等。
// 步骤 1:创建数据通道
// 使用createDataChannel方法在本地PeerConnection对象上创建一个数据通道
var dataChannel = pc1.createDataChannel("myDataChannel");
dataChannel.onopen = function() {
console.log('数据通道已打开');
};
// 步骤 2:设置消息处理程序
// 通过为dataChannel对象添加相应的事件处理程序来监听消息的收发
dataChannel.onmessage = function(event) {
var receivedMessage = event.data;
console.log('接收到的消息:', receivedMessage);
};
// 步骤 3:发送消息
// 使用send方法将消息发送给对等方
var messageToSend = "Hello, world!";
dataChannel.send(messageToSend);