当前位置: 首页 > ai >正文

SRS流媒体服务器(3)视频通话环境搭建和源码分析

1. 概述

        本文档介绍如何通过SRS 4.0搭建 WebRTC视频通话环境,涵盖环境配置、服务器编译启动、逻辑分析及测试方法。SRS 源码包提供了信令服务器以及显示UI静态web页面分别在3rdparty/signaling 3rdparty/httpx-static。信令服务器是基于go语言编写,所以需要搭建go环境。

2. 环境搭建

2.1 安装go语⾔环境

#下载安装包
cd /usr/local/
wget https://dl.google.com/go/go1.16.5.linux-amd64.tar.gz --no-check-certificate
tar -C /usr/local -xzf go1.16.5.linux-amd64.tar.gz#配置环境变量
vim /etc/profile
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
source /etc/profile

2.2 编译启动 SRS 流媒体服务器 

编译可参考SRS流媒体服务器(1)概述和环境搭建-CSDN博客


#vim conf/rtc.conf 
rtc_server {enabled on;listen 8000; #改成自己云服务器ipcandidate xxx.81;
}# 启动 SRS
./objs/srs -c conf/rtc.conf  

2.3 编译启动信令服务器 

cd 3rdparty/signaling
make && ./objs/signaling  # 默认端口 1989

2.4 编译启动 Web 服务器(支持 HTTPS/WSS)

#编译
cd 3rdparty/httpx-static
make
#生成 SSL 证书
openssl genrsa -out server.key 2048
openssl req -new -x509 -key server.key -out server.crt -days 3650
#启动
./objs/httpx-static -http 80 -https 443 -ssk server.key -ssc server.crt \--proxy http://127.0.0.1:1989/sig \--proxy http://127.0.0.1:1985/rtc \--proxy http://127.0.0.1:8080/

3. 测试方法

访问以下 URL 进行测试(替换 localhost 为实际 IP):

  1. https://localhost/demos/

  2. https://192.168.3.6/demos/

3.1 排查失败之云服务器端口开放 

   当你在公网部署且访问一直在转圈失败,连摄像头都无法打开,那可能是端口未开放。这里排查了很久,居然需要打开3306这个端口!以及8000(rtp配置文件端口)

除此之外SRS 流媒体服务器其他端口说明如图:

 4. 源码分析

入口代码 one2one.html:297 $("#btn_start").click(startDemo);

SrsRtcSignalingParse:

  1. 解析出连接信令服务器的地址
  2. 房间号:可填或随机
  3. 显示名:可填或随机
  4. 主机

拉流和推流函数对象主要做:

  • 1.确定协议
  • 2.addtrack
  • 3. offer/answer协商
  • 5.RTCPeerConnection  
  • 6.parseUrl xxx + '/rtc/v1/play/  如: 'https://117.72.13.81:443/rtc/v1/push or play/'
	var startDemo = async function () {sig = new SrsRtcSignalingAsync();   //srs.sig.js:28  创建SrsRtcSignalingAsync,RTC信令sig.onmessage = function (msg) {    //onmessage订阅新的信令消息console.log('Notify: ', msg);if (msg.event === 'leave') {$('#player').hide();}if (msg.event === 'publish') {//房间已经存在的参与者,收到publish信令后再去订阅新加入者if (msg.peer && msg.peer.publishing && msg.peer.display !== display) {startPlay(host, room, msg.peer.display);}}};await sig.connect(conf.wsSchema, conf.wsHost, room, display);//连接websock,见下面SrsRtcSignalingAsync代码let r0 = await sig.send({action:'join', room:room, display:display}); //向信令服务器发送join信令,会返回房间列表。console.log('Signaling: join ok', r0);// 对于一对一演示,当房间已满时发出警报并忽略。if (r0.participants.length > 2) {alert('Room is full, already ' + (r0.participants.length - 1) + ' participants');sig.close();return;}// 如果信令正常,开始推流await startPublish(host, room, display);     //向srs流媒体服务器开始推流let r1 = await sig.send({action:'publish', room:room, display:display}); //向信令服务器发送publish信令console.log('Signaling: publish ok', r1);// 拉其他人的流r0.participants.forEach(function(participant) {if (participant.display === display || !participant.publishing) return;startPlay(host, room, participant.display);// 对于新进的房间,会拉取房间内另一个人的流});if (r0.participants.length >= 2) {$('.srs_merge').show();}};var startPublish = function (host, room, display) {$(".ff_first").each(function(i,e) {$(e).text(display);});var url = 'webrtc://' + host + '/' + room + '/' + display + conf.query;$('#rtc_media_publisher').show();$('#publisher').show();if (publisher) {publisher.close();}publisher = new SrsRtcPublisherAsync(); //创建RTC异步推流 srs.sdk.js:20 与下文类似$('#rtc_media_publisher').prop('srcObject', publisher.stream);};var startPlay = function (host, room, display) { //向srs服务器拉流$(".ff_second").each(function(i,e) {$(e).text(display);});//拼接url "webrtc://117.72.13.81/63838c2/1907a7c",其中webrtc://是协议头,"117.72.13.81"是srs服务器ip,"63838c2"是房间号,"1907a7c"是参与者昵称var url = 'webrtc://' + host + '/' + room + '/' + display + conf.query;$('#rtc_media_player').show();$('#player').show();if (player) {player.close();}player = new SrsRtcPlayerAsync();//创建RTC异步拉流 srs.sdk.js:278 1.确定协议 2.addtrack 3. offer/answer协商 5.RTCPeerConnection  6.parseUrl xxx + '/rtc/v1/play/  如: 'https://117.72.13.81:443/rtc/v1/publish/',$('#rtc_media_player').prop('srcObject', player.stream);};// Pass-by to SRS url. 用于解析出连接信令服务器的地址let conf = SrsRtcSignalingParse(window.location);$("#btn_start").click(startDemo);// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732if (conf.autostart) {window.addEventListener("load", function(){ startDemo(); });}
});

 SrsRtcSignalingAsync 信令函数对象主要做:

  1. connect:连接信令服务器 wss://xxxx/sig/v1/rtc
  2. onmessage:处理接收到的消息
  3. send : 把对象序列化后发送到服务器
  4. close: 关闭
    function SrsRtcSignalingAsync() { //信令函数var self = {};// The schema is ws or wss, host is ip or ip:port, display is nickname// of user to join the room.self.connect = async function (schema, host, room, display) {var url = schema + '://' + host + '/sig/v1/rtc'; //如:api:"wss://117.72.13.81/sig/v1/rtc"self.ws = new WebSocket(url + '?room=' + room + '&display=' + display); //与url建立连接 参数:房间号,昵称self.ws.onmessage = function(event) { //收到消息的处理函数var r = JSON.parse(event.data);var promise = self._internals.msgs[r.tid];if (promise) {promise.resolve(r.msg);delete self._internals.msgs[r.tid];} else {self.onmessage(r.msg);}};};//消息是一个json对象。self.send = async function (message) {return new Promise(function (resolve, reject) {var r = {tid: Number(parseInt(new Date().getTime()*Math.random()*100)).toString(16).substr(0, 7), msg: message};self._internals.msgs[r.tid] = {resolve: resolve, reject: reject};self.ws.send(JSON.stringify(r));});};self.close = function () {self.ws && self.ws.close();self.ws = null;for (const tid in self._internals.msgs) {var promise = self._internals.msgs[tid];promise.reject('close');}};return self;
    }

    4.1 总体流程

    学习资料分享

    40voice · GitHub

    http://www.xdnf.cn/news/4383.html

    相关文章:

  • 使用 Vue CLI 和 vuedraggable 实现拖拽排序功能
  • 深度学习赋能:正面吊车载箱号识别系统的核心技术
  • 电子电器架构 --- 48V架构的一丢丢事情
  • 排序算法——计数排序
  • RabbitMQ高级特性
  • RabbitMQ-springboot开发-应用通信
  • 技术分享:Franka机器人新方案——双臂数据采集与适应性安装,带你探索具身智能的奥秘
  • 【温湿度物联网】记录1:寄存器配置
  • RTC实时时钟DS1337S/PT7C4337WEX国产替代FRTC1337S
  • 关于大疆红外图片提取温度方法 python 方法
  • C++ std::sort 函数
  • JC/T 2187-2013 铝波纹芯复合铝板检测
  • 【MySQL】C语言访问数据库
  • 第5讲、Transformer 编码器(Encoder)处理过程详解
  • 世界无人机大会将至,大势智慧以“AI+实景三维”赋能低空经济
  • 从创意到变现:独立创造者的破局之路——解码《Make:独立创造者手册》
  • PyCharm连接WSL2搭建的Python开发环境
  • Kepware 连接Modbus TCP/IP
  • 上海雏鸟科技再赴越南,助力10518架无人机刷新吉尼斯记录
  • MySQL优化-MySQL常见的锁机制
  • 报表的那些事:四部演进史——架构视角下的技术跃迁与实战思考
  • 高防ip是怎么做到分布式防御的
  • 如何用命令行判断一个exe是不是c#wpf开发的
  • win11指定Microsoft Print To PDF的输出路径(电子书djvu转pdf输出路径)
  • dify 部署后docker 配置文件修改
  • docker host模式问题
  • 使用Milvus向量数据库构建具有长期记忆的对话机器人
  • Flowchart 流程图的基本用法
  • 基于OpenTelemetry的分布式链路追踪Trace‌实现(PHP篇)
  • androidStudio里gradle过滤冲突资源文件