前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >干货 | 携程移动直播探索

干货 | 携程移动直播探索

作者头像
携程技术
发布2020-11-19 11:33:01
9910
发布2020-11-19 11:33:01
举报
文章被收录于专栏:携程技术

作者简介

鹏程,携程 Android 开发工程师,Android google jetpack和kotlin语言的拥护者。

一、背景

直播行业大概在10年前就开始兴起了,秀场直播和游戏直播是pc时代比较成功的应用场景。现阶段,移动互联网的大规模普及,流量价格越来越便宜,移动视频直播异常火爆,随着各行各业的不断融合,直播带货超高的营业额,明星艺人、销售、秀场网红的涌入,直播行业迎来了空前的繁荣发展。从pc直播到渐渐火爆的移动直播,直播技术也在不断地更新迭代,趋于成熟。

本文从直播流的选择、交互优化、快速迭代等方面介绍携程直播技术。

二、直播原理

视频直播流程如下图。简单来说,推流端通过视频采集功能,把采集到的视频画面经过一系列的业务特效处理后,进行视频编码推送。拉流端使用流播放器把视频画面播放出来。

  • 采集:视频采集的主要采集源:摄像头、屏幕录制、视频文件推流
  • 处理:视频采集后得到原始数据,为了增强一些现场效果,需要在编码前进行处理(logo、美颜、变声)
  • 编码:编码性能、编码速率和编码压缩比直接影响整个流媒体传送的用户体验和传送成本
  • 推流:推流是直播的第一步。推流协议的选择会直接影响到观看的用户体验,常见的流协议(RTMP、HLS)
  • 分发:流媒体服务器负责直播流的发布和转播分发功能
  • 播放:直播终端的展示

前四步我们通常情况下称为推流操作,第五步称为服务分发或者cdn分发,第六步称为拉流操作。简化图如下:

推流操作中比较重要的两步是编码和推流。

2.1 编码

1)编码是什么

视频编码是压缩和可能改变视频内容格式的过程。

2)编码能做什么

a. 减少占用空间;

b. 兼容性;

在减少占用空间方面:

(数据来源于网络)

在兼容性方面,有时内容已经被压缩到足够的大小,但仍然需要进行编码以实现兼容性。这通常被更准确地描述为代码转换。兼容可能涉及某些服务或程序,这些服务或程序需要某些编码规范。

国内常见的编解码器是H.265、H.264。

2.2 推流

常见的流协议为以下几种:

1)RTMP

RTMP(Real Time MessagingProtocol):实时消息传输协议,是Adobe公司为flash播放器和服务器之间实现音频、视频和数据传输开发的实时消息传输协议。在RTMP协议中,视频必须是H264编码,音频必须是AAC或者MP3编码,且多以Flv格式封包。

RTMP的优势在于:

  • RTMP 是专为流媒体开发的协议,对底层的优化比其它协议更加优秀,同时它 Adobe Flash 支持好,基本上所有的编码器(摄像头之类)都支持 RTMP 输出。
  • RTMP适合长时间播放。因为RTMP支持的很完善,所以能做到flash播放RTMP流长时间不断流。当时的测试时长是100万秒,即10天多可以连续播放。(数据来源于网络)
  • RTMP 的延迟相对较低,一般延时在 1-5s 之间,一般的视频会议,互动式直播,完全是够用的。

RTMP的劣势是:RTMP是基于TCP协议,不会丢包。所以当网络状态差时,服务器会将包缓存起来,导致累积的延迟;待网络状况好了,就一起发给客户端。

2)HLS

HLS(HTTPLive Straming): 是苹果公司实现的基于HTTP的流媒体传输协议。它将整个流分为多个小文件来下载,客户端只要不停的按顺序播放从服务器获取的文件,就实现了直播。

HLS的优势是:客户端支持简单,只需要支持HTTP请求即可。并且HTTP协议很方便通过防火墙或者代理服务器。CDN支持良好。由于是苹果公司提出的,所以在苹果的全系列产品都支持。

HLS的劣势:相比 RTMP 这类长连接协议,HLS的延时较高, 难以用到互动直播场景。

3)WebRTC

WebRTC(Web Real TimeCommunication):是一个支持浏览器进行实时语音、视频对话的开源协议。基于UDP,即使在网络信号一般的情况下也具备较好的稳定性。

WebRTC的优点:开发者使用简单的HTML标签和JavaScriptAPI就能够实现Web音/视频通信的功能。

WebRTC的缺点:WebRTC中很多的参数都是由GIPS公司的工程师们依靠经验所设定的值,这就会出现卡顿、延时、回声、丢包、多人视频不稳定等问题。WebRTC缺乏服务器方案的设计和部署。对Native开发支持不够。

4)HTTP-Flv

HTTP-Flv:是一种将直播流模拟成flv文件,通过http协议进行下载的模式实现流媒体传输的协议。

它结合了RTMP的低延时,以及可以复用现有HTTP分发资源的流式协议。优势在于可以在一定程度上避免防火墙的干扰,可以使用HTTPS做加密通道,很好的支持移动端。

缺点在于由于它的传输特性,会让流媒体资源缓存在本地客户端,在保密性方面不够好。因为网络流量较大,它也不适合做拉流协议。

协议

http-flv

RTMP

HLS

WebRTC

传输方式

HTTP长连接

Tcp

http短连接

UDP

视频封装格式

FLV

FLV

TS文件

Track分片

原理

同RTMP,使用HTTP协议

每个时刻的数据收到后立即转发

集合一段时间的数据,生产TS切片并更新m3u8索引

Udp 传输协议,保证低延时和及时性。Client-client之间传输,要解决NAT 穿透问题。

延时

低 1-5s

低 1-5s

高 10-20秒

低1-2s

数据分段

连续流

连续流

切片文件

P2P数据交换

Html5

支持

不支持

支持

支持

其他

需要Flash技术支持,

网络质量要求高

要解决NAT,socket建立等问题

我们选择RTMP作为主要的流协议的原因有:

1)RTMP是编码器输入的工业标准协议,基本上所有的编码器(摄像头等)都支持RTMP输出。

2)RTMP适合长时间播放的优势,可以保证尽可能的减少用户重连的次数。

3)直播场景互动性交高,对时延要求高。RTMP通常情况下可以做到3秒延迟,满足大多数场景(hls大概10秒)。

4)WebRTC对浏览器支持较好,对native支持不够,需要做大量的开发工作。

5)由于开源软件和开源库的支持稳定完整(OBS软件,开源的librtmp库,服务端有nginx-rtmp插件),RTMP在国内流行度很高,技术相对成熟。

目前市面上有很多云直播厂商。可以综合考虑推流协议,时延要求、推拉流费用,SDK的size以及扩展直播场景等方面来选择适合自己的sdk。

三、直播前端框架

当我们需要建立一个直播的时候,我们需要做什么呢?

简单的来说分3步。

第一步:从sdk中拿出推流Manager,设置预览View,设置推流地址。

代码语言:javascript
复制
@Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.live_push);
    livePusher = new LivePusher();
    videoView = findViewById(R.id. live_video_preview);
        livePusher. startCameraPreview(videoView);
        String pushUrl = "rtmp://...";
    livePusher.startPusher(PushUrl);
    }

第二步:使用拉流Manager,设置播放预览view,设置拉流地址和流类型(RTMP、flv等)。

代码语言:javascript
复制
@Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.live_pull);
    livePlayer = new LivePlayer();
    playerView = findViewById(R.id.live_video_view);
        String pullURl = "rtmp://...";
    livePlayer.setPlayerView(playerView)
    livePlayer.startPlay(pullURl, PLAY_TYPE_LIVE_RTMP)

}

第三步就可以愉快地观看直播了。

携程直播就是在这个基础之上,进行了复杂的业务开发。视频推流和拉流是需要调用Native直播sdk的方法,所以需要保留在Native中。页面上的互动区域需要更快速的迭代方式,所以选择了RN。

携程直播作出以下的分层结构:

视频直播前端框架图

1)Lib

这一层主要放置整个直播项目通用的类。

ClientProxy:网络请求的通用字段封装和返回的常规错误码处理、序列化处理、通用Log日志控制等。

PushManger 和 PullManger 使用了 Proxy 设计模式用于减少sdk和业务代码的耦合。使用单例模式保证多个直播的配置统一。

Event:跨平台事件传递类(EventBus),RN、Hybrid的事件都最终调用native的Event方法发送事件来保证多平台事件传递的可能。

RN:

代码语言:javascript
复制
Event.sendEvent("EventName",{ params: 0 });

Native:

代码语言:javascript
复制
CtripEventCenter.getInstance().sendMessage(EventName,jsonObject)

底层都是调用Native的EventBus。

IMManger:消息的管理类。控制直播间的弹幕消息,开始结束消息以及礼物等消息的分发。

2)Page

把推流和拉流页面称为Page。主要作用有两个,首先调用SDK做推拉流。其次,在页面中对RN和Native进行交互,例如从消息中获取流状态、礼物或者其他的消息。然后给RN发Event事件或者调用Native方法来完成相关消息的后续动作。

Page中注册消息监听。

代码语言:javascript
复制
interface CTLiveChatMessageListener {
       fun startLive()
}
Page.registerCTLiveChatMessageListener(listener)

在listener中使用Event分发事件。

3)View层

Page上挂载了一个透明的RNView作为直播中交互View。主要负责渲染业务交互view,比如头像名称、评论列表、礼物动画、商品卡片、分享等。

在 page 的 onCreate 的时候把 view 挂载上去。

代码语言:javascript
复制
manager.beginTransaction().add(R.id.live_crn_fragment, rnFragment,
        "livePage").commitAllowingStateLoss()

然后页面和逻辑放到RN中。

效果图上,摄像头的内容为原生Native,其他的可见为RNVIew。

四、遇到的问题和解决的办法

在Native-RN 混合开发过程中,我们遇到了一些棘手的问题:

1)在多次唤醒直播间,或者同时打开多个直播间时,会存在画面和声音对不上,或者出现多个声道的问题。为了解决这个问题我们把直播间做成单例,保证整个app的运行过程中只存在一个直播间。

2)覆盖在直播预览页面上面的交互RNView设置为透明背景不生效问题。我们在RN的render返回一个透明View,但是在页面上还是出现了白色的底色。这个时候需要检查一下fragment是否挂载在一个白色View上。

3)在Page初始化的时候发送Event事件,但是RN没有收到的问题。这个时候RN容器可能还没有创建完成,我们需要保证发送事件的时机在RN容器创建完成之后。

五、总结

视频直播在近几年是一个比较火爆的技术点。直播的场景每年都在迅速地更新中。我们需要使用一种更快速的迭代方式,所以需要在优化时把稳定的东西使用native封装成基础页面,在保证底层稳定的前提下,选择跨平台的技术栈进行快速的页面迭代开发。ReactNative或者Flutter等跨平台开发语言都是不错的选择。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 携程技术中心 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档