首页 > 其他分享 >WebRTC学习记录以及以Janus-gateway流程增进理解

WebRTC学习记录以及以Janus-gateway流程增进理解

时间:2023-04-14 12:33:35浏览次数:51  
标签:插件 handle Janus ice gateway janus session WebRTC 客户端

这篇文章是我按照我的学习习惯记录的文章,借鉴了许多大佬的学习框架,以及独自去验证正确性的一个过程
Web 实时通信(Real-Time Communication)

概述
https://webrtcforthecurious.com/zh/docs/01-what-why-and-how/

看完只有一个感受 :为什么音视频要扯上web,其中的协议大部分都来自web的世界,思考的泉水都是起源于web的思考框架,webrtc去掉音视频 也是一个很好的p2p 框架,加上音视频的难度就在于传输的内容必须是低延时性和交互性(Real-Time),这里反而是webrtc最引人注目的地方,也是webrtc创新的地方。

信令 sdp 
连接 nat,利用udp,stun or turn   ice
安全 DTLS 
传输 RTP,RTCP,SRTP(利用DTLS的秘钥),SRTCP(利用DTLS的秘钥),SCTP(keep-alive)

这里利用开源框架 janus-gateway 了解实实现细节,网上吹嘘这个的也挺多,咱来一探究竟,
首先把demo建立起来,打开日志,在echotest的demo下,将相应的日志文件获取,获取日志文件阅读过程,将整个源码的流程理清。

从janus的main函数开始,其实主要功能注释都有提供,主要有两个方面可以探讨,一个是框架设计(如何将WebRTC的思路集成至框架中并且考量未来扩展),再一个就是WebRTC的代码设计细节

加载插件的思路实际就是从配置文件读取对应插件的名字以及路径,使用动态库链接,并解使用统一的接口进行初始化。

  1. config 阶段
    分为四类 janus eventhandler(将消息发布出去所使用的组件) transport(传输) plugin

  2. 根据config创建 守护进程

  3. 初始化logger 加载日志插件

  4. 处理剩余config

  5. 处理 特殊ip

  6. 获取本地ip

  7. 客户端安全验证 配置应用

  8. 配置ice所需的stun 和turn服务器地址,一开始我的理解webrtc 是客户端的端到端,为啥网关也需要呢,假如该gateway部署在nat之后就需要了,后面理解了gateway本身也可以是客户端,网关只是起到一个转发的作用。

  9. sessions( HashTable  ) 超时watchdog(房间session超时等回调)

  10. janus_requests 分发队列 初始化 janus的request就同步处理  其它request 异步处理丢进线程池异步处理

  11. 读取配置文件加载event handler ,获取所有event handler 
    文档详细描述:https://janus-legacy.conf.meetecho.com/docs/eventhandlers.html
    event handler抽象结构声明 janus_eventhandler 具体实现由对应eventhandler动态库里的加载执行
    这里以websocket的eventhandler 分析一下这个事件处理器的主要工作内容
    读取相应配置 -> 启动一个websocket thread 处理ws ,启动一个消息处理线程 (janus core广播消息的回调就是将该消息放到该队列当中
    event -> 进去event thread 解析出message 并丢进message的队列,websocket 线程将该消息丢给ws 传递出去
    如何处理事件,事件需要广播,初始化event事件队列,开启新线程处理event(分发给每个handler)

  12. 读取配置文件 加载plugin
    这里需要注意插件是如何和客户端通信的 配合这篇博文食用更佳 https://blog.csdn.net/cgs1999/article/details/94436089
    这里找echo-test 最简单的插件分析,可以发现插件和core的交流基本上和业务没有什么关系,所以这里可以抽离出来,这里分析抽象的plugin行为应该是怎么样的
    具体行为不在main函数里,看一下对plugins 的操作 ,可以看到plugin的sessionid是由从第10步中的janus_process_incoming_request 传递的。
    从sessionid入手,发现sessionid是janus_request的message传递。 而janus_request的message是由transport 传进来的。那transport中的message的来源呢?从第13步的transport即可知道。来源知道了,剩下去处。
    session的开始是由create开始,如果json消息里没有session且是create消息,就会根据逻辑创建session。
    以下几个阶段:


    create(创建janus会话)
    通过客户端生成的transfaction 创建core_session,transfaction确保是同一个core_session,后续的操作都需要带上这个sessionid
    attach(创建ICE会话,上下文包括插件以及janus_session)
    以插件编写的get_package 的返回值为key 找已注册的插件,验证token,并创建一个handle,这个handle的定义为janus_ice_handle (用于标识一个ICE会话,封装了ICE的传输信息,用于一个通道实际的数据收发,一个core_session上可以有若干janus_ice_handle,实际就是attach多个插件的意思);janus_ice_handle_attach_plugin 利用core_session 和 handle 和插件建立plugin_session(具体由插件实现,和插件的业务相关),并补充handle的信息,这里详细介绍下handle 中的几个关键点。主要创建一个新的上下文并启动事件循环和一个消息队列(janus_ice_outgoing_traffic)以及线程资源用于协商ice会话或者其它事项.
    webrtc过程
    SDP交换过程
    根据WebRTC的协议定义,这个过程就是需要想办法吧sdp提供给两边。
    客户端创建sdp 并用上述会话以janus message( janus的message 需要带core session和 handle 的id才能确定具体的handle )承载sdp信息传给janus-gateway,janus-gateway属于sdp(signal-server的作用)
    解析sdp->基于libnice库和janus建立ice链接(Setup ICE locally)初始化会话后续所步骤需要的资源,等待客户端建立ice连接->插件处理sdp并获取本地的sdp以event消息传递给客户端。这里需要理解为什么SDP需要在插件中返回,把能否进行媒体传输的决定权移交给上层业务(插件)。
    trickle 消息,用于交换ice的candidate,双方的消息都是trickle
    这里有个问题就是trikle的消息都是两边的库生成candidate信息所调用的回调向对方发送trikle消息。存在一个问题就是服务端的trikle消息可能比服务端的sdp消息要快?万一sdp失败了怎么办 Todo ICE通道的建立和SDP(没有candidate)没有冲突,只需要考虑sdp的异常case关闭session即可
    客户端利用webrtcsdk收集candidate,给janus发送消息,janus利用attach阶段建立的消息循环向ice层设置客户端的candidates
    janus利用nice_agent_gather_candidates,给客户端发送消息,客户端接收到trickle消息直接在peerConnection.addIceCandidate设置
    这里是服务端需要处理多个会话所以需要有特殊消息循环机制(消息如下图)和多线程处理,而客户端只有一个会话,所以客户端逻辑稍微简单
    获取candidate结束后会在message中添加complete标识。

     

     


    NAT
    这里我们只需要知道libnice实现了nat即可,这里引入的libnice库很重要,janus的和客户端的p2p连接接就是这个库做到的,NAT的过程的具体需要知道libnice的大概实现和调用逻辑,一边更熟悉webrtc 建立连接的过程。,当libnice 发射new-selected-pair信号的时候,就是已经确认nat通道已经确认,如果需要webrtc的安全传输则在这时候开始建立dtls通道。
    DTLS
    利用openssl bio建立,是一个简单的小状态机。(这里要是被攻击不就会创建n多线程?)

    SRTP
    协商SRTP的秘钥,即从上一步建立的DTLS中设置相关的秘钥即可。
    创建处理SRTCP的事件源
    协商完成就是说明通道已经协商完毕可以传输了,随后发送event

    webrtcup消息
    Janus发送webrtcup通知ICE通道建立
    rtppacket传输
    ice通道收到rtp消息交给插件转发rtp即可,这里需要注意如何把rtp的包转发给别人。
    这里比较关键的函数如下,只需要几个参数就可以修改rtp的 头

    随后根据插件的plugin_session获取core_session使用该core_session的ice通道的handle转发rtp,echotest的handle是本身,所以使用原来的即可

     

     


  13. 读取配置文件 加载transport,
    以transport 为例。websocket 比较好理解,需要定义janus子协议。

  14. wertc 的断开,客户端主动发送destory的消息,或者janus在websocket 会有监听的心跳,如果在一段时间的心跳(keepalive的msg)结束了,就表示断开连接了

配置至本地demo测试:
学习完大致流程后,利用网上大佬们的Android Demo https://github.com/lesliebeijing/JanusAndroidDemo.git  直接跑一边熟悉流程
大致原理就是利用transport来交流网关业务,同时双端配合webrtc 通过webrtc来实现网关和客户端的视频转发

感触:其实难度在于没人告诉你WebRTC为什么这样设计?这也是我苦恼的地方,我不认识熟悉Janus-gateway的人,所有遇到问题都是强迫自己去看代码寻找答案,这对于初学者来说确实是很痛苦的一件事情。但是分析下来其实代码很精简,每块代码都有它存在的意义。耗时两个星期才读了个大概。。。还有很多~ c真的很难读 擦,后续的就是插件的业务和如何断开连接的分析,

后面发现比较新的流媒体服务器都是使用单进程单线程模型,就是为了解决C10K问题。同时也没有相应的文章去描述如何把janus应用到负载均衡上,对于如何在流媒体服务做负载均衡这一块我也是很有疑问的,这对于做到低延时很有破坏效果(如果动态切换网关ip的话,还得再学习一下

 

标签:插件,handle,Janus,ice,gateway,janus,session,WebRTC,客户端
From: https://www.cnblogs.com/Keep-J0K3R/p/17317942.html

相关文章

  • springcloud gateway根据服务名称进行路由失败There was an unexpected error (type=S
    出现错误,如下图:解决办法:检查自己的yaml文件:server:port:88spring:application:name:applicationNamecloud:nacos:discovery:server-addr:127.0.0.1:8848gateway:#开启服务发现路由(不开启跨域问题可能无法解决)disco......
  • SIP视频监控 / webrtc视频会议接入GB28181国标平台
     截图使用的是知乎视频 实现思路:1.使用国标代理网关,建立sip号码与gb28181设备号,通道号之间的对照表,实现gb28181网关功能(设备注册,目录查询,心跳,直播拉流,Bye,设备注销),参:GB28181国标代理-CHHC-博客园(cnblogs.com)2.直播拉流时,可通过调用sip系统/视频会议系统提供发送RTP......
  • SAP ABAP Gateway 系统里 HTTP 请求响应头部字段 DataServiceVersion 的可能取值范围
    SAPABAPGateway系统里HTTP请求的响应头部字段集合里,DataServiceVersion这个字段的作用是什么,包含哪些可能的值?如下图第178行代码所示。在SAPABAPGateway系统中,DataServiceVersion是HTTP响应头部字段集合中的一个字段,用于指定OData服务的版本信息。具体来说,Da......
  • 网页端WebRTC推流转换为RTMP/GB28181等其他直播流协议
    网页端WebRTC推流转换为RTMP/GB28181等其他直播流协议WebRTC是一个在WEB浏览器端广泛应用的流媒体引擎,通过点对点的方式实现音视频数据的传输,以完成视频会议等功能。但是考虑到WebRTC主要是为有限人数情况下的点对点视频会议服务,在做其他直播应用的时候,或者接入现有流媒体网络的......
  • webrtc QOS笔记三 Nack机制浅析
    nack源码浅析nack源码浅析VideoNacknack模块nacklistkeyFramelist&recoveredlistnack发送的策略nack模块的几个重要常量改进参考配置一个合适的发送延迟重发补偿AudioNackSRSNackVideoNack机制概述nack的机制非常简洁,收到非连续的packe......
  • LiveQing流媒体RTMP推流服务-如何获直播流地址 HLS/HTTP-FLV/WS-FLV/WebRTC/RTMP视频
    @目录1、服务说明2、如何一步一步搭建视频直播3、配置鉴权直播间3.1直播间创建3.2获取RTMP推流地址3.3播放流地址4、视频集成方式5、分享页面集成6、视频流地址集成6.1、直播流地址(页面查看获取)6.2、直播流地址(接口调用获取)6.2.1、接口服务地址说明6.2.2、获取直播列表7、RTMP......
  • nginx keepalive_timeout 300; 504 Gateway Time-out
    实践:1、http{includemime.types;#includeluawaf.conf;includeproxy.conf;default_typeapplication/octet-stream;server_names_hash_bucket_size512;client_header_buffer_size32k;large_client_header_buffers432k;client_max_b......
  • WebRTC通信时获取速率(每秒帧数)相关信息
    在用WebRTC进行通信时,可以通过RTCPeerConnection对象的getStats方法获取相关的连接统计信息,以此获取每秒帧数。--ByBriskyu1 getStats的使用方法constpc=newRTCPeerConnection()//获取视频流对象varselector=pc.getRemoteStreams()[0].getAudioTracks()[0]//......
  • mysql Gateway Time-out (rejected) 与服务器的连接断开,请检查网络状况与服务器的运
    操作mysql时出现如下错误504 mysql GatewayTime-out(rejected)与服务器的连接断开,请检查网络状况与服务器的运行状态。 解决办法:在nginx.conf中加入如下三条,......
  • 我用ChatGPT做WebRTC音视频性能优化,主打一个高效
    摘要随着GPT-4的发布,AI的风越吹越旺。GPT-4可以回答问题,可以写作,甚至可以基于一张草图生成html代码搭建一个网站。即构社区的一位开发者@倪同学就基于目前在研究的WebRTC......