mediasoup是一个开源的WebRTC SFU服务器实现,同时也提供了客户端的WebRTC SDK,相当于一个从前到后完整的WebRTC项目,同时该项目在代码设计和性能上比较优秀,有些公司在启动RTC项目时会直接基于mediasoup开发,省去了从0到1的过程。
mediasoup也是学习入门WebRTC的优秀的项目,而且从前到后一条龙学到底,本文会说明mediasoup项目本地调试环境的搭建。
使用到的工具与环境为:
-
Windows操作系统
-
nodejs v18.19.1
-
python v3.12.2
-
visual studio 社区版即可
本文不会普及WebRTC相关的概念,0基础可以先看这篇文章:从前端视角从0认识Web实时通讯 - 掘金
一、mediasoup项目介绍
mediasoup主要提供了三个github项目,下面括号里为写文档时对应的commit_id,分别为:
-
mediasoup(8d757bc): SFU的核心实现,c++负责实现连接建立,流媒体转发等模块,是最核心的模块;nodejs是c++程序对外暴露的API,同时也提供了rust版本的API(这个不在本文讨论范围内);
-
mediasoup-client(390ed87): mediasoup在浏览器Web侧对应的SDK实现,主要提供了transport/producer/consumer/不同版本浏览器pc处理的handler,但是不提供信令连接,需要业务层自行实现;
-
mediasoup-demo(cfe014a): 使用mediasoup实现的一个简单的会议系统,里面包括了前端(React)和后端信令(nodejs)的实现,前后端程序又分别引用了mediasoup-client和mediasoup项目
二、跑通mediasoup Demo
首先clone mediasoup-demo项目,目录结构如下:
vbscript
.
├─app 前端程序
├─server 后端程序
2.1 前端程序
- yarn
- yarn start
顺利的话就可以启动前端项目了,打开 https://localhost:3000/,但还没有后端服务,所以还不能使用
2.2 后端程序
接下来去启动后端服务
- yarn 安装依赖,这个过程中会下载mediasoup项目,并编译mediasoup项目到server/node_modules/mediasoup/worker/out/Release/mediasoup-worker.exe,最后会在nodejs服务里调用这个exe
- 项目启动需要一个config.js配置文件,但项目只提供了一个config.example.js,直接复制+改成config.js,里面的内容不需要动
- 项目需要https和dtls加密,因此需要自签一个证书,调用openssl生成证书(我是在linux环境生成的):
csharp
openssl req -new -newkey rsa:1024 -x509 -sha256 -days 3650 -nodes -out fullchain.pem -keyout privkey.pem
将生成的fullchain.pem和privkey.pem复制到 server/certs目录
- 修改一下process.env.MEDIASOUP_LISTEN_IP的环境变量,这个是ice连接的IP,直接填成本机的ipv4地址即可,可以使用ipconfig/ifconfig命令手动查看,或者让写段代码让nodejs自己识别一下地址,在server里引入执行一下(lint规则有点特殊,如果有lint问题,直接使用eslint --fix自动修复下)
ini
function getIPAdress()
{
const interfaces = require('os').networkInterfaces();
for (const devName in interfaces)
{
if (interfaces.hasOwnProperty(devName))
{
const iface = interfaces[devName];
for (let i = 0; i < iface.length; i++)
{
const alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal)
{
return alias.address;
}
}
}
}
}
function initProcessEnv()
{
process.env.MEDIASOUP_LISTEN_IP = getIPAdress();
}
module.exports = initProcessEnv;
- yarn start启动项目
回到浏览器,正常的话就可以看到连接成功,并有数据变化
三、搭建nodejs/c++调试环境
3.1 nodejs调试
虽然vscode/webstorm也可以调试nodejs程序,但总感觉没有Chrome浏览器方便,因此我们主要使用Chrome来调试,方法可以将server/package.json里的start命令稍微修改下:
json
"start": "node --inspect=8888 server.js",
运行命令后,去Chrome浏览器打开:chrome://inspect/#devices
打开Open dedicated DevTools for Node,配上本地的8888端口,然后稍等片刻就能看到inspect按钮,打开后就可以愉快地给代码打断点了。
3.2 c++程序调试
首先我们要下载mediasoup项目,然后自己编译一个Debug版本,因为只有Debug版本才会生成pdb文件,在vs里配置好pdb后才能愉快地打断点。
- 编译Debug版本
在package.json里已经配置好了编译的脚本,因此不需要做什么额外的工作,只是需要将python环境里有MEDIASOUP_BUILDTYPE 改为Debug字符串,如果不改环境变量就直接改task.py
里的这行:
ini
MEDIASOUP_BUILDTYPE = os.getenv('MEDIASOUP_BUILDTYPE') or 'Debug';
改完之后就开始编译
json
"worker:build": "node npm-scripts.mjs worker:build",
编译过程中遇到一个问题,是python里的PTY 错误,查了半天没有搞定,然后看到task.py里有个PTY_SUPPORTED = sys.stdout.isatty();
根据系统能力探测,可能是探测支持,但实际又有什么问题,索性把PTY_SUPPORTED改为False,结果跑通。
编译完成的程序在 mediasoup/worker/out/Debug/mediasoup-worker.exe,pdb文件在mediasoup/worker/out/Debug/build/mediasoup-worker.pdb
- 把demo的mediasoup-worker程序换成上步打包的产物
这个在nodejs程序里也有环境变量,使用的话是在mediaosup/node/src/Worker.ts里,如果有环境变量优先使用环境变量
arduino
export const workerBin = process.env.MEDIASOUP_WORKER_BIN
? process.env.MEDIASOUP_WORKER_BIN
: process.env.MEDIASOUP_BUILDTYPE === 'Debug'
? path.join(
__dirname,
'..',
'..',
'worker',
'out',
'Debug',
'mediasoup-worker'
)
: path.join(
__dirname,
'..',
'..',
'worker',
'out',
'Release',
'mediasoup-worker'
);
因此我们在上步指定IP的位置再加一行代码:
ini
process.env.MEDIASOUP_WORKER_BIN = 'D:\...\mediasoup\worker\out\Debug\mediasoup-worker.exe';
重新运行命令,看下我们自己编译的worker是否运行正常。
- 在vs里配置调试环境
上步使用我们自己编译的exe是为了让编译出来的pdb和exe配套,下面在vs里配置pdb,打开工具-选项-符号,在右侧添加pdb的目录(注意是目录,不是pdb文件),配置完点击确定
在程序运行的前提下,打开调试-附加到进程,在里面过滤mediasoup,找到程序后点击附加
随便打个断点测试下,生效!断点要打开源码的位置,即vs打开mediasoup项目,附加进程后,添加断点没有黄色的叹号就是成功。