使用带有字节范围寻址的LL-HLS来实现低延迟流中的互操作性

2020-12-11 10:46:55 浏览数 (1)

本文为媒矿工厂翻译的技术文章

原标题:Using LL-HLS with Byte-range Addressing to Achieve Interoperability in Low Latency Streaming

原作者:Will Law

原文链接:https://blogs.akamai.com/2020/11/using-ll-hls-with-byte-range-addressing-to-achieve-interoperability-in-low-latency-streaming.html

翻译整理:郝明月

01

PART

介绍

随着移动网络,Microsoft平滑流,Apple HLS,Adobe HDS和MPEG DASH的出现,HTTP自适应分段(HAS)流从2008年到2012年开始大规模使用。在典型的10s分段时长下,直播延迟(从拍摄一个动作到在设备屏幕上显示同一动作的时间的延迟)保持在30s到60s的范围内,大大落后于广播。在接下来的十年中,分段时长减少到2s,等待时间也随之减少到8s至16s,该范围仍然是当今许多直播场景的典型延迟时间。2020年给业界带来了两个针对2s范围内的延迟的HAS标准:低延迟DASH(LL-DASH)和低延迟HLS(LL-HLS)。这两个标准都是独立开发的,尽管它们可以作为单独的流部署在内容交付系统中,但是如果两种流格式都可以由一套媒体内容集服务,则打包程序,原始文件,CDN和播放器将获得性能和成本优势。

HLS规范已更新到版本10。在众多改进中,LL-HLS引入了部分分段(“parts”)的概念。每个部分都可以通过唯一的URL分散寻址,也可以选择作为媒体段中引用的字节范围来寻址。绝大多数早期实现都集中在分散的部分寻址模式上。但是,基于范围的寻址具有一些性能优势,同时有助于增加LL-DASH解决方案的互操作性和CDN效率。它还对跨通用代理缓存实现有一些性能的提升。

本文将研究使用基于范围的寻址可以解决的问题,使其有效运行所要满足的要求以及通过大规模部署它可以获得的好处。

02

PART

缓存效率

从低延迟和标准延迟的HLS和DASH客户端混合使用时在边缘的缓存效率开始,它们都播放相同的内容。缓存是CDN扩展支持HTTP的流的方法。可以缓存的内容越多,性能越好,成本也越低。对于一个具有4s段和1s部分的LL-HLS流,图1显示了所有需要在4s窗口中的边缘缓存的对象,数量很多,有些比其他大,我们可以通过图形化缩放它们以使面积与大小成比例来突出显示此差异。图1显示视频片段占用的空间最大

图1

注意,在实时边缘播放的低延迟客户端消耗的部分(紫色),与标准延迟客户端连续媒体段(绿色)之间存在内容的重复。如果要添加DASH的内容,如图2所示,会出现三类文件,它们都保存相同的媒体内容,但彼此争夺缓存空间。

图2

我们的目标是将这些减少到一个文件集,这将使原始存储降低3倍,并使CDN的缓存效率提高三倍。这可以通过使用字节范围寻址来实现。

03

PART

字节范围寻址

在LL-HLS媒体播放列表中,使用每个部分的唯一URL单独地描述了一个部分。例如

#EXT-X-PART:DURATION = 0.500,URI =“ segment1000-6.m4s”

可以使用BYTERANGE语法描述同一部分

#EXT-X-PART:DURATION = 0.500,URI =“ segment1000.m4s”,BYTERANGE = 251022 @ 2079557

它指定部分在媒体段中的长度和偏移量。对于尚不清楚最后字节位置的PRELOAD HINT部分,仅发出字节范围开始的信号:

#EXT-X-PRELOAD-HINT:TYPE = PART,URI =“ segment1000.m4s”,BYTERANGE-START = 2005479

图3在左边显示了一个部分媒体播放列表,在右边显示了字节范围寻址的等效列表:

图3

我们特别感兴趣的是当面对由PRELOAD HINT条目指定的开放范围请求时的预期起始点行为。根据HLS规范,“处理包含一个或多个尚未完全可以发送的部分分段的URL或URL的字节范围的请求时-例如响应EXT-X- PRELOAD的请求-HINT标记-服务器必须避免传输属于该部分段的任何字节,直到该部分段的所有字节都可以以链接的全速传输到客户端为止。“这意味着源必须阻止响应直到该预加载部分的所有字节可用为止。规范继续:如果请求的范围包括一个以上的部分分段,则服务器必须依次为每个部分分段强制执行此交付。这使客户端能够执行准确的自适应比特率(ABR)测量。“由于我们的开放范围请求确实包含多个部分(实际上,它包括该分段的所有其余部分)。因此源端应继续沿同一次请求返回连续的部分,并在每个部分完全可用时将其传输。这里的关键是:单个请求实际上将返回该段中剩余的所有部分,图4说明了我们如何利用这一事实来推导LL-HLS和LL-DASH之间的通用工作流程。

图4

图4的下半部分表示使用字节范围寻址的客户端的工作流程。在时间0处,它针对段1发出开放范围的请求。起点阻塞响应,直到第1部分的全部可用为止,然后它开始将聚合的内容返回给客户端。在这里,我会仔细使用“聚合”一词。如果这是http / 1.1,则它将是分块的传输响应,但是,由于LL-HLS强制使用http / 2,并且http / 2具有framing功能,因此这只是一个汇总的http / 2响应。请注意,单独寻址和字节寻址在延迟上是等效的。

04

PART

请求率收益

考虑一个字节范围寻址的LL-HLS客户端的启动行为。如图5

图5

它可以简单地充当单独寻址的客户端,即对每个单独的部分提出七个独立的请求。最后一个请求将是PRELOAD部分的一个开放请求。但是,另一种方法是简单地发出单个请求,如图6所示:

图6

该单个请求将以正确的顺序返回所有部分,包括将跟随PRELOAD部分的所有将来部分。这正是播放器所需要的(对于这个部分持续时间与片段持续时间比率),可以将媒体请求次数降低7倍。由于LL-HLS的缺点之一是它对边缘的高请求率,因此这是一个很有前途的好处。但是,部署它需要明确CDN边缘如何处理该开放范围请求。

05

PART

开放式范围请求的问题

假设一台边缘服务器收到一个客户端请求,该客户端请求开始range = 0的范围未知的对象。假设它的实际大小是1000B,并且边缘收到了第一个100B。这时:

  1. 等待直到收到EOF信号并返回内容长度为1000的200响应代码
  2. 立即返回开放式206响应中拥有的100B,并在传递第1000个字节后关闭响应

行为1实际上是当今大多数CDN的行为方式,而行为2是低延迟流工作所需的行为。由于这两个都是有效的用例,边缘服务器如何分辨要采取的行为?幸运的是,有一个RFC可以解救!RFC8673表示如果客户端期望来自固定偏移量的汇总响应,则永远不应发出开放范围的请求。它应该发送一个非常大的请求作为范围请求中的最后一个字节。已建议使用9007199254740991作为候选对象(对于64位系统,它等于Number.MAX_SAFE_INTEGER)。这将向代理服务器(或源服务器)发出信号,以开始206响应,该响应从请求的偏移量开始并随着时间的推移进行聚合,直到对象被完全传输为止。请注意,仅当范围请求的start-byte-pos不为零时才需要此约定。如果所请求的范围从零开始,则可以使用标准(非范围)GET请求,因为源自然会提供聚合响应。

到这里再次考虑播放启动行为。我们应该考虑三种情况。首先是让播放器调入下面的播放列表,如图7所示:

图7

为了开始播放,它将从实时边缘找到最新的独立部分(以黄色突出显示)。然后它将发出以下请求:

GET / v1_1-7728.m4s HTTP / 2

注意,由于起始偏移为零,因此此处不需要RFC8673约定。服务器将响应:

HTTP / 2 200

原点将通过burst传输其具有的字节(最多375122)来响应,然后在每个部分边界可用时释放其余部分。这将为用户提供开始所需的独立部分,并包括“提示”部分在内的所有部分。由于大小未知,响应中将不包含内容长度标头。如果这是HTTP1.1连接,则将其表示为“块传输编码”响应,但是由于LL-HLS要求与客户端建立H2连接,因此客户端将其简单地视为聚集响应。

第二个启动案例涉及到该段中非零偏移量的独立部分。媒体播放列表可能类似于图8:

图8

这个媒体部分有两个独立的部分,我们希望从最新的部分开始,以最大程度地减少延迟。客户首先要

GET / v1_1-7728.m4s HTTP / 2

范围:字节= 245668-9007199254740991

请注意,该请求的第一个字节位置为245668,而不是零,这需要使用RFC8673约定。服务器将响应HTTP / 2 206部分内容

内容范围:字节245668-9007199254740991 / *

源端通过在内容范围标头中确认RFC8673建立的约定进行响应,并将内容长度标记为*,因为尚不清楚。然后它将字节从245668突发到375123,并在每个部分边界可用时释放其余部分。

第三种也是最后一种启动情况是边缘条件,其中PRELOAD提示表示新段的开始。

图9

注意,在图9中,HINT属于片段7729(紫色高亮显示),而先前的片段7728拥有我们需要开始的独立部分。要启动,播放器需要发出两个请求。第一个是:

GET / v1_1-7728.m4s HTTP / 2

范围:字节= 245668-498933

由于段7728完全可用,因此播放器知道该段的内容长度,因此不需要使用RFC8673大数字约定。它只是要求从最后一个独立部分的开始到段末尾的字节范围。服务器将响应

HTTP / 2 206部分内容

内容长度:253265

内容范围:字节245668-498933 / 498934

这是常规的206响应。由于内容长度已知,因此添加了内容长度响应头。由于段在原点完全可用,因此所有数据将作为一个连续块突发传输。然后,客户端需要再次发出请求以继续播放:

GET / v1_1-7729.m4s HTTP / 2

服务器将响应:

HTTP / 2 200

当段7729的所有部分在聚合响应中变为可用时,服务器将对其进行burst传输,并且播放器将进入稳态播放。

06

PART

稳定状态

说到稳态,那是什么样的?如果在播放器启动后检查所有通过线路的请求,它们将如下所示:

GET / v1_1-7729.m4s HTTP / 2

范围:字节= 567843-9007199254740991

GET / v1_1-7730.m4s HTTP / 2

GET / v1_1-7731.m4s HTTP / 2

GET / v1_1-7732.m4s HTTP / 2

...

除了由于非零起始偏移量而使用RFC8673约定的第一个请求外,这些都是不带范围标头的标准GET请求。令人惊讶的是,我们可以大致观察到,使用字节范围寻址的LL-HLS客户端对于每种媒体类型,每个段持续时间只需要发出一个请求。对于LL-HLS来说,这是很好的性能提升,否则格式相当冗长。请注意,客户端仍必须在各自的部分持续时间间隔刷新其媒体播放列表,因为它们向其提供有关流的状态变化的信息。总体请求率的降低取决于部分时长与分段时长的比率。表1显示了使用离散或基于范围部分寻址的LL-HLS客户端在相同时间间隔的每个段持续时间内发出的请求数。

表1

对于4s段和1s部分的情况,我们发现每4s的请求总数减少了37.5%。如果部分的持续时间减少到0.5s,则减少幅度将上升至43%。这是对CDN可伸缩性和整体系统成本至关重要的实质性收益。对于一百万个连接的客户,每4秒减少430,000个请求是一个巨大的差异。针对CDN的每个请求都具有成本-连接,计算和功耗。为了最大程度地提高分发效率,我们希望在最大限度地提高最终用户体验质量的同时,最大限度地减少需求。

07

PART

段结构

LL-HLS起源的早期版本产生的部件都是独立的(即每个部件都包含一个关键帧),然后具有带有单个关键帧的连续段,如图10所示。

图10

这样做的原因是编码效率-通过更长的GOP,编码效率会有很小的提高。但是,这种安排破坏了将单个对象存储在高速缓存中的可移植性,我们可以从中为部分和分段提供服务。为了实现统一的缓存,我们的段必须是我们各部分的直接串联,如图11所示。

图11

将缓存占用空间减少一半所获得的好处远远超过了拥有两个不同的媒体对象所带来的较小的编码效率收益。

08

PART

估计吞吐量

所有HTTP自适应流客户端都必须使用媒体段的下载,以便估计可用吞吐量,从而允许其ABR算法切换。

图12

对于单独的部分寻址,这是通过测量接收到的字节并除以接收它们所花费的时间来完成的,如图12所示。由于媒体对象在服务器上完全可用,因此传输它们的速率受到媒体对象的限制,进而可以用来估计有多少吞吐量可用。如果对范围寻址响应遵循相同的逻辑,则它将提供错误的结果。分子将是正确的,但分母将包括源端阻塞传递的时间,如图13所示。

图13

播放器将继续用媒体时间的总字节数除以传送时间,该时间实际上是该片段的媒体播放时间。该结果将始终等于对象的编码比特率-这是无用的结果,既不准确,又会阻止播放器切换到更高的比特率。

相反,播放器必须在收到的比特数增加时才进行估计,如图14所示。

图14

09

PART

这在现实世界中可行吗?

为了在真实的互联网上验证此文章中描述的概念,我与法国的编码器和服务器提供商Ateme合作。Ateme在美国弗吉尼亚州的一个AWS实例中安装了编码器和LL-HLS源端。然后,我将Akamai CDN放在此之上,并使用它将其流传输到位于加利福尼亚州旧金山的客户端,如图15所示。

图15

图16是正在运行的实时流的屏幕截图。

图16

该流包含4s段和0.5s部分。它以1.5的目标端到端延迟运行。在右侧的图表中,绿点表示每个媒体细分请求的完成情况,这些都需要不到4s的时间。橙色点表示媒体播放列表更新,该更新每500毫秒发生一次。通过检查图17中的视频对象请求,

图17

我们可以看到,请求仅针对段进行,每个请求都从边缘服务器收到200个响应,并且花费不到4s的时间即可完成。即使我们在LL-HLS中使用基于范围的寻址,在稳定播放的情况下,客户端也无需发出任何基于范围的请求!如果以非零偏移量发出了初始请求,则该初始请求将使用RFC8673约定,并显示为206响应,然后是CORS预检选项请求,以验证是否允许范围标头。该预检请求是从Web浏览器进行测试的人工产物,如果从本机应用程序进行测试则不会出现。相比之下,媒体播放列表更新(图18中)的返回速度要比媒体片段快得多,大约间隔为500毫秒。

图18

图19显示了媒体段请求之一的详细信息。请注意,由于客户端正在请求整个段,因此没有内容范围响应标头,并且由于这是针对未知大小对象的聚合H2响应,因此没有内容长度响应标头。

图19

图20显示了我们三个目标播放器,他们都来自同一源端服务器和边缘服务器。左下角是处于字节范围寻址模式的LL-HLS播放器。左上方是LL-DASH播放器。右侧是标准延迟HLS播放器,由HLS.js表示。

图20

标准延迟播放器正在播放与LL-HLS播放器完全相同的流,但是落后12秒,因为它忽略了部分,而是在开始之前在其缓冲区中构建了4秒段中的三个。图21基本上是对该文档所支持的整个方法的验证。它显示了三个相邻布置的播放器,每个播放器都从边缘拉出相同的媒体片段。例如1-401326000.m4s。

图21

中间的面板属于旧式延迟播放器,并且始终落后于其他两个播放器的完整部分,这两个延迟播放器均具有低延迟并在仍在生产时拉动对象。如果我们检查第一个从CDN边缘请求给定段的播放器,我们会注意到它收到了TCP_MISS响应(图22)。这表明该内容在边缘不可用,并且边缘必须向源发出转发请求才能将其检索。这是正常现象,因为至少一个请求必须始终到原始位置才能检索内容。

图22

重要的是,对同一对象的第二个及后续请求收到了TCP_HIT响应(图23)。这表明对象实际上是在边缘缓存并从边缘提供服务。成功!

图23

10

PART

结论

LL-HLS基于范围的寻址的出现为直播流带来了许多好处:

  • 在原始和CDN分发层提高了缓存效率,从而提高了性能并降低了运营成本。
  • 客户的请求率降低。对于典型的编码配置,我们显示减少了30%到40%,这可以增加CDN支持的规模,降低运营成本,并减少请求错误之间的发生率。
  • 即使在播放列表中使用基于范围的寻址,处于稳定状态的LL-HLS客户端也无需针对源进行任何范围请求,从而消除了基于浏览器的客户端的CORS preflight要求。
  • 四种类型的客户端之间的互操作性:低延迟HLS客户端,标准延迟HLS客户端,低延迟DASH客户端和标准延迟DASH客户端。
  • 如果分发链中存在CDN,则它需要在源,CDN和客户端层支持RFC8673才能有效工作。如果客户端直接与源对话,则可以预期源行为适当,并且不需要RFC8673约定。

0 人点赞