欢迎访问个人GitHub
https://github.com/zq2599/blog_demos前端
内容:全部原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;java
本篇概览
- 本文是《Kurento实战》的第四篇,前面的文章中,我们先部署KMS再启动官方demo,还把Kurento的重要概念都分类学习过,接下来要开始应用开发了;
- 本文的主要内容是分析官方的<font color="blue">kurento-hello-world</font>项目,了解Kurento应用开发的基本流程和知识点,本文使用的代码是官方发布的6.15.0版本,地址:https://github.com/Kurento/ku...
- 阅读代码时,若是能从总体上将划分清楚功能模块,再有针对性的逐个攻破细节,将会更高效的学习和理解源码,接下来我们就按照Kurento官方的标准套路去拆分并逐个攻破;
如何划分功能模块
按照不一样的职责划分,整个代码被拆分为三部分:git
- WebSocket相关:WebSocket相关的通用处理,例如链接创建、关闭、异常的回调,业务逻辑的分发等;
- WebRTC信令相关:ICE、SDP相关的处理;
- 业务逻辑:若是说1和2表明的是WebRTC的通用处理,那么剩下的就是如何使用Kurento来实现业务需求了,这部分的主要内容是业务应用使用Kurento官方client和KMS交互,控制KMS为端侧提供服务,交互方式以下图:

- 按照上述方式将代码作好拆分,划定边界,不管是阅读官方demo仍是本身开发应用,都能条理清晰的应对,接下来一块儿学习官方的hello-world源码,看看一个完整的Kurento应用是如何开发出来的
WebSocket相关
最简单的逻辑应该是通用的WebSocket处理了,我们先看这部分,复杂的稍后再说,Handler类中和WebSockert相关的逻辑以下:程序员
- 继承自TextWebSocketHandler(只处理text类型的数据,对于二进制数据直接关闭会话);
- 重写afterConnectionEstablished:WebSocket链接创建的回调,只打了一行日志;
- 重写handleTransportError:WebSocket发生异常时候的回调,仅关闭WebSocketSession;
- 重写afterConnectionClosed:不论WebSocket是正常关闭仍是发生异常,此方法都会执行,逻辑也很简单,就是调用stop方法,这个方法是用来释放KMS资源的,有好几处都会调用,咱们留到稍后和其余处理KMS的地方一块儿讲;
- 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 |
- 并非全部的应用都须要重写上诉所有代码,仍是以实际需求出发决定是否要重写,以<font color="blue">kurento-one2one-call</font>项目为例,只重写了handleTextMessage和afterConnectionClosed,其余的使用父类的便可,以下图:

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


- 从上图可见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>的源码分析,整个工程的代码在拆分后再分析时,变得异常清晰和简单:web
- WebSocket和常规的java开发无异,向标准靠拢便可;
- WebRTC相关代码占了较大比重,可是严格遵循了标准的信令流程,只要熟悉WebRTC就很容易阅读和理解;
- 业务逻辑实际上是和业务需求相关联的,这里须要熟悉KMS提供的能力,才能充分发挥KMS的实例,而pipeline编排和各个element的使用,也会是我们后面文章的重点,用好这些element,打磨出更强大灵活的服务;
你不孤单,欣宸原创一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 数据库+中间件系列
- DevOps系列
欢迎关注公众号:程序员欣宸
微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...
https://github.com/zq2599/blog_demos