WebRTC实战P2P音视频通话解决方案
1、简介
本文将详细介绍如何利用 WebRTC 技术实现 P2P 音视频通话,并提供了一个跨平台的方案,包括:基于 socket.io 和 Node.js 实现的服务端,以及 JavaScript 和 Android 客户端。让我们一起来探讨如何搭建这个系统,以及如何编写代码吧。
由于 server 、js、android 代码还在整理中,预计还需要 2-3 天时间。地址:github.com/yangkun1992…
下面是 PC 与 IOS 在不同网络环境下的效果图(WiFi <->移动网络):
2、服务端2.1 使用 nodejs 和 socket.io 实现信令服务器
我们借助上一篇信令服务的流程图,来实现一个 nodejs 信令服务器
我们先设计一个信令
join: 当前用户和远端用户加入到房间中的信令
leave: 当前用户和远端用户离开房间的信令
message: 交换双方的 SDP、ICE 信令
首先,我们需要搭建一个 Node.js 服务端,用于处理信令交换。在这里,我们将使用 socket.io 库作为通信协议,借助 http、https、fs 等组件。实现一个简单的 Node.js 服务端实例:
create server.js 下面就是信令服务的核心代码 var log4js = require("log4js"); var http = require("http"); var https = require("https"); var fs = require("fs"); var socketIo = require("socket.io"); var express = require("express"); var serveIndex = require("serve-index"); var USERCOUNT = 3; ... //http server var http_server = http.createServer(app); http_server.listen(80, "0.0.0.0"); var options = { key : fs.readFileSync("./cert/xxx.key"), cert: fs.readFileSync("./cert/xxx.pem") } //https server var https_server = https.createServer(options, app); var io = socketIo.listen(https_server); io.sockets.on("connection", (socket)=> { socket.on("message", (room, data)=>{ socket.to(room).emit("message",room, data);//发送给当前房间的其它客户端 }); socket.on("join", (room)=>{ socket.join(room); var myRoom = io.sockets.adapter.rooms[room]; var users = (myRoom)? Object.keys(myRoom.sockets).length : 0; logger.debug("the user number of room is: " + users); if(users < USERCOUNT){ socket.emit("joined", room, socket.id); //发送给自己,相当于回调 if(users > 1){ socket.to(room).emit("otherjoin", room, socket.id); //发送给当前房间的其它客户端 } }else{ socket.leave(room); socket.emit("full", room, socket.id); } }); socket.on("leave", (room)=>{ var myRoom = io.sockets.adapter.rooms[room]; var users = (myRoom)? Object.keys(myRoom.sockets).length : 0; logger.debug("the user number of room is: " + (users-1)); socket.to(room).emit("bye", room, socket.id); socket.emit("leaved", room, socket.id); }); }); https_server.listen(443, "0.0.0.0");
要运行上面的 server.js 信令服务器,您需要按照以下步骤进行安装和运行: 安装 Node.js 和 npm: 安装所需的依赖项 npm install express socket.io fs http https启动 server node server.js2.2 搭建 sturn/turn 服务器
由于网络环境的影响我们需要搭建一个 sturn/turn 服务器,以便提升 P2P 的成功率,下面是一个粗略的搭建方式,但是也够用了。 安装 Coturn
在终端中输入以下命令,使用 yum 包管理器安装 Coturn: sudo yum install coturn配置 Coturn
找到并编辑 Coturn 的配置文件 /etc/coturn/turnserver.conf ,根据您的需求修改以下配置项: # 配置监听的端口号 listening-port=3478 min-port=49152 max-port=65535 #配置域名 realm=xxx.com #允许使用 TURN/STUN 服务的用户的凭据 user=123456:123456 cert=/path/to/xxx.pem pkey=/path/to/xxx.pem # 配置日志文件路径 log-file=/root/log/turnserver.log启动 Coturn
在终端中输入以下命令,启动 Coturn 服务: sudo systemctl start coturn sudo systemctl stop coturn sudo systemctl restart coturn sudo systemctl status coturn测试 coturn 我们可以去 trickle-ice 测试网站进行测试
正如 trickle-ice 网站所说: 如果你测试一个 STUN 服务器,你能收集到一个类型为"srflx"的候选者,它就可以工作。如果你测试一个 TURN 服务器,你能收集到一个类型为"relay"的候选人,它就会工作.
由此上图 sturn 和 turn 候选者地址都能成功连接。
C++音视频学习资料免费获取方法:关注音视频开发T哥 ,点击「链接」即可免费获取2023年最新 C++音视频开发进阶独家免费学习大礼包! 3、客户端
WebRTC 是一种基于 Web 技术的实时通信解决方案,可用于在浏览器中实现P2P音视频通话。当然,现在基本上所有上层平台都支持了。在 WebRTC 中,双方通信通过 ICE 协议进行连接,通过 SDP 协议交换媒体信息,通过 DTLS 协议进行加密,通过 SRTP 协议进行媒体传输。
下面,我们将为你介绍如何使用 WebRTC 在浏览器和 Android 中实现 P2P 音视频通话。 3.1 Web
我们按照上面信令的流程来实现: 3.1.1 获取媒体流
WebRTC 支持从设备摄像头和麦克风获取视频和音频流。使用 JavaScript 的 getUserMedia API,您可以请求用户授权,从摄像头和麦克风获取本地媒体流,并将其添加到一个 MediaStream 对象中。 function startCall(){ if(!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia){ console.error("the getUserMedia is not supported!"); return; }else { var constraints = { video: true, //传输视频 audio: true //传输音频 } navigator.mediaDevices.getUserMedia(constraints) .then(getMediaStream)//打开成功的回调 .catch(handleError);//打开失败 } }3.1.2 连接信令服务器并加入到房间中function connect(){ //连接信令服务器 socket = io.connect(); //加入成功的通知 socket.on("joined", (roomid, id) => { ... }); //远端加入 socket.on("otherjoin", (roomid) => { ... }); //房间满了 socket.on("full", (roomid, id) => { ... }); //接收自己离开房间的回调 socket.on("leaved", (roomid, id) => { ... }); //收到对方挂断的消息 socket.on("bye", (room, id) => { ... }); //收到服务断开的消息 socket.on("disconnect", (socket) => { ... }); //收消息,用于交换 SDP 和 ICE 消息等 socket.on("message", (roomid, data) => { ... }); //发送 join 消息到信令服务器并加入到 123456 房间中 socket.emit("join", 123456); }3.1.3 创建 PeerConnection 并添加媒体轨道
当收到自己加入房间成功的消息后,连接到远程对等方,我们就需要创建一个 RTCPeerConnection 对象,并将本地媒体流添加到其中。然后,您需要创建一个 RTCDataChannel 对象,用于在对等方之间传输数据。 var pcConfig = { "iceServers": [{ "urls": "turn:xxx:3478", "credential": "1234", "username": "1234" }] }; pc = new RTCPeerConnection(pcConfig); //当前 icecandida 数据 pc.onicecandidate = (e)=>{ ... } //datachannel 传输通道 pc.ondatachannel = e=> { ... } // 添加远端的媒体流到