3

Kurento实战之四:应用开发指南

 3 years ago
source link: https://segmentfault.com/a/1190000040180073
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

  • 本文是《Kurento实战》的第四篇,前面的文章中,咱们先部署KMS再启动官方demo,还把Kurento的重要概念都分类学习过,接下来要开始应用开发了;
  • 本文的主要内容是分析官方的<font color="blue">kurento-hello-world</font>项目,了解Kurento应用开发的基本流程和知识点,本文使用的代码是官方发布的6.15.0版本,地址:https://github.com/Kurento/ku...
  • 阅读代码时,如果能从整体上将划分清楚功能模块,再有针对性的逐个攻破细节,将会更高效的学习和理解源码,接下来咱们就按照Kurento官方的标准套路去拆分并逐个攻破;

如何划分功能模块

按照不同的职责划分,整个代码被拆分为三部分:

  1. WebSocket相关:WebSocket相关的通用处理,例如连接建立、关闭、异常的回调,业务逻辑的分发等;
  2. WebRTC信令相关:ICE、SDP相关的处理;
  3. 业务逻辑:如果说1和2代表的是WebRTC的通用处理,那么剩下的就是如何使用Kurento来实现业务需求了,这部分的主要内容是业务应用使用Kurento官方client和KMS交互,控制KMS为端侧提供服务,交互方式如下图:
    在这里插入图片描述
  • 按照上述方式将代码做好拆分,划定边界,不论是阅读官方demo还是自己开发应用,都能条理清晰的应对,接下来一起学习官方的hello-world源码,看看一个完整的Kurento应用是如何开发出来的

WebSocket相关

最简单的逻辑应该是通用的WebSocket处理了,咱们先看这部分,复杂的稍后再说,Handler类中和WebSockert相关的逻辑如下:

  1. 继承自TextWebSocketHandler(只处理text类型的数据,对于二进制数据直接关闭会话);
  2. 重写afterConnectionEstablished:WebSocket连接建立的回调,只打了一行日志;
  3. 重写handleTransportError:WebSocket发生异常时候的回调,仅关闭WebSocketSession;
  4. 重写afterConnectionClosed:不论WebSocket是正常关闭还是发生异常,此方法都会执行,逻辑也很简单,就是调用stop方法,这个方法是用来释放KMS资源的,有好几处都会调用,我们留到稍后和其他处理KMS的地方一起讲;
  5. WebSockert部分最重要的代码是handleTextMessage方法,里面是收到前端数据时的处理逻辑:先把数据转为JsonObject对象,此对象的messageId字段有四种值,每一种id及其对应的处理方法如下表格所示:
messageId处理方法说明PROCESS_SDP_OFFERhandleProcessSdpOffer收到前端SDPOffer数据后的处理逻辑ADD_ICE_CANDIDATEhandleAddIceCandidate收到前端ICE数据后的处理逻辑STOPhandleStopHashMap删除用户数据,再远程调用MediaPipeline.releaseERRORhandleErrorHashMap删除用户数据,再远程调用MediaPipeline.release
  1. 并不是所有的应用都需要重写上诉全部代码,还是以实际需求出发决定是否要重写,以<font color="blue">kurento-one2one-call</font>项目为例,只重写了handleTextMessage和afterConnectionClosed,其他的使用父类的即可,如下图:

在这里插入图片描述

  1. 还有一个发送消息到浏览器侧的sendMessage方法,以及发送错误信息的sendError方法;
  • <font color="blue">kurento-hello-world</font>应用的功能是和KMS实现实时音视频通信,因此WebRTC标准的信令处理是必不可少的,可惜Kurento官方并没有对信令处理做太多封装(也可能是信令和不同的业务处理逻辑都不一样,导致不好抽象),结果就是一堆信令处理的代码散落在业务代码中;
  • 就算业务和信令的处理代码同时出现在Handler类中,只要熟悉WebRTC的信令处理流程,也很容易读懂代码,下图结合了WebRTC标准的信令处理流程,对前端和服务端的代码串联在一起就行分析,左边是浏览器上执行的js代码,右边是服务端,这些代码都用红色箭头标识了处于WebRTC信令处理流程的具体位置,至此,整个流程都清晰的展现出来:

在这里插入图片描述

  • 如果您在电脑或手机上看上图觉得模糊,请下载原始文件,用<font color="blue">draw.io</font>打开,文件所在目录是:https://github.com/zq2599/blo... ,文件名为<font color="red">helloworld-flow.drawio</font>
  • 上图列出了信令相关的所有代码,等到看完这些,剩下的就是业务代码了,也就是图中紫色部分的<font color="blue">handleProcessSdpOffer</font>方法;

  • <font color="blue">kurento-hello-world</font>应用是把本地摄像头和麦克风数据传到KMS,再从KMS取得这些数据在页面展示,先看看官方是如何描述KMS pipeline的:

在这里插入图片描述

  • 从上图可见pipeline逻辑非常简单:只有一个WebRtcEndpoint,把自己的Src和Sink接上就完成了,咱们来看看对应的代码,在方法handleProcessSdpOffer中:
    // 创建pipeline
    final MediaPipeline pipeline = kurento.createMediaPipeline();
    user.setMediaPipeline(pipeline);

    // 创建webRtcEndpoint
    final WebRtcEndpoint webRtcEp =
        new WebRtcEndpoint.Builder(pipeline).build();
    user.setWebRtcEndpoint(webRtcEp);

    // 自己的sink连接上自己的src
    webRtcEp.connect(webRtcEp);

    // ---- Endpoint configuration

    String sdpOffer = jsonMessage.get("sdpOffer").getAsString();
    
    // 注册各类监听,例如媒体资源状态变化、ICE变化等
    // 通过websocket回复SDP Offer
    initWebRtcEndpoint(session, webRtcEp, sdpOffer);

    log.info("[Handler::handleStart] New WebRtcEndpoint: {}",
        webRtcEp.getName());
    
    // ---- Endpoint startup
    // 取得ICE信息
    startWebRtcEndpoint(webRtcEp);
  • 再来看看停止WebRtc的stop方法,其实就是向KMS发送了release指令:
  private void stop(final WebSocketSession session) {
    // Remove the user session and release all resources
    final UserSession user = users.remove(session.getId());
    if (user != null) {
      MediaPipeline mediaPipeline = user.getMediaPipeline();
      if (mediaPipeline != null) {
        log.info("[Handler::stop] Release the Media Pipeline");
        mediaPipeline.release();
      }
    }
  }

以上就是整个<font color="blue">kurento-hello-world</font>的源码分析,整个工程的代码在拆分后再分析时,变得异常清晰和简单:

  1. WebSocket和常规的java开发无异,向标准靠拢即可;
  2. WebRTC相关代码占了较大比重,但是严格遵循了标准的信令流程,只要熟悉WebRTC就很容易阅读和理解;
  3. 业务逻辑其实是和业务需求相关联的,这里需要熟悉KMS提供的能力,才能充分发挥KMS的实例,而pipeline编排和各个element的使用,也会是咱们后面文章的重点,用好这些element,打磨出更强大灵活的服务;

你不孤单,欣宸原创一路相伴

欢迎关注公众号:程序员欣宸

微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...
https://github.com/zq2599/blog_demos


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK