Skip to content

Instantly share code, notes, and snippets.

@quink-black
Created October 20, 2021 12:09
Show Gist options
  • Save quink-black/964d2475a473089876bbe77855802f2b to your computer and use it in GitHub Desktop.
Save quink-black/964d2475a473089876bbe77855802f2b to your computer and use it in GitHub Desktop.
HLS如何切码流

HLS协议的核心设计至少包括三点:大规模分发、多设备兼容和码率自适应。码率自适应包括自适应算法设计以及如何实现切换。HLS协议本身不负责自适应算法,它描述的是如何实现切换。一个基础问题:从a.m3u8切换到b.m3u8时,如何在b.m3u8中找到要播放的切片?

最简单、看起来最合理的方案:在b.m3u8中找匹配的sequence number。可能多数播放器是这么做的。

但是,HLS草案第9版(2012年9月)新增了这么一段描述:

https://datatracker.ietf.org/doc/html/draft-pantos-http-live-streaming-09

used to synchronize the old and new timelines precisely. A client MUST NOT assume that segments with the same media sequence number in different variants or renditions contain matching content.

最终,RFC 8216修改为:

A client MUST NOT assume that segments with the same Media Sequence Number in different Variant Streams or Renditions have the same position in the presentation; Playlists MAY have independent Media Sequence Numbers. Instead, a client MUST use the relative position of each segment on the Playlist timeline and its Discontinuity Sequence Number to locate corresponding segments.

可知,不同流的sequence number是独立的,根据sequence number去匹配是不符合标准的。

那么,按照标准该如何在不同的流之间匹配对应的切片呢?

  • 对于点播和event类型直播,对所有切片时长进行累加,根据累加时长在不同流间匹配对应的切片

  • 对于live直播,根据切片时间戳做匹配,因为HLS要求

    o Matching content in Variant Streams MUST have matching timestamps. This allows clients to synchronize the media.

    怎么根据时间戳匹配呢?不管三七二十一,先下载一个切片,解析下时间戳,再根据m3u8里切片的时长,找到对应的切片。运气好一次命中,运气不好得下载俩切片才能实现切码流。

Exoplayer关于此问题有个深入讨论:HLS support for different GOP between variants 。对应的代码提交:Main branch: Ignore segment sequence numbers when switching variants

另外一个和切码流相关的是EXT-X-DISCONTINUITY-SEQUENCE,HLS草案12版添加的。HLS标准对不同流里的DISCONTINUITY-SEQUENCE做了限定:

   o  Matching content in Variant Streams MUST have matching
      Discontinuity Sequence Numbers (see Section 4.3.3.3).

为什么需要EXT-X-DISCONTINUITY-SEQUENCE呢?因为出现EXT-X-DISCONTINUITY的直播场景,EXT-X-DISCONTINUITY在m3u8刷新过程中会消失,a.m3u8有EXT-X-DISCONTINUITY,b.m3u8无EXT-X-DISCONTINUITY,播放器没办法做匹配。EXT-X-DISCONTINUITY-SEQUENCE起到了对EXT-X-DISCONTINUITY的计数功能,效果是对切片做了分组。通过时间戳在不同流之间匹配切片时,要先匹配DISCONTINUITY-SEQUENCE。举个例子:当前在a.m3u8 DISCONTINUITY-SEQUENCE为3的某个切片结束时timestamp是600秒,下个切片DISCONTINUITY-SEQUENCE还是3;切换到b.m3u8,先找到对应的DISCONTINUITY-SEQUENCE 3的切片区间,再从中找开始时间为600秒的切片。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment