HLS 协议向全球规模的受众提供实时和点播内容流。从历史上看,HLS 更倾向于流可靠性而不是延迟。低延迟 HLS 扩展了协议,以实现低延迟视频流,同时保持可扩展性。新的低延迟模式将公共网络上的视频延迟降低到标准电视广播的范围内。
后端制作工具和内容交付系统必须实施新规则,以实现低延迟流播放。低延迟 HLS 在以下方面提供了新功能:
生成部分段
播放列表增量更新
阻止播放列表重新加载
使用预加载提示
格式副本报告
HLS 规范在 HTTP 实时流式处理第 2 版修订版 7 及更高版本中定义了低延迟扩展。
低延迟 HLS 提供了一个并行通道,用于在媒体播放列表的实时边缘分发媒体,该通道将媒体划分为大量较小的文件,例如 CMAF 块。这些较小的文件称为 HLS 部分段。由于每个部分片段的持续时间都很短,因此可以比其父片段更早地打包、发布并添加到媒体播放列表中。
常规媒体段可能每个为 6 秒,而示例部分片段可能只有 200 毫秒。第一个部分段可能在前一个分段发布后仅 200 毫秒发布,然后是其 29 个对等段,最后是一个常规长度的 6 秒媒体段,其中包含与其 30 个部分段的串联相同的媒体。为了减少播放列表膨胀,服务器会在部分片段大于(旧)实时边缘的三个目标持续时间时从媒体播放列表中删除它们。
您可以使用新的 EXT-X-PART 标签将部分片段添加到媒体播放列表中。您可以将其他媒体段标签(例如 EXT-X-DISCONTINUITY)放置在父区段边界。
部分分段必须采用 HTTP 实时流式传输第 2 版第 3.1 节中所述的受支持的媒体段格式之一。
客户端使用低延迟 HLS 更频繁地传输播放列表。他们可以请求,服务器可以提供播放列表增量更新,从而降低此传输成本。这些更新将客户端已有的播放列表的相当一部分替换为新的 EXT-X-SKIP 标记。
为了支持新媒体段和部分片段的高效客户端通知,低延迟 HLS 引入了阻止播放列表重新加载请求的功能。当客户端发出 HTTP GET 以请求媒体播放列表更新时,它可以添加称为传递指令的特殊查询参数,以指定它希望播放列表响应包含未来的段。然后,服务器保留请求(块),直到包含该段的播放列表版本可用。阻止播放列表重新加载可消除播放列表轮询。
在全球范围内交付低延迟流时,消除不必要的往返至关重要。服务器使用新标记 EXT-X-PRELOAD-HINT 来通知客户端即将推出的部分段和媒体初始化部分。客户端可以提前发出对提示资源的 GET 请求;一旦介质可用,服务器就会响应请求。
以低延迟播放时,客户端必须能够以最少的往返次数切换演绎版,以便执行比特率自适应。为了支持此功能,服务器将多变量播放列表中其他格式副本的格式副本报告添加到每个媒体播放列表中。EXT-X-格式副本报告标记带有格式副本报告,并提供信息,例如该格式副本的媒体播放列表中当前中的最后一个媒体序列号和部分。
HLS 现在定义了传递指令,这些指令是可以添加到播放列表的 GET 请求 URL 的特殊查询参数。这些交付指令包括:
_HLS_msn=
指示服务器必须保留请求,直到播放列表包含媒体序列号为 M 或更高版本的媒体段。
_HLS_part=
结合_HLS_msn指示服务器必须保留请求,直到播放列表包含媒体序列号 M 或以后的部分段 N。段的第一个部分段为 _HLS_part=0,第二个段为 _HLS_part=1,依此类推。_HLS_part参数需要_HLS_msn参数。
_HLS_skip=是|v2
请求播放列表增量更新,其中播放列表的早期部分将替换为 EXT-X-SKIP 标记。
以下播放列表标签支持低延迟 HLS。
EXT-X-SERVER-CONTROL
允许服务器指示对阻止播放列表重新加载和播放列表增量更新等功能的支持。
EXT-X-PART-INF
提供有关播放列表中 HLS 部分片段的信息。
EXX-部件
标识播放列表中的部分片段。
EXT-X-PRELOAD-HINT
提示需要资源或资源的字节范围来播放演示文稿的后续部分。
请注意,当提示的部分片段最终作为 EXT-X-PART 标签显示在播放列表中时,它可能与之前的部分片段不同。它可能具有不同的不连续序列号、介质初始化部分或加密配置。换句话说,部分段前面可以有一个 EXTINF 标签,指示前一个父段的结束,以及一个 EXT-X-DISCONTINUITY、EXT-X-MAP 或 EXT-X-KEY 标签。
如果计划的细分发生变化,服务器可以选择不发布之前提示的部分细分,例如在广告提前返回的情况下。
EXT-X-RENDITION-REPORT
包含有关关联格式副本的信息,该格式副本与包含它的播放列表一样最新。
EXT-X-SKIP
当服务器发出播放列表增量更新时,它会将早于跳过边界的媒体段及其关联的标记替换为 EXT-X-SKIP 标记。
为了支持及时交付媒体,低延迟 HLS 需要某些传输功能,这些功能超出了常规 HLS 所需的功能。这些要求在低延迟服务器配置文件中定义。由于低延迟 HLS 语法与现有 HLS 向后兼容,因此如果客户端发现服务器不支持所需配置的某个方面,则它们将回退到常规延迟 HLS 播放。HTTP 实时流式传输第 2 版在附录 B 中定义了低延迟服务器配置文件。
低延迟 HLS 的玩家应该期望通过 CDN 和其他 HTTP 缓存交付低延迟流。若要以低延迟开始播放,客户端必须首先获取媒体播放列表的合理最新版本。HTTP 实时流第 2 版的附录 C 描述了一种通过 HTTP 缓存获取最新媒体播放列表的有效方法。
下面是一个低延迟播放列表的示例。
#EXTM3U
# This Playlist is a response to: GET https://example.com/2M/waitForMSN.php?_HLS_msn=273&_HLS_part=2
#EXT-X-TARGETDURATION:4
#EXT-X-VERSION:6
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=1.0,CAN-SKIP-UNTIL=12.0
#EXT-X-PART-INF:PART-TARGET=0.33334
#EXT-X-MEDIA-SEQUENCE:266
#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:13:36.106Z
#EXT-X-MAP:URI="init.mp4"
#EXTINF:4.00008,
fileSequence266.mp4
#EXTINF:4.00008,
fileSequence267.mp4
#EXTINF:4.00008,
fileSequence268.mp4
#EXTINF:4.00008,
fileSequence269.mp4
#EXTINF:4.00008,
fileSequence270.mp4
#EXT-X-PART:DURATION=0.33334,URI="filePart271.0.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.2.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.3.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.4.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart271.5.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.6.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.7.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.8.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart271.9.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.10.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.11.mp4"
#EXTINF:4.00008,
fileSequence271.mp4
#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:14:00.106Z
#EXT-X-PART:DURATION=0.33334,URI="filePart272.a.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.b.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.c.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.d.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.e.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.f.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart272.g.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.h.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.i.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.j.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.k.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.l.mp4"
#EXTINF:4.00008,
fileSequence272.mp4
#EXT-X-PART:DURATION=0.33334,URI="filePart273.0.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart273.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart273.2.mp4"
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="filePart273.3.mp4"
#EXT-X-RENDITION-REPORT:URI="../1M/waitForMSN.php",LAST-MSN=273,LAST-PART=2
#EXT-X-RENDITION-REPORT:URI="../4M/waitForMSN.php",LAST-MSN=273,LAST-PART=1
下面是播放列表增量更新的示例。
#EXTM3U
# Following the example above, this Playlist is a response to: GET https://example.com/2M/waitForMSN.php?_HLS_msn=273&_HLS_part=3 &_HLS_skip=YES
#EXT-X-TARGETDURATION:4
#EXT-X-VERSION:9
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=1.0,CAN-SKIP-UNTIL=12.0
#EXT-X-PART-INF:PART-TARGET=0.33334
#EXT-X-MEDIA-SEQUENCE:266
#EXT-X-SKIP:SKIPPED-SEGMENTS=3
#EXTINF:4.00008,
fileSequence269.mp4
#EXTINF:4.00008,
fileSequence270.mp4
#EXT-X-PART:DURATION=0.33334,URI="filePart271.0.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.2.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.3.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.4.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart271.5.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.6.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.7.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.8.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart271.9.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.10.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart271.11.mp4"
#EXTINF:4.00008,
fileSequence271.mp4
#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:14:00.106Z
#EXT-X-PART:DURATION=0.33334,URI="filePart272.a.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.b.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.c.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.d.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.e.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.f.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart272.g.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.h.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.i.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.j.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.k.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart272.l.mp4"
#EXTINF:4.00008,
fileSequence272.mp4
#EXT-X-PART:DURATION=0.33334,URI="filePart273.0.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="filePart273.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart273.2.mp4"
#EXT-X-PART:DURATION=0.33334,URI="filePart273.3.mp4"
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="filePart273.4.mp4"
#EXT-X-RENDITION-REPORT:URI="../1M/waitForMSN.php",LAST-MSN=273,LAST-PART=3
#EXT-X-RENDITION-REPORT:URI="../4M/waitForMSN.php",LAST-MSN=273,LAST-PART=3
下面是字节范围寻址部分的示例。
# In these examples only the end of the Playlist is shown.
# This is Playlist update 1
#EXTINF:4.08,
fs270.mp4
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="20000@0"
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="23000@20000"
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="18000@43000"
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="fs271.mp4",BYTERANGE-START=61000
# This is Playlist update 2
#EXTINF:4.08,
fs270.mp4
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="20000@0"
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="23000@20000"
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="18000@43000"
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="19000@61000"
#EXTINF:4.08,
fs271.mp4
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="fs272.mp4",BYTERANGE-START=0
# This is Playlist update 3
#EXTINF:4.08,
fs270.mp4
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="20000@0"
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="23000@20000"
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="18000@43000"
#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE="19000@61000"
#EXTINF:4.08,
fs271.mp4
#EXT-X-PART:DURATION=1.02,URI="fs272.mp4",BYTERANGE="21000@0"
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="fs272.mp4",BYTERANGE-START=21000