写点什么

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

  • 2020-01-19
  • 本文字数:4368 字

    阅读完需:约 14 分钟

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

一、课堂腾讯云点播 HLS 播放

1. HLS 浅析

(1) HLS 协议


点播业务目前用的是 HLS 协议。HLS 协议全称是 HTTP Live Streaming,它是一个由苹果提出的基于 HTTP 的流媒体网络传输协议。HLS 协议规定:


  • 视频的封装格式是 TS;

  • 视频编码格式为 H264,音频编码格式为 MP3、AAC 或者 AC-3;

  • 除了 TS 视频文件本身,还定义了用来控制播放的 m3u8 文件。


HLS 的工作流程如下图(来源苹果官网)所示:



  • 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 文件并连续播放。



以企鹅辅导为例,一级 index(master_playlist.m3u8)文件如下图所示:



  • #EXTM3U —表明该文件是一个 m3u8 播放列表文件,必须在第一行给出;

  • #EXT-X-VERSION:3 —播放列表文件的版本,现在主流版本是 3;

  • #EXT-X-STREAM-INF —不同码率的数据流 ;

  • PROGRAM-ID=0 —唯一标记;

  • BANDWIDTH=92166 —这个值是十进制整数代表每秒钟的比特率,这个值必须是整个播放列表中码率的峰值;

  • RESOLUTION=384x288 —视频流的分辨率。


二级 index(对应任意一个清晰度)文件如下图所示:



  • #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 的播放流程如下图所示:



该流程存在一些缺点,比如:用户播放视频的时候可能等待的时间较长,造成流量的浪费,无法做缓存、预加载等优化策略等。


(2) 通过本地代理播放


基本流程如下图所示:



企鹅辅导详细流程如下图所示:



具体流程可以概括为:


  • 启动本地代理服务器(一期采用 mongoose);

  • 视频源地址传给本地代理服务器;

  • 将视频源地址转换成本地代理服务器(127.0.0.1)的地址作为播放器的视频源地址;

  • 播放器向本地代理服务器发送请求;

  • 本地代理服务器截取这个请求,再根据解析出来请求的信息向远端服务器发起请求;

  • 本地代理服务器开始接受数据,写入文件并将文件数据再返回到播放器;

  • 播放器接收到这些数据之后播放。


目前是使用 mongoosehttps://github.com/cesanta/mongoose)来实现本地 Http Server,在这里简单介绍一下 mongoose。


mg_mgr:用于管理连接、事件等的 Manager ;mg_connection:单个连接,保存了连接信息。


主要用法步骤


  1. 调用 mg_mgr_init 进行初始化;

  2. 调用 mg_bind,第 2 个参数为需要监听的端口号,第 3 个参数为处理请求的 handler;

  3. 调用 mg_set_protocol_http_websocket 将上一步返回的 mg_connection 与内建的 http handler 绑定。这样我们的 handler 才能收到 http 事件;

  4. 通过一直调用 mg_mgr_poll 接收请求。


(3) Cache 功能


使用本地代理一个重要作用就是 Cache。


  1. 首先缓存 m3u8 文件内容;

  2. 当播放器请求第 1 个 ts 分片,异步请求下一个 ts 分片并缓存数据;

  3. 当播放器请求分片 data 时,内存有就内存返回,内存没有就向远端 Server 请求。


缓存淘汰


假定用户经常看的视频不能优先淘汰,那么用 LFU 淘汰策略即可。每个缓存块设置一个 count,缓存命中一次就 count++,触发淘汰的时候,把 count 最小的先淘汰。


流量控制


例如用户只看了视频前面一点,就暂停了,那么后面的视频不再下载等,具体细节后续文章将会详细说明。


seek


播放视频的时候,用户会拖动进度条进行 seek,与 mp4 文件不同,对于 hls 文件 ffplay 会根据 seek 的 position,向本地服务器请求 seek 的 position 所在的 ts 分片。

3. 腾讯课堂云点播在线播放时序图解析


如上图所示:


  • 第一步通过业务 get_token 协议拿到防盗链需要的 Key。这里需要注意的是防盗链的 Key 顺序一定要按照腾讯云文档中的顺序,带 KEY 防盗链的视频播放地址的校验工具;

  • 第二步通过腾讯云 getplayinfo 协议拿到播放的链接,这里的链接 master 和 transcodelist 都会返回;

  • 第三步在请求的 URL 中拼接 voddrm.token 参数,用于鉴权;

  • 第四步将请求的 URL 透传给教育自研的播放器 ARMPlayer,ARMPlayer 会启动本地代理,请求数据/解码/渲染。课堂采用的是 HLS 加密 [1],所以播放的时候还需要通过 DK(密钥)进行 TS 解密。

4. 课堂腾讯云点播本地播放时序图解析


如上图所示:


  • 第一步启动本地代理,通过上层透传的本地存储的 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 每次都需要拉取。



点播首帧优化前请求流程

这里面可能会涉及到一些问题,下面给出它们的解决方案。

问题 1:master.m3u8 透传给 FFmpeg,FFmpeg 会串行拉取 3 个清晰度的 m3u8 及第 1 个 TS 分片。



指定清晰度.m3u8


解决方案:


  • getplayinfo 协议直接获取指定清晰度 m3u8,减少 master.m3u8 ->清晰度.m3u8 的网络请求;

  • 播放器从 master.m3u8 改为指定清晰度.m3u8 透传给 FFmpeg,减少 avformat_find_stream_info 串行拉取 3 个清晰度和第 1 个 TS 分片的耗时。


问题 2:DNS 解析耗时高。



DNS 缓存


解决方案


  • 增加 DNS 结果缓存模块,缓存“{域名: IP}”;

  • 视频播放时,直接查表,取出域名对应的 IP 地址。


问题 3:每个清晰度.m3u8 大小是 400kb 左右,拉取慢


解决方案


  • 预加载;

  • 预加载策略

  • 预加载学生报名直播课结束 1 周内的 m3u8 数据和指定位置的 TS、DK。


问题 4:DK 和 TS 每次都需要拉取



本地代理缓存


解决方案


播放器设计了一个本地代理层,播放器不直连远端 server,而是通过本地代理层发出请求,通过本地代理层实现缓存和读取本地资源进行播放。

2. 播放成功率优化

对于播放成功率,最主要是要完善监控系统以及对出现的问题各个击破,目前遇到的主要问题和解决方式如下:



主要问题和解决方式 1



主要问题和解决方式 2

3. 播放体验优化

  • ffplay 音视频同步;

  • 企鹅辅导录播多路视频流精确对齐。



精确 Seek 流程

4. 下载优化

  • 下载成功率

  • 因为教育自研的播放器下载和播放底层库共用,所以除了播放出现的类似问题,下载方面我们还针对存储、写磁盘、安全性做了优化,已下载视频采取 DB 分级映射缓存。

  • 下载速度

  • 因为 HLS 是由无数个 TS 和 DK 构成,如果是单线程下载,每次请求一个 TS 和 DK 地址都将重新建立连接,所以这里我们采用的是多线程以及播放缓存复用逻辑。

5. 缓冲优化

这里存在两个问题,下面来做出解决方案。


问题 1:旧播放器在读数据 -> 解封装 -> 解码 -> 渲染链路上均出现过因为抖动而出现的缓冲。



缓冲区


解决方案


  • 帧缓冲区,抵抗网络抖动和解码抖动;

  • 显示缓冲区,抵抗渲染抖动。


问题 2:旧播放器是顺序存储同时没有异步请求后面的 TS 分片和 DK。



多线程和存储


解决方案


  • 顺序存储和 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


本文转载自公众号云加社区(ID:QcloudCommunity)。


原文链接


https://mp.weixin.qq.com/s/JdyL3VriaFegcoQcDj6KsQ


2020-01-19 15:085655

评论

发布
暂无评论
发现更多内容

【Zeekr_Tech】为自动驾驶保驾护航—谈谈主流中间件设计

Zeekr_Tech

自动驾驶 软件架构

电阻电路的等效变换(Ⅰ)

謓泽

3月月更

Linux之export命令

入门小站

前Cisco思科首席工程师、Webex AV1第一人Thomas加入微帧科技!

微帧Visionular

视频编码

聊聊我对敏捷项目交付的理解

老张

交付质量 项目交付

面试官:你在项目中用过 多线程 吗?

田维常

Java 开发 多线程编发编程

最终信息模式:终结香农极限,语义通信的另类空间

脑极体

华为云企业级Redis揭秘第17期:集群搭载多DB,多租隔离更降本

华为云开发者联盟

数据库 redis 集群 GaussDB(for Redis) 多DB

数字人民币为全球CBDC监管提供宝贵经验

CECBC

去你的35岁危机|ONES 人物

万事ONES

程序员 ONES

超级app+轻应用=未来?

發財KK

移动应用 轻应用 快应用 App生态

区块链的支付模式

CECBC

在线Js,JavaScript压缩格式化工具

入门小站

工具

技术平台&应用开发专题月 | 国产化替代的本质是价值替代

用友BIP

用友 用友iuap

都是让小程序在app运行,FinClip 与 uniapp有什么区别?

發財KK

小程序 uni-app 前端开发 sdk

小程序加入智能家居行业,共创未来美好生活

發財KK

物联网 小程序容器 智慧生活 全屋智能 智能家居生态平台

女性开发者为您解读数据库的未来机遇与挑战

亚马逊云科技 (Amazon Web Services)

Hero 专栏

创业圈的哈利波特们注意了!霍格沃兹即将开学,谁是你的魔法导师?

创业邦

我们如何建立一套无参考视频质量评价体系?

声网

视频 Dev for Dev VQA

5G区块链技术让建水紫陶有了“身份证”

CECBC

cdr2022新版本号V24.0.0301简体语言新增功能

茶色酒

cdr2022

WebAssembly技术_在Web端运行C与C++程序(win10)

DS小龙哥

webassembly 3月月更

我写的 Python 代码,同事都说好

AlwaysBeta

Python Pythonic

java高级用法之:在JNA中将本地方法映射到JAVA代码中

程序那些事

Java Netty 程序那些事 3月月更

在线JSON转YAML工具

入门小站

工具

关注:车联网的数据安全问题

發財KK

车联网 物联网 数据安全 隐私安全 信息服务

阿里云云原生应用平台总经理丁宇:“连接、合作、赋能”,携手加速器伙伴助力企业云上创新

阿里巴巴云原生

元宇宙跟区块链的关系是什么呢?

CECBC

使用云服务器ECS搭建DoH服务的开发实践

阿里云弹性计算

征文投稿 玩转ECS DoH

AI与开源的碰撞 昇思MindSpore TechDay直播来袭

Geek_2d6073

面试官:你在项目中用过 多线程 吗?

田维常

面试 java面试

腾讯课堂点播上云客户端实践总结_安全_云加社区_InfoQ精选文章