腾讯课堂点播上云客户端实践总结

qcloudcommunity · · 1372 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

> 导语 | 自从2018年企鹅辅导直播、点播和腾讯课堂直播上云以后,19年上半年腾讯课堂点播也开始自研上云。本文是对腾讯课堂点播上云客户端方案的整理与总结,希望能与各位同行一起交流。 ### 一、课堂腾讯云点播 HLS 播放 #### 1. HLS 浅析 ##### (1) HLS 协议 点播业务目前用的是 HLS 协议。HLS协议全称是 HTTP Live Streaming,它是一个由苹果提出的基于HTTP的流媒体网络传输协议。HLS协议规定: 视频的封装格式是TS; 视频编码格式为H264,音频编码格式为MP3、AAC或者AC-3; 除了TS视频文件本身,还定义了用来控制播放的m3u8文件。 HLS的工作流程如下图(来源苹果官网)所示: ![alt](https://pic4.zhimg.com/80/v2-50d6c9b5d361360e266513610c435ed3_hd.jpg) Server Server获取媒体输入流,Media编码 MPEG-4(H.264 video 和 AAC audio),然后打包到 MPEG-2 (MPEG-2 transport stream)的传输流中,传输流会经过Stream segmenter,MPEG-2传输流会被分散为小片段然后保存为一个或多个系列的 .ts 格式的媒体文件。 Distribution Stream segmenter会创建一个索引文件,通常会包含这些媒体文件的一个列表,也能包含元数据,一般都是一个.m3u8的列表,列表元素会关联一个 URL 用于客户端访问,然后按序去请求这些 URL。 Client Client主要接受Client客户端请求并提供相关联的资源给客户端。 ##### (2)HLS 的 index 文件 index 文件就是 m3u8 文本文件,如下图(来源苹果官网)所示。客户端播放HLS视频流的逻辑是先下载一级 Index file,它里面记录了二级索引文件(Alternate-A、Alternate-B、Alternate-C)的地址,然后客户端再去下载二级索引文件,二级索引文件中记录了 TS、dk 的下载地址,这样客户端就可以按顺序下载 TS、dk 文件并连续播放。 ![alt](https://pic3.zhimg.com/80/v2-5b573a950dd5e7de9776d9f401c5798e_hd.jpg) 以企鹅辅导为例,一级 index(master_playlist.m3u8)文件如下图所示: ![alt](https://pic1.zhimg.com/80/v2-183c2543a76d9f21c2311fe144565144_hd.jpg) #EXTM3U ---表明该文件是一个m3u8播放列表文件,必须在第一行给出; #EXT-X-VERSION:3 ---播放列表文件的版本,现在主流版本是3; #EXT-X-STREAM-INF ---不同码率的数据流 ;  PROGRAM-ID=0 ---唯一标记; BANDWIDTH=92166 ---这个值是十进制整数代表每秒钟的比特率,这个值必须是整个播放列表中码率的峰值; RESOLUTION=384x288 ---视频流的分辨率。 二级 index(对应任意一个清晰度)文件如下图所示: ![alt](https://pic4.zhimg.com/80/v2-291c9e039b87b73f4208eccd275f9243_hd.jpg) #EXT-X-KEY ---媒体文件有可能要被加密,该标签描述了如何解密媒体文件; METHOD ---包括NONE、AES-128、和SAMPLE-AES。如果该值是NONE或播放列表没有定义该标签,表示媒体段没有被加密。如果设置了NONE,则其他属性不会出现。其中AES-128表示媒体是由AES-128标准构造的的128bit的 key,和密码块链接(CBC)和PKCS7加密组成的,URI 参数必须出现在METHOD后面; URI ---描述了如何获取key文件; IV ---IV可以不存在,如果没有IV则使用序列号作为IV进行编解码,将序列号的高位赋到16字节的buffer中,左边补0,如果有IV,则将该值作为16字节的16进制数; #EXT-X-MEDIA-SEQUENCE ---m3u8播放列表中第一个出现的媒体段的序列号; #EXT-X-TARGETDURATION ---该标签描述了媒体段的最大时长,EXTINF后面的实际媒体段时长不能超过这个标签描述的值,否则会引起错误; #EXTINF ---该标签描述了媒体段的时长,在3.0版本后时长可以是浮点数,否则必须是整数。 #### 2. 播放器本地代理 ##### (1) 播放器直连Server 以企鹅辅导为例,播放器直连远端Server的播放流程如下图所示: ![alt](https://pic3.zhimg.com/80/v2-6c9947094f26c4c772987c8eaf1280f6_hd.jpg) 该流程存在一些缺点,比如:用户播放视频的时候可能等待的时间较长,造成流量的浪费,无法做缓存、预加载等优化策略等。 ##### (2) 通过本地代理播放 基本流程如下图所示: ![alt](https://pic3.zhimg.com/80/v2-6810d35fc6bd8eef6eb38109184384da_hd.jpg) 企鹅辅导详细流程如下图所示: ![alt](https://pic1.zhimg.com/80/v2-a1466e77f1396916c927c689c8368be0_hd.jpg) 具体流程可以概括为: 启动本地代理服务器(一期采用mongoose); 视频源地址传给本地代理服务器; 将视频源地址转换成本地代理服务器(127.0.0.1)的地址作为播放器的视频源地址; 播放器向本地代理服务器发送请求; 本地代理服务器截取这个请求,再根据解析出来请求的信息向远端服务器发起请求; 本地代理服务器开始接受数据,写入文件并将文件数据再返回到播放器; 播放器接收到这些数据之后播放。 目前是使用mongoose(https://github.com/cesanta/mongoose)来实现本地Http Server,在这里简单介绍一下mongoose。 mg_mgr:用于管理连接、事件等的 Manager ;mg_connection:单个连接,保存了连接信息。 主要用法步骤: 调用mg_mgr_init进行初始化; 调用mg_bind,第2个参数为需要监听的端口号,第3个参数为处理请求的handler; 调用mg_set_protocol_http_websocket将上一步返回的mg_connection与内建的http handler绑定。这样我们的handler才能收到http事件; 通过一直调用mg_mgr_poll接收请求。 ##### (3) Cache功能 使用本地代理一个重要作用就是Cache。 首先缓存m3u8文件内容; 当播放器请求第1个ts分片,异步请求下一个ts分片并缓存数据; 当播放器请求分片data时,内存有就内存返回,内存没有就向远端Server请求。 缓存淘汰: 假定用户经常看的视频不能优先淘汰,那么用 LFU 淘汰策略即可。每个缓存块设置一个count,缓存命中一次就 count++,触发淘汰的时候,把 count 最小的先淘汰。 流量控制: 例如用户只看了视频前面一点,就暂停了,那么后面的视频不再下载等,具体细节后续文章将会详细说明。 seek: 播放视频的时候,用户会拖动进度条进行seek,与 mp4 文件不同,对于 hls 文件 ffplay 会根据 seek 的 position,向本地服务器请求 seek 的 position 所在的  ts 分片。 #### 3. 腾讯课堂云点播在线播放时序图解析 ![alt](https://pic3.zhimg.com/80/v2-6c9947094f26c4c772987c8eaf1280f6_hd.jpg) 如上图所示: 第一步通过业务 get_token 协议拿到防盗链需要的Key。这里需要注意的是防盗链的Key顺序一定要按照腾讯云文档中的顺序,带KEY防盗链的视频播放地址的校验工具; 第二步通过腾讯云 getplayinfo 协议拿到播放的链接,这里的链接 master和 transcodelist 都会返回; 第三步在请求的 URL 中拼接 voddrm.token 参数,用于鉴权; 第四步将请求的 URL 透传给教育自研的播放器 ARMPlayer,ARMPlayer会启动本地代理,请求数据/解码/渲染。课堂采用的是HLS加密 [1],所以播放的时候还需要通过DK(密钥)进行TS解密。 #### 4. 课堂腾讯云点播本地播放时序图解析 ![alt](https://pic1.zhimg.com/80/v2-a1466e77f1396916c927c689c8368be0_hd.jpg) 如上图所示: 第一步启动本地代理,通过上层透传的本地存储的URL,读取DB中的指定清晰度的 m3u8 链接和指定清晰度的 m3u8 的内容; 第二步改写 m3u8 链接和 DK/TS 的域名为:127.0.0.1; 第三步请求本地 DK 和 TS 数据; 第四步解密/解封装/渲染。 ### 二、课堂腾讯云点播优化 #### 1. 首帧优化 首帧的主要耗时点有: master.m3u8 透传给FFmpeg,FFmpeg 会串行拉取3个清晰度的m3u8及第1个TS分片; DNS解析耗时高; 每个清晰度.m3u8大小是400kb左右,拉取慢; DK和TS每次都需要拉取。 ![alt](https://pic1.zhimg.com/80/v2-9566ed2816bafe9978e25f3dbfedc4c8_hd.jpg) 点播首帧优化前请求流程  这里面可能会涉及到一些问题,下面给出它们的解决方案。 问题1:master.m3u8透传给FFmpeg,FFmpeg会串行拉取3个清晰度的m3u8及第1个TS分片。 ![alt](https://pic3.zhimg.com/80/v2-4f7f0f51b81adbe3c10954cb4f0416de_hd.jpg) 指定清晰度.m3u8  解决方案: getplayinfo协议直接获取指定清晰度m3u8,减少master.m3u8 ->清晰度.m3u8的网络请求; 播放器从master.m3u8改为指定清晰度.m3u8透传给FFmpeg,减少avformat_find_stream_info串行拉取3个清晰度和第1个TS分片的耗时。 问题2:DNS解析耗时高。 ![alt](https://pic4.zhimg.com/80/v2-01157935dba6dcdf125f481049cbbac3_hd.jpg)  DNS缓存  解决方案: 增加DNS结果缓存模块,缓存“{域名: IP}”; 视频播放时,直接查表,取出域名对应的IP地址。 问题3:每个清晰度.m3u8大小是400kb左右,拉取慢 解决方案: 预加载; 预加载策略 预加载学生报名直播课结束1周内的m3u8数据和指定位置的TS、DK。 问题4:DK和TS每次都需要拉取 ![alt](https://pic2.zhimg.com/80/v2-ba2e6cede6747224879de979be0b03bd_hd.jpg)  本地代理缓存  解决方案: 播放器设计了一个本地代理层,播放器不直连远端server,而是通过本地代理层发出请求,通过本地代理层实现缓存和读取本地资源进行播放。 #### 2. 播放成功率优化 对于播放成功率,最主要是要完善监控系统以及对出现的问题各个击破,目前遇到的主要问题和解决方式如下: ![alt](https://pic4.zhimg.com/80/v2-63cd0e0cdd47c41a43a41cc6fab4ecb3_hd.jpg)  主要问题和解决方式1  ![alt](https://pic2.zhimg.com/80/v2-a09c680cfa9e37ed878e49159cfde879_hd.jpg)  主要问题和解决方式2  #### 3. 播放体验优化 ffplay音视频同步; 企鹅辅导录播多路视频流精确对齐。 ![alt](https://pic4.zhimg.com/80/v2-df32b8d3f1f8f5fca49a313c2f40f577_hd.jpg)  精确Seek流程  #### 4. 下载优化 下载成功率 因为教育自研的播放器下载和播放底层库共用,所以除了播放出现的类似问题,下载方面我们还针对存储、写磁盘、安全性做了优化,已下载视频采取DB分级映射缓存。 下载速度 因为HLS是由无数个TS和DK构成,如果是单线程下载,每次请求一个TS和DK地址都将重新建立连接,所以这里我们采用的是多线程以及播放缓存复用逻辑。 #### 5. 缓冲优化 这里存在两个问题,下面来做出解决方案。 问题1:旧播放器在读数据 -> 解封装 -> 解码 -> 渲染链路上均出现过因为抖动而出现的缓冲。 ![alt](https://pic4.zhimg.com/80/v2-995f7511bcb5c368b0a5573cc11cb6e3_hd.jpg)  缓冲区  解决方案: 帧缓冲区,抵抗网络抖动和解码抖动; 显示缓冲区,抵抗渲染抖动。 问题2:旧播放器是顺序存储同时没有异步请求后面的TS分片和DK。 ![alt](https://pic3.zhimg.com/80/v2-98c04892ca856c30520adf822d8d4d0a_hd.jpg)  多线程和存储  解决方案: 顺序存储和Seek之后的非顺序存储; 多线程异步请求。 #### 6. 安全性优化 防盗链,腾讯云防盗链主要有2种形式Referer防盗链和Key防盗链,目前课堂采用的是Key防盗链,腾讯云防盗链[2]; HLS加密; 水印。 ### 三、课堂腾讯云点播踩过的坑 因为腾讯课堂不仅是新生成或上传的视频要上云,同时对于之前存量的几百万MP4视频要重新转码上传到云上,这个过程中容易踩到不少坑。这里提供一些常见的问题以及解决方案。 #### 1. 转码出的视频清晰度不全 这里主要有2个原因:机构上传的视频清晰度较低,低转高不一定能转码出来,其次1080p不一定能转成功。 解决方案: 后台重新转码; 客户端健壮性,对于清晰度缺少的视频播放和下载采用降级策略,降级到最近的清晰度最清晰的视频。 #### 2. 获取腾讯云播放链接是通过getplayinfo接口 回包中包括 master.m3u8 和 transcodelist 两个信息,出现 master.m3u8 包含的清晰度个数和 transcodelist 清晰度个数不一致。 解决方案:后台重新转码。 #### 3. 播放提前结束或seek不准确 HLS标准中的EXTINF 标志的切片时间总和和TS分片实际的时间总和不一致,导致播放提前结束和Seek不准确。 解决方案:后台重新转码 #### 4. 录播视频经过腾讯云转码出现拉伸 机构上传的原视频不是标准的720,腾讯云重新转码会出现拉伸。 解决方案:后台重新转码。 #### 5. 播放一直加载中 因为存量视频从原来的MP4视频切到HLS,偶现从后台拉到的用户上一次MP4播放进度同步到HLS,超过了HLS视频总时长, 播放一直loading 解决方案:客户端容错, 超过视频总时长将 Position 置为0。 除了上面视频本身可能会出现的坑,还有客户端灰度期间兼容两种视频源同时存在切换、Next学位和普通课程、回放分段视频切换等也容易踩坑。目前课堂建立了完善的监控,第一时间发现解决问题。 从辅导到课堂,直播回放全量上云,各项数据和用户体验都有了很大的提升,欢迎大家一起参与腾讯课堂点播上云,一起为教育点播保驾护航! **参考资料:** [1] HLS 加密: https://cloud.tencent.com/document/product/266/9638 [2] 腾讯云防盗链: https://cloud.tencent.com/document/product/266/14047 欢迎关注「云加社区」,腾讯在线教育部上云实践系列文章将会陆续上线。 ![alt](https://pic1.zhimg.com/v2-9a8d132a85a2f2d7b23850be16f61d5c_b.jpg) ———————————————— 版权声明:本文为CSDN博主「QcloudCommunity」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/QcloudCommunity/article/details/103932740

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1372 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传