作者:张凌柱(以绳)
本文为《优酷播放黑科技》系列文章第二篇,第一篇文章可点击优酷播放黑科技 | 自在视角技术体验优化实际进行查看。点关注不迷路 ~
直播内容区别于点播,因其实时性、强互动性的特点吸引着用户,在观看的同时还能够同步进行点赞、评论、打赏等互动行为。此类互动次要集中在用户的社交行为,而内容型的互动也随着点播中的“互动剧集”的呈现而映入公众的眼帘,用户能够在剧情停顿的要害节点抉择角色执行不同的行为继而进入到不同的分支剧情中。同样直播方向上的内容型互动也在被不停的摸索和利用中,其中一个例子就是同时进行多个视角的直播,容许用户切换抉择某个特定的视角观看直播内容。尤其在中大型的直播流动中(例如街舞、欧冠等),粉丝向比拟显著(明星、球星),如果能提供多个观看视角或者提供某个聚焦视角供切换抉择,在用户体验上无疑能有很大的晋升。
基于此,通过钻研与摸索,最终基于 WebRTC 落地实现了低提早高清晰度的多视角直播能力,并在《这!就是街舞》的年度总决赛正式上线利用。成果视频如下:
视频可点击查看:优酷播放黑科技 | 基于 WebRTC 实现的直播 ” 云多视角 ” 技术解析
计划选型
是否实现 低提早切换 、 高清晰度 、 全机型笼罩 的用户体验是最终决定采纳哪种技术计划的重要衡量标准。业内罕用的应用层协定包含:
- HLS(含 LHLS)
- RTMP
- RTP(严格来说 RTP 介于应用层和传输层之间)
其中,RTMP 因其优缺点(低提早但易被防火墙拦挡)被确定用于直播推流,本文暂不多作介绍,上面咱们次要针对拉流过程进行剖析。依据端上拉流个数能够将实现计划分为:
- 单路流伪多视角直播:基于 HLS 协定,端上同一时间仅拉取一路流,切视角须要从新切流地址起播;
- 多路流多视角直播:基于 HLS 协定,端上同时拉取多路流进行解码渲染,切视角不须要切流地址起播;
- 单路流多视角直播:基于 RTP 协定,端上同一时间仅拉取一路流,切视角不须要从新切流地址起播。
横向比照
对处于劣势的个性作标红解决后失去的表格:
计划 | 协定 | 同时预览 | 无缝切换 | 码率 | 端性能累赘 | 增量老本 |
---|---|---|---|---|---|---|
单路流伪多视角直播 | HLS | 否 | 否 | 一般 | 一般 | 无 |
多路流多视角直播 | HLS | 是 | 是 | 高 | 高 | CDN |
单路流多视角直播 | RTP | 是 | 是 | 一般 | 一般 | 边缘服务与流量带宽 |
通过比照,咱们最终决定采纳基于 RTP 的单路流多视角直播,即边缘计划。
WebRTC 概述
WebRTC,名称源自网页即时通信(英语:Web Real-Time Communication)的缩写,是一个反对网页浏览器进行实时语音对话或视频对话的 API。它于 2011 年 6 月 1 日开源并在 Google、Mozilla、Opera 反对下被纳入万维网联盟的 W3C 举荐规范。WebRTC 默认应用 UDP 协定 (实际上应用的是 RTP/RTCP 协定) 进行音视频数据的传输,然而也能够通过 TCP 传输。目前次要利用于视频会议和连麦中。
WebRTC 内部结构
Voice Engine 音频引擎负责音频采集和传输,具备降噪、回声打消等性能。Video Engine 视频引擎负责网络抖动优化,互联网传输编解码优化。音视频引擎之上是 一套 C++ API。
WebRTC 协定栈
ICE、STUN、TURN 用于内网穿透, 解决了获取与绑定外网映射地址的问题。DTLS (UDP 版的 TLS)用于对传输内容进行加密。RTP/SRTP 次要用来传输对实时性要求比拟高的音视频数据,RTCP/SRTCP 用来管制 RTP 传输品质。SCTP 用于自定义利用数据的传输。
零碎设计
多视角直播整体链路波及流生产、域名调度服务、边缘服务、合流服务、直播播控服务等多个环节,整体构造框架如下:
- 流生产:演播现场摄像机采集流上传到直播核心,直播核心对流进行编码及优化解决;
- 合流服务:多路输出流通过工夫戳进行音视频对齐后,依照模版输入多路混合流;
- 边缘服务:预缓存合流服务多路输入流,对输入流进行编码,通过 RTP 连贯传输给端侧;
- 域名调度服务:进行 IP、端口配置,供端侧与边缘服务通信;
- 播控服务:提供合流服务申请参数配置、及多视角业务能力配置等播放管制服务。
具体设计
端侧为了尽可能的复用播控主链路,缩小对主播放链路的侵入,减少了多视角播放器。多视角播放器与其余播放器放弃雷同的调用接口,在播控处依据业务类型决定是否创立多视角播放器。在业务层减少多视角插件,与其余业务解耦,能够很不便的挂载与移除。
端侧结构设计如下:
外围流程
用户进入多视角模式次要起播流程如下:
目前反对 3 种展现状态,别离为 mix 模式、cover 模式及 source 模式,下图为具体状态及切换过程。
[]()
边端指令
端侧与边缘结点次要交互指令,通过 RTP 协定进行数据传输。通用头部传输格局如下,PT=96 代表 H264 媒体数据。
- 建连指令:阻塞式指令,端侧与边缘结点建设 RTP 连贯,须要期待边缘结点返回响应,如果在肯定工夫内无返回,则认为建连失败;
- 断连指令:非阻塞式指令,端侧与边缘结点断开连接,无需期待边缘结点返回;
- 播放指令:非阻塞式指令,端侧下发播放指令,须要传递播放流 ID 及 OSS 流配置信息,供边缘结点查找到正确流;
- 切流指令:非阻塞式指令,端侧下发切换视角指令,为了与原视角放弃同步,须要传递原视角帧工夫戳到边缘服务。
我的项目落地
播放能力调整
- 音频采样率调整
WebRTC 目前默认不反对 48K 音频采样率,而以后大型直播的采样率较高,如果不通过调整下发到端上会导致音频解码模块的解体;
- AAC 音频解码能力扩大
WebRTC 里音频编码默认用的是 Opus,但以后直播现状大部分都是 AAC 格局,所以须要客户端在 offer SDP 中增加 AAC 编码信息并实现 AAC 解码器,边缘服务配合下发 RTP 打包数据;
- H.264 编码反对
为了尽可能地升高延时,WebRTC 视频编码采纳的是 VP8 和 VP9,须要迁徙至更通用的 H.264 编码;
- 在传输方式上,WebRTC 应用 P2P 形式来进行媒体直达,它只是解决端到端的问题,对于大型 PGC、OGC 的直播内容来说显著不适宜,因而网络传输层并没有打洞逻辑,利用 RTP 连贯传输流媒体数据,RTCP 进行传输品质管制。
接入已有播放体系
为了尽可能小的缩小对主播放器影响,与主播放器放弃了统一的数据申请流程、一样的播放能力接口、统一的数据埋点机会等:
- 多视角播放器:封装 WebRTC,扩大出多视角播放器,专用于多视角视频播放;
- 播控逻辑调整:调整直播旁路数据获取流程,将合路服务、AMDC 等服务返回数据合并到数据流中;
- 播放能力 & 统计调整:放弃原有播放能力及回调接口,通过扩大接口参数来予以辨别;
- 扩大错误码:基于主播放器谬误规定,扩大出多视角播放器错误码。
端侧问题解决
最终须要实现下图所示的主播放窗口附带几个子播放窗口同时渲染:
右侧可滑动列表采纳 UITableView(RecyclerView)实现,为每一个子窗口增加渲染实例 GLKView(被 RTCEAGLVideoView 包裹治理),通过在适合的机会创立、移除、更新子窗口的渲染 frame 实现一路流多个视角同步直播的成果。
期间次要解决了切视角闪动的体验问题以及内存透露导致的渲染黑屏稳定性问题。这里作简要介绍。
播放闪动
【问题形容】如果一共有 N 个视角,那么咱们的实现计划则共有 N *3(参见零碎设计中的 3 种展现状态)路流,每次点击视角切换,理论的操作流程是播放器收回 RTP 切流指令,边缘节点换流 ID 并发送 Sei 回传信息,播放器接管到 SEI 信息后进行各个窗口的裁剪与更新操作。这就存在一个问题,切视角胜利后窗口更新须要肯定的工夫,会导致理论接管到了新流的帧数据最开始的一帧或几帧采纳的裁剪形式仍旧是旧流的模板,所以用户会看到一瞬间的视觉残留。
【解决方案】在播放内核收到切流指令之后,设置短时间的丢帧窗口期,待收到 Sei 信息表明切流胜利后复原渲染,这期间因为没有新的帧数据所以用户看到的是动态帧,这样能够屏蔽导致子窗口内容错乱的渲染数据,下层 UI 在此期间也看不到残留帧闪动了,用户体感上根本是平滑切换的。
内存透露
【问题形容】当用户不停地切换视角,列表刷新,cell 从新创立的过程中,内存占用不停增长,达到下限后导致黑屏窗口的呈现。
【解决方案】内存透露的起因在于 cell 从新创立过程中,内核中的 OpenGL 渲染实例产生了批量新的创立,而旧的实例又未能及时销毁。第一步明确过下层业务代码对 UIView 对象通过 removeFromSuperview 有开释操作,而 lldb 打印援用计数后仍旧不为 0,那么问题就出在了内核的实例治理上。__bridge_retained 代表 OC 转 CF 对象后,内存治理须要手动开释,因而切视角时须要调用相干 Filter 实现 C ++ 层面的销毁与开释。解决后的内存体现:
服务并发优化
优化前版本已经反对 CUBA 相干赛事直播,然而存在不少问题:老本高、切换延时高,且不具备反对大规模并发能力。本次优化指标是可能反对大型流动直播,大幅降低成本,同时保障体验。
编码前置
下图为优化前链路,能够看到,每个客户端须要从新布局和编码,这两个操作消耗大量资源,即便是用 T4 GPU 也只能反对 20 路同时观看。
通过剖析能够发现,在多视角的利用场景下用户观看的组合是无限的,在街舞模式下,观看视角为 3 *N,N 为原始采集视角,那么咱们如果把这 3N 个流事后生产,而后在边缘服务间接复制编码后的 H.264 数据,则能够把 CPU 的耗费大大降低,同时承载的用户数就是进步至多一个数量级。
图中合流服务只需生产一次,生产的内容就能够为所有的边缘服务节点所共享。
然而这种简略的切流有个问题,无奈做到帧级的对齐,换句话说,就是用户在抉择不同视角时会发现新切的视角跟之前的视角工夫上不间断。为了解决这个问题,咱们请阿里云导播的同学在合流时以相对工夫戳为根据,进行对齐,同时将这个工夫戳信息透传给边缘服务。
解决的 PTS 对齐的问题,咱们依然无奈做到真正的帧级对齐,因为还有 GOP 对齐的问题,相熟 H,264 编码的同学都晓得,视频的编码解码都是以 GOP 为单位的,GOP 的长度可能有 1s 到 10s 甚至更长,在直播中典型利用长度为 2s。如果用户切换时,恰好在一个新的 GOP 的开始,则简略切流即可实现,然而咱们不能要求用户在哪些工夫能切,哪些工夫不能切,用户要的是想切就切。咱们的解决形式如果用户切换时没有能够正好切换的 GOP,边缘服务就生产一个。
通过上图,咱们能够看到,当用户从视角 1 切换到视角 2 时,咱们在切换点产生一个新的 GOP,这样推流到客户端后,端上能够无缝解码渲染到新的视角。
通过下面的步骤,咱们大大减少了编码耗费,然而为了可能疾速响应用户切视角,咱们必须把所有源视角的原始画面 Frame(YUV420)筹备好,当须要产生新的 GOP 时,能够间接应用。然而需要总是变动的,4 个视角时,咱们能够对 4 3=12 路流都进行事后解码,当业务方要 9 3=27 路流时,同时解码 27 路 1080p 视频数据使得整个 32 核机器不堪重负,更何况当前还可能要求更多路源流。
按需解码
用户想要更多的视角,咱们须要满足。那么之前全副事后解码的形式必须扭转,所以咱们实现了按需解码,也就是只有真的须要解码时,才去为它筹备那路流的 Frame(YUV420)。这里最大的问题就是实时性的问题,因为当用户切换时,画面可能处于一个 GOP 的任意地位,而咱们只能从 GOP 的开始帧进行解码。不过通过屡次优化,做到了出现给用户的提早不会被感知的成果。
客户端动静缓存
做过音视频的同学都应该对卡顿率很相熟,年年治理总是不够现实,多视角直播则面临更麻烦的问题,因为如果升高卡顿率,最根本的做法是增大播放缓存,然而咱们又心愿用户可能迅速看到新的视角,就要求缓存不能太高。所以咱们引入了动静缓存,简略来讲就是当用户切换时,咱们采纳极低水位缓存,保障切换体验,而当用户不切换时,缓存会缓缓复原到肯定水位,保障肯定水平反抗网络抖动。
总结与瞻望
多视角能力在街舞总决赛正式上线,作为优酷独翻新玩法,收到了来自于微博、朋友圈等宽广用户的诸多正向反馈。后续优酷打算将通过交互优化,时延优化等形式,进一步晋升用户体验。
关注【阿里巴巴挪动技术】微信公众号,每周 3 篇挪动技术实际 & 干货给你思考!