写点什么

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

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:1904 字

    阅读完需:约 6 分钟

  • 按照上述方式将代码做好拆分,划定边界,不论是阅读官方 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_OFFER | handleProcessSdpOffer | 收到前端 SDPOffer 数据后的处理逻辑 |


| ADD_ICE_CANDIDATE | handleAddIceCandidate | 收到前端 ICE 数据后的处理逻辑 |


| STOP | handleStop | HashMap 删除用户数据,再远程调用 MediaPipeline.release |


| ERROR | handleError | HashMap 删除用户数据,再远程调用 MediaPipeline.release |


  1. 并不是所有的应用都需要重写上诉全部代码,还是以实际需求出发决定是否要重写,以 kurento-one2one-call 项目为例,只重写了 handleTextMessage 和 afterConnectionClosed,其他的使用父类的即可,如下图:



  1. 还有一个发送消息到浏览器侧的 sendMessage 方法,以及发送错误信息的 sendError 方法;

信令相关

  • kurento-hello-world 应用的功能是和 KMS 实现实时音视频通信,因此 WebRTC 标准的信令处理是必不可少的,可惜 Kurento 官方并没有对信令处理做太多封装(也可能是信令和不同的业务处理逻辑都不一样,导致不好抽象),结果就是一堆信令处理的代码散落在业务代码中;

  • 就算业务和信令的处理代码同时出现在 Handler 类中,只要熟悉 WebRTC 的信令处理流程,也很容易读懂代码,下图结合了 WebRTC 标准的信令处理流程,对前端和服务端的代码串联在一起就行分析,左边是浏览器上执行的 js 代码,右边是服务端,这些代码都用红色箭头标识了处于 WebRTC 信令处理流程的具体位置,至此,整个流程都清晰的展现出来:



  • 如果您在电脑或手机上看上图觉得模糊,请下载原始文件,用 draw.io 打开,文件所在目录是:https://github.com/zq2599/blog_demos/tree/master/files ,文件名为 helloworld-flow.drawio

  • 上图列出了信令相关的所有代码,等到看完这些,剩下的就是业务代码了,也就是图中紫色部分的 handleProcessSdpOffer 方法;

业务相关

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



  • 从上图可见 pipeline 逻辑非常简单:只有一个 WebRtcEn


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


dpoint,把自己的 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();


}


}


}

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
Kurento实战之四:应用开发指南