[其他] 冲顶大会有前端什么事吗?

[复制链接]
乌拉乌拉 发表于 2023-10-12 02:27:51|来自:北京 | 显示全部楼层 |阅读模式
最近的冲顶大会只是一个知识问答的模式,不过结合直播起来可能就带来不一样的效果了。总的来看主要火起来的有几个基本点:

  • 低门槛:人人都可以答题
  • 奖金高:差不多都是百万以上,但是不排除机器人和你分钱 :)
  • 延时低:同时出题,同时答题。这点对于延时直播来说,压力非常大,差不多延时必须控制到 2s 之内。所以,HLS 基本上就凉了。
  • KOL 带节奏,比如王思聪 撒币
  • 主播美眉
  • 。。。
作为一个前端开发来说,我觉得直播的世界离我们太遥远,其中有两座大山,一个是 X5 ,一个是 苹果。因为,X5 和苹果这逼不提供 MSE 给前端用,导致了一个结果,要么用 HLS 直播,要么你就不播。现在,鄙人正在腾讯打工,最近和 X5 杠上了,问他们为什么不支持 MSE?他们给的答复是:



可以说,在明年,MSE 技术应该会让前端能力得到极大的扩展。但是,MSE 只是作为一个播放端的技术,流从哪里来?H5 直播是怎么搞的?
对于一些基础知识,推荐大家直接去这篇文章里面查看:
https://www.villianhr.com/2017/03/31/全面进阶 H5 直播
现阶段,比较流行的协议主要有:HLS,RTMP,HTTPFLV。延时性就属 HLS 最菜,这是苹果自研直播流播放器,差不多播放延时有 10s+ 左右。而 RTMP 和 HTTPFLV 都和 Adobe 公司有点关系,这有种让人离不开 Flash 的感觉,他们俩的延时性都出奇的好,差不多只有 3s 左右,但是里面流确实 FLV 格式的。
但是,W3C 不同意,老子绝壁不想和 Flash 再有半点关系,我现在有 WebM,FMP4,TS 凭啥再去迁就你的 FLV?
为了从源头解决这个问题,MPEG 推出了 MPEG-DASH 直播标准来统一各种比较尴尬的流描述文件。它主要是基于 mpd 文件来做的切片和文件的 download。先来看一份简单的 MPEG-DASH 文件:
<?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?>
<MPD xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34; xmlns=&#34;urn:mpeg:dash:schema:mpd:2011&#34; xsi:schemaLocation=&#34;urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd&#34; profiles=&#34;urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple&#34; maxSegmentDuration=&#34;PT2S&#34; minBufferTime=&#34;PT2S&#34; type=&#34;static&#34; mediaPresentationDuration=&#34;PT10S&#34;>
   <ProgramInformation>
      <Title>Media Presentation Description from DASHI-IF live simulator</Title>
   </ProgramInformation>
   <BaseURL>http://vm2.dashif.org/dash/vod/testpic_2s/</BaseURL>
   <Period id=&#34;precambrian&#34; start=&#34;PT0S&#34;>
      <AdaptationSet contentType=&#34;audio&#34; mimeType=&#34;audio/mp4&#34; lang=&#34;eng&#34; segmentAlignment=&#34;true&#34; startWithSAP=&#34;1&#34;>
         <Role schemeIdUri=&#34;urn:mpeg:dash:role:2011&#34; value=&#34;main&#34;/>
         <SegmentTemplate startNumber=&#34;1&#34; initialization=&#34;$RepresentationID$/init.mp4&#34; duration=&#34;2&#34; media=&#34;$RepresentationID$/$Number$.m4s&#34;/>
         <Representation id=&#34;A48&#34; codecs=&#34;mp4a.40.2&#34; bandwidth=&#34;48000&#34; audioSamplingRate=&#34;48000&#34;>
            <AudioChannelConfiguration schemeIdUri=&#34;urn:mpeg:dash:23003:3:audio_channel_configuration:2011&#34; value=&#34;2&#34;/>
         </Representation>
      </AdaptationSet>
      <AdaptationSet contentType=&#34;video&#34; mimeType=&#34;video/mp4&#34; segmentAlignment=&#34;true&#34; startWithSAP=&#34;1&#34; par=&#34;16:9&#34; minWidth=&#34;640&#34; maxWidth=&#34;640&#34; minHeight=&#34;360&#34; maxHeight=&#34;360&#34; maxFrameRate=&#34;60/2&#34;>
         <Role schemeIdUri=&#34;urn:mpeg:dash:role:2011&#34; value=&#34;main&#34;/>
         <SegmentTemplate startNumber=&#34;1&#34; initialization=&#34;$RepresentationID$/init.mp4&#34; duration=&#34;2&#34; media=&#34;$RepresentationID$/$Number$.m4s&#34;/>
         <Representation id=&#34;V300&#34; codecs=&#34;avc1.64001e&#34; bandwidth=&#34;300000&#34; width=&#34;640&#34; height=&#34;360&#34; frameRate=&#34;60/2&#34; sar=&#34;1:1&#34;/>
      </AdaptationSet>
   </Period>
</MPD>

基本原理是,后台将一份完整的流文件切片,生成 Initial Segment 和 Media Segments,这些就是流的片段文件,比如 .mp4,.ts等。更详细的内容,下面会进行详述。
那该协议的延时性怎么样呢?
这个主要取决于你的协议,最极致的时延是比 HTTP-FLV 还要快,差不多 <= 2~3s。其中,最主要的是它定义的模板解析机制,直接根据时间戳来协定。
MPD 基本简介

DASH 其实只是一系列概念,原意是 Dynamic Adaptive Streaming over HTTP。它主要是基于 mpd 文件来做的切片和文件的 download。整个模式有点类似于 HLS,但是其可以应用于所有的 视频格式,比如 mp4,webm。它将整个的视频文件,切片分为一个个具体的 HTTPFLV segments。不过,其更优于 HLS,这个已经在上面阐述清楚了。
MPD 的播放模式,其实就是根据 XML 的内容,协商出来播放的切片 URL 地址。一个简易的 MPD 文件为:
<?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?>
<MPD availabilityStartTime=&#34;1970-01-01T00:00:00Z&#34; id=&#34;Config part of url maybe?&#34; maxSegmentDuration=&#34;PT2S&#34; minBufferTime=&#34;PT2S&#34; minimumUpdatePeriod=&#34;P100Y&#34; profiles=&#34;urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple&#34; publishTime=&#34;2018-01-06T06:57:00Z&#34; timeShiftBufferDepth=&#34;PT5M&#34; type=&#34;dynamic&#34; ns1:schemaLocation=&#34;urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd&#34;
      xmlns=&#34;urn:mpeg:dash:schema:mpd:2011&#34;
      xmlns:ns1=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;>
      <ProgramInformation>
            <Title>Media Presentation Description from DASHI-IF live simulator</Title>
      </ProgramInformation>
      <BaseURL availabilityTimeOffset=&#34;10.000000&#34;>https://vm2.dashif.org/livesim-dev/ato_10/testpic_2s/</BaseURL>
      <Period id=&#34;p0&#34; start=&#34;PT0S&#34;>
            <AdaptationSet contentType=&#34;audio&#34; lang=&#34;eng&#34; mimeType=&#34;audio/mp4&#34; segmentAlignment=&#34;true&#34; startWithSAP=&#34;1&#34;>
                  <Role schemeIdUri=&#34;urn:mpeg:dash:role:2011&#34; value=&#34;main&#34; />
                  <SegmentTemplate duration=&#34;2&#34; initialization=&#34;$RepresentationID$/init.mp4&#34; media=&#34;$RepresentationID$/$Number$.m4s&#34; startNumber=&#34;0&#34; />
                  <Representation audioSamplingRate=&#34;48000&#34; bandwidth=&#34;48000&#34; codecs=&#34;mp4a.40.2&#34; id=&#34;A48&#34;>
                        <AudioChannelConfiguration schemeIdUri=&#34;urn:mpeg:dash:23003:3:audio_channel_configuration:2011&#34; value=&#34;2&#34; />
                  </Representation>
            </AdaptationSet>
            <AdaptationSet contentType=&#34;video&#34; maxFrameRate=&#34;60/2&#34; maxHeight=&#34;360&#34; maxWidth=&#34;640&#34; mimeType=&#34;video/mp4&#34; minHeight=&#34;360&#34; minWidth=&#34;640&#34; par=&#34;16:9&#34; segmentAlignment=&#34;true&#34; startWithSAP=&#34;1&#34;>
                  <Role schemeIdUri=&#34;urn:mpeg:dash:role:2011&#34; value=&#34;main&#34; />
                  <SegmentTemplate duration=&#34;2&#34; initialization=&#34;$RepresentationID$/init.mp4&#34; media=&#34;$RepresentationID$/$Number$.m4s&#34; startNumber=&#34;0&#34; />
                  <Representation bandwidth=&#34;300000&#34; codecs=&#34;avc1.64001e&#34; frameRate=&#34;60/2&#34; height=&#34;360&#34; id=&#34;V300&#34; sar=&#34;1:1&#34; width=&#34;640&#34; />
            </AdaptationSet>
      </Period>
</MPD>
XML 文件里面的每一个标签内容,都是遵循 MPEG-DASH LA 的标准。其内部包含 N+1 个 Periods Tag。每一个 Period 包含相关的 media stream,比如 video:不同的编码,视角,带宽等、 audio:不同语言,类型,带宽等。一些共同的参数,比如 codec,frame rate, audio-channel 在同一个 Period 是不能改变的。所以,尽可能在一个 Period 提供更丰富的描述信息来说是非常重要的。虽然,Period 里面的信息不能动态改变,但是,用户可以自己手动选择,自己想要的分辨率,带宽大小等等。
Period 可以包含多个流,所以,还可以提供插入广告,或者视角流的切分等功能。这个也是 MPEG-DASH 设计的初衷,通过一份文件协商出多个媒体流的内容。其基础架构内容为:



这里,我们先简单介绍一下,几个重点 TAG 具体的内容。
MPD

该是 MPD 里面文件的最外层的 Tag,有相关的属性来对其进行描述。该标签里面的属性极为重要,它决定了该 MPD 描述的文件属性和 媒体流 的播放顺序和内容。
再说三遍:
MPD 文件非常重要!
MPD 文件非常重要!
MPD 文件非常重要!
其基本属性为:



接下来,我们一个一个简单介绍一下:

  • id: 设置 MPD 的 identifier,一般不需要。
  • profiles: 设置 MPD 的基本标准,具体内容,参考下表 profles。





  • type: 用来设置 MPD 文件的基本属性。取值有两个

    • static:segment 的时长需要在 @availabilityStartTime 和 @availabilityEndTime 之间。
    • dynamic:主要根据 availabilityStartTime 时间决定。



  • availabilityStartTime: 设置所有 segment 的参考时间,如果 type 为 dynamic,则该属性是必须的。
  • availabilityEndTime: 对于 static 文件来说的静态文件范围。
  • pulishTime: 设置 MPD 文件生成的绝对时间(wall-clock)
  • mediaPresentationDuration: 设置当前 mediaSegments 的总时间长。例如 PT20M,表示时长为 20min。当 MPD.minimumUpdatePeriod 和 Period.duration 没有设置时,该属性可以作为替代。
  • minimumUpdatePeriod: 设置当前 MPD 文件的更新时间。当 type = static 时,该属性不应该出现。
  • minBufferTime:用来设置最小 segment 时长,例如:PT2S。该通常和 Representation.bandwidth(bps) 一起使用,来计算最小 segment 大小值。
  • timeShiftBufferDepth: 用来设置 MPD 中 segment 的有效区间。或者可以理解为 过期时间。这里,后面我们会详述一下。
  • maxSegmentDuration: 设置最大 segment 时长。
上面我们已经了解 MPD 标签里面的基本属性,这些属性在整个 MPEG-DASH 里面非常重要,后面,我们将简单讲解一下关于 MPD 更新和文件过期的点。
MPD 文件更新机制

MPD 文件的更新主要取决于 @minimumUpdatePeriod 属性设置,例如:minimumUpdatePeriod=&#34;PT10S&#34;。用来标识,MPD 文件从上一次 MPD 获取时间开始,10s 后检查一次更新。如果没有该属性,或者为 0,则代表该 MPD 文件不会过期。整个更新逻辑为:



那当 MPD 文件发生更新时,有一些内容需要注意:

  • MPD.id 属性值必须和以前的 MPD 一致
  • Period.id 属性必须和以前的 Period 一致
  • MPD.publishTime 需要和更新时间一致
更详细的内容,可以参考 ISO/ITU 官方标准 5.4 Media Presentation Description updates。
Segment 文件过期

特别针对于直播切片文件来说,由于服务器容量有限,所以,并不会一直被保存在服务器当中。最好的办法就是协定对应 Segment 的过期时间。那这个过期时间是怎么确定的呢?
主要根据以下公式:
[max(AST, now-timeShiftBufferDepth), now]

  • AST:是 MPD.availabilityStartTime 属性.
  • timeShiftBufferDepth: 是 MPD.timeShiftBufferDepth 属性,用来协定过期时间。
因为通常情况,max(AST, now-timeShiftBufferDepth) = now-timeShiftBufferDepth。所以,上面的范围可以精简为:
now-timeShiftBufferDepth <= time <= now
整个时长区间是由 MPD.timeShiftBufferDepth 属性值来控制的。例如,MPD 标签的设置值为:
timeShiftBufferDepth=&#34;PT5M&#34;
那么,文件有效期范围为,具体最新 MPD 文件 publishTime 前 5min 之内的链接是有效的。
Period

Period 主要是用来包含具体 流媒体 的数据,其本身只是起到设置 startTime 和区分多个 Period@id 的作用。它的基本属性没有多少:



这里,我直接用文本的形式表达一下:
<xs:sequence>
    <xs:element name=&#34;BaseURL&#34; type=&#34;BaseURLType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
    <xs:element name=&#34;SegmentBase&#34; type=&#34;SegmentBaseType&#34; minOccurs=&#34;0&#34;/>

    <xs:element name=&#34;SegmentList&#34; type=&#34;SegmentListType&#34; minOccurs=&#34;0&#34;/>
    <xs:element name=&#34;SegmentTemplate&#34; type=&#34;SegmentTemplateType&#34; minOccurs=&#34;0&#34;/>
    <xs:element name=&#34;AssetIdentifier&#34; type=&#34;DescriptorType&#34; minOccurs=&#34;0&#34;/>

    <xs:element name=&#34;EventStream&#34; type=&#34;EventStreamType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
    <xs:element name=&#34;AdaptationSet&#34; type=&#34;AdaptationSetType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
    <xs:any namespace=&#34;##other&#34; processContents=&#34;lax&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
</xs:sequence>
<xs:attribute ref=&#34;xlink:href&#34;/>
<xs:attribute ref=&#34;xlink:actuate&#34; default=&#34;onRequest&#34;/>
<xs:attribute name=&#34;id&#34; type=&#34;xs:string&#34; />
<xs:attribute name=&#34;start&#34; type=&#34;xs:duration&#34;/>
<xs:attribute name=&#34;duration&#34; type=&#34;xs:duration&#34;/>
<xs:attribute name=&#34;bitstreamSwitching&#34; type=&#34;xs:boolean&#34; default=&#34;false&#34;/>
<xs:anyAttribute namespace=&#34;##other&#34; processContents=&#34;lax&#34;/>
对于 Period 我们主要关注一下 attribute 属性内容。

  • id: 用来标识 Period 的唯一性。如果 MPD.type=dynamic,则该 id 不会在 MPD 更新时改变。
  • start: 用来设置 Period 下,Segment 参考的开始时间。不过,该 start 的确定并不是根据本身的 Period 来决定,还需要根据前一个 Period 来确定:

    • 如果当前的 Period 没有 start 属性,但是前一个 Period 是正常的,有 start 和 duration 属性。那么当前的 Period.start = prevPeriod.start + prevPeriod.duration
    • 如果当前的 Period 没有 start 属性,MPD.type = static,该 Period 是该 MPD 第一个出现的 Period 标签,那么 start 值默认会被设置为 0



  • duration: 用来决定当前 Period 的时长
  • bitstreamSwitching: 是否允许改变切流,默认为 false。
例如:
<Period id=&#34;p0&#34; start=&#34;PT0S&#34;>
    // ...
  </Period>
AdapationSet

AdaptionSet 主要是用来对当前包含的流进行基本信息的表述,相当于 MP4 中的 ftype+moof box 信息。
主要属性如下,
<xs:sequence>

    <xs:element name=&#34;Accessibility&#34; type=&#34;DescriptorType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>

    <xs:element name=&#34;Role&#34; type=&#34;DescriptorType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
    <xs:element name=&#34;Rating&#34; type=&#34;DescriptorType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
    <xs:element name=&#34;Viewpoint&#34; type=&#34;DescriptorType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
    <xs:element name=&#34;ContentComponent&#34; type=&#34;ContentComponentType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>

    <xs:element name=&#34;BaseURL&#34; type=&#34;BaseURLType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
    <xs:element name=&#34;SegmentBase&#34; type=&#34;SegmentBaseType&#34; minOccurs=&#34;0&#34;/>

    <xs:element name=&#34;SegmentList&#34; type=&#34;SegmentListType&#34; minOccurs=&#34;0&#34;/>

    <xs:element name=&#34;SegmentTemplate&#34; type=&#34;SegmentTemplateType&#34; minOccurs=&#34;0&#34;/>
    <xs:element name=&#34;Representation&#34; type=&#34;RepresentationType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
</xs:sequence>
    <xs:attribute ref=&#34;xlink:href&#34;/>
    <xs:attribute ref=&#34;xlink:actuate&#34; default=&#34;onRequest&#34;/> <xs:attribute name=&#34;id&#34; type=&#34;xs:unsignedInt&#34;/>
    <xs:attribute name=&#34;group&#34; type=&#34;xs:unsignedInt&#34;/> <xs:attribute name=&#34;lang&#34; type=&#34;xs:language&#34;/>
    <xs:attribute name=&#34;contentType&#34; type=&#34;xs:string&#34;/> <xs:attribute name=&#34;par&#34; type=&#34;RatioType&#34;/>
    <xs:attribute name=&#34;minBandwidth&#34; type=&#34;xs:unsignedInt&#34;/> <xs:attribute name=&#34;maxBandwidth&#34; type=&#34;xs:unsignedInt&#34;/>
    <xs:attribute name=&#34;minWidth&#34; type=&#34;xs:unsignedInt&#34;/> <xs:attribute name=&#34;maxWidth&#34; type=&#34;xs:unsignedInt&#34;/>
    <xs:attribute name=&#34;minHeight&#34; type=&#34;xs:unsignedInt&#34;/> <xs:attribute name=&#34;maxHeight&#34; type=&#34;xs:unsignedInt&#34;/>
    <xs:attribute name=&#34;minFrameRate&#34; type=&#34;FrameRateType&#34;/> <xs:attribute name=&#34;maxFrameRate&#34; type=&#34;FrameRateType&#34;/>
    <xs:attribute name=&#34;segmentAlignment&#34; type=&#34;ConditionalUintType&#34; default=&#34;false&#34;/>
    <xs:attribute name=&#34;subsegmentAlignment&#34; type=&#34;ConditionalUintType&#34; default=&#34;false&#34;/>
    <xs:attribute name=&#34;subsegmentStartsWithSAP&#34; type=&#34;SAPType&#34; default=&#34;0&#34;/>
    <xs:attribute name=&#34;bitstreamSwitching&#34; type=&#34;xs:boolean&#34;/>
看图会不会更清晰:



这些属性,我就不一一多说了,大家看一个 Demo 理解一下:
<AdaptationSet contentType=&#34;video&#34; maxFrameRate=&#34;60/2&#34; maxHeight=&#34;360&#34; maxWidth=&#34;640&#34; mimeType=&#34;video/mp4&#34; minHeight=&#34;360&#34; minWidth=&#34;640&#34; par=&#34;16:9&#34; segmentAlignment=&#34;true&#34; startWithSAP=&#34;1&#34;>
    <Role schemeIdUri=&#34;urn:mpeg:dash:role:2011&#34; value=&#34;main&#34; />
    <SegmentTemplate initialization=&#34;$RepresentationID$/init.mp4&#34; media=&#34;$RepresentationID$/t$Time$.m4s&#34; timescale=&#34;90000&#34;>
        <SegmentTimeline>
            <S d=&#34;180000&#34; r=&#34;150&#34; t=&#34;136377021600000&#34; />
        </SegmentTimeline>
    </SegmentTemplate>
    <Representation bandwidth=&#34;300000&#34; codecs=&#34;avc1.64001e&#34; frameRate=&#34;60/2&#34; height=&#34;360&#34; id=&#34;V300&#34; sar=&#34;1:1&#34; width=&#34;640&#34; />
</AdaptationSet>
这里的描述信息,并不只局限于 AS(AdaptionSet) 一个属性,还可以用在 Representation 上。
Representation

Representation 是嵌套在 AS 里面,它也是流的相关描述信息,其实也就相当于是一个 IS(Initial Segment)。
主要信息有:



主要用法就是给当前的流提供基本描述信息:
<Representation bandwidth=&#34;300000&#34; codecs=&#34;avc1.64001e&#34; frameRate=&#34;60/2&#34; height=&#34;360&#34; id=&#34;V300&#34; sar=&#34;1:1&#34; width=&#34;640&#34; />
指定 Rep(Representation)的生效范围是在当前的 Period 的范围之内,也就是从:Period.start - Period.endTime。Rep 的描述信息为了使用率最大,被 Rep 包含的 Stream 都可以用该内容作为描述信息。
另外,我们还可以结合 dependencyId 和 id 来重复利用 Rep 的内容。通过 dependencyId指定模板 Rep@id,实现信息的直接复用。
<Representation bandwidth=&#34;300000&#34; codecs=&#34;avc1.64001e&#34; frameRate=&#34;60/2&#34; height=&#34;360&#34; id=&#34;1&#34; sar=&#34;1:1&#34; width=&#34;640&#34; />

<Representation dependencyId=&#34;1&#34; id=&#34;2&#34; mimeType=&#34;video/mp4&#34; />
MPD 如何表达 Segments

在 MPD 中,描述 Segments 主要由 SegmentBase, SegmentTemplate and SegmentList。一个完整的 Rep 需要:

  • N+1 SegmentList 标签
  • 1 SegmentTemplate
  • N+1 BaseURL 标签,[0,1] SegmentBase,没有 SegmentTemplate 和 SegmentList 标签。
这里,我们简单描述一下对应 Segment tag 的内容。
SegmentBase

SegmentBase 只在 static MPD 文件中使用,其基本内容其实是几个 Segments tag 共享内容,基本属性为:
<xs:sequence>
<xs:element name=&#34;Initialization&#34; type=&#34;URLType&#34; minOccurs=&#34;0&#34;/>
<xs:element name=&#34;RepresentationIndex&#34; type=&#34;URLType&#34; minOccurs=&#34;0&#34;/>
<xs:any namespace=&#34;##other&#34; processContents=&#34;lax&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>
</xs:sequence>
<xs:attribute name=&#34;timescale&#34; type=&#34;xs:unsignedInt&#34;/>
<xs:attribute name=&#34;presentationTimeOffset&#34; type=&#34;xs:unsignedLong&#34;/>
<xs:attribute name=&#34;timeShiftBufferDepth&#34; type=&#34;xs:duration&#34;/>
<xs:attribute name=&#34;indexRange&#34; type=&#34;xs:string&#34;/>
<xs:attribute name=&#34;indexRangeExact&#34; type=&#34;xs:boolean&#34; default=&#34;false&#34;/>
<xs:attribute name=&#34;availabilityTimeOffset&#34; type=&#34;xs:double&#34;/>
<xs:attribute name=&#34;availabilityTimeComplete&#34; type=&#34;xs:boolean&#34;/>


// extension prop
<xs:extension base=&#34;SegmentBaseType&#34;>
   <xs:sequence>
    <xs:element name=&#34;SegmentTimeline&#34; type=&#34;SegmentTimelineType&#34; minOccurs=&#34;0&#34;/>
    <xs:element name=&#34;BitstreamSwitching&#34; type=&#34;URLType&#34; minOccurs=&#34;0&#34;/>
   </xs:sequence>
    <xs:attribute name=&#34;duration&#34; type=&#34;xs:unsignedInt&#34;/>
    <xs:attribute name=&#34;startNumber&#34; type=&#34;xs:unsignedInt&#34;/>
</xs:extension>
如果觉得不清楚,可以看这张图:
![image.png-194.7kB][108]
Initialization Tag 可以作为元素,也可以直接作为 Segments Tag 的属性,来设置 Initial Segment 的 URL 链接。基本设置为:
<BaseURL>v-0144p-0100k-libx264.mp4</BaseURL>
<SegmentBase indexRange=&#34;678-1597&#34; timescale=&#34;12288&#34;>
    <Initialization range=&#34;0-677&#34;/>
</SegmentBase>
indexRange 设置 media Segment 的字节范围,range 则设置 Initial Segment 的字节范围。
另外,还有几个属性比较重要:

  • presentationTimeOffset:设置当前 Segment 相对于 Period 开始的偏移时间。
  • timeShiftBufferDepth:默认覆盖 MPD 的属性,并且该值不能比 MPD 的小。
  • availabilityTimeOffset:设置当前 Segment 可以获得的时间偏移量。
不过,在实际使用时,使用 SegmentBase 的情况很少,大家对其有印象即可。
SegmentList

该标签是用来标识一整套 Segment 的 URL list 内容。具体内容信息可以参考:
<xs:element name=&#34;SegmentURL&#34; type=&#34;SegmentURLType&#34; minOccurs=&#34;0&#34; maxOccurs=&#34;unbounded&#34;/>

<xs:attribute name=&#34;media&#34; type=&#34;xs:anyURI&#34;/>
<xs:attribute name=&#34;mediaRange&#34; type=&#34;xs:string&#34;/>
<xs:attribute name=&#34;index&#34; type=&#34;xs:anyURI&#34;/>
<xs:attribute name=&#34;indexRange&#34; type=&#34;xs:string&#34;/>
主要内容为:



该 Tag 常常用来包含一个完整的视频 List 内容。
<SegmentList timescale=&#34;90000&#34; duration=&#34;5400000&#34;>
       <RepresentationIndex sourceURL=&#34;representation-index.sidx&#34;/>
       <SegmentURL media=&#34;segment-1.ts&#34;/>
       <SegmentURL media=&#34;segment-2.ts&#34;/>
       <SegmentURL media=&#34;segment-3.ts&#34;/>
       <SegmentURL media=&#34;segment-4.ts&#34;/>
       <SegmentURL media=&#34;segment-5.ts&#34;/>
       <SegmentURL media=&#34;segment-6.ts&#34;/>
       <SegmentURL media=&#34;segment-7.ts&#34;/>
       <SegmentURL media=&#34;segment-8.ts&#34;/>
       <SegmentURL media=&#34;segment-9.ts&#34;/>
       <SegmentURL media=&#34;segment-10.ts&#34;/>
</SegmentList>
SegmentTemplate

SegmentTemplate 主要应用在文件切片数量过于庞大,如果使用 SegmentList 标签,则有点得不偿失。对于一些 live scenarios,比如直播,连麦等等。使用 SegmentTemplate 应该是非常有用的。它可以通过 startNumber,以及对应的 模板URL,来提供给客户端进行相关链接解析。例如:
<Representation mimeType=&#34;video/mp4&#34;
                   frameRate=&#34;24&#34;
                   bandwidth=&#34;1558322&#34;
                   codecs=&#34;avc1.4d401f&#34; width=&#34;1277&#34; height=&#34;544&#34;>
  <SegmentTemplate media=&#34;http://cdn.bitmovin.net/bbb/video-1500/segment-$Number$.m4s&#34;
  initialization=&#34;http://cdn.bitmovin.net/bbb/video-1500/init.mp4&#34;
  startNumber=&#34;0&#34;
  timescale=&#34;24&#34;
  duration=&#34;48&#34;/>
</Representation>
具体属性内容为:




  • index: 对于 Template 字段,对 $Number$ 和 $Time$ 标识符进行替换。
  • initialization: 用来标识 Initialization Segment 的具体地址,在该属性里面只能使用标识符$RepresentationID$。
使用 template 的方式,能够很大的减小 MPD 文件大小,不过会额外增加以下客户端解析 MPD 的时间。除了上面使用 $Number$ 形式进行解码外,还可以使用 $RepresentationID$ 的标识符来进行字符替换:
<SegmentTemplate
    duration=&#34;2&#34;     
    initialization=&#34;$RepresentationID$/init.mp4&#34;
    media=&#34;$RepresentationID$/$Number$.m4s&#34;
    startNumber=&#34;0&#34; />
<Representation
    bandwidth=&#34;300000&#34;
    codecs=&#34;avc1.64001e&#34;
    frameRate=&#34;60/2&#34;
    height=&#34;360&#34;
    id=&#34;V300&#34;
    sar=&#34;1:1&#34;
    width=&#34;640&#34; />
那一共有哪些标识符可以使用呢?在哪些标签里面才能使用这些标识符呢?我们简单描述一下:
Identifier 用途

Identifier 常常用在 SegmentTemplate 标签中,只有以下属性可以使用标识符:media, index, initialization 和 bitstreamSwitching 属性。

  • $RepresentationID$: 对应于 Representation 标签中的 id 属性,比如上面就是 V300。。。
完整标识符解释内容,可以关注公众号:前端小吉米,输入:MPD.identifier 获取。
另外,除了 SegmentTemplate 能够可以来作为 Template 模板之外,还有 SegmentTimeline 也可以完成该模板效果,只是一个是基于 Number,一个是基于 Time。
SegmentTimeline

SegmentTimeline 里面会通过多个 S 标签,来标识在同一个 MPD duration 内的 Segment 内容。也就是说,SegmentTimeline 只是提供了一个模板容器,具体的流的标识还是由 S 标签内容来决定。直接看一个最简单的 ST(SegmentTimeline):
<SegmentTimeline timescale=&#34;1000&#34;>
    <S t=&#34;0&#34; r=&#34;10&#34; d=&#34;24000&#34;/>
</SegmentTimeline>
这里,我们先来看一下 S 标签下的基本属性值:

  • t:标识当前 Segment 在 Period 流中开始时间。一般来说,不用设置即可。如果设置了,则其值为 previous S@t + @d * (@r + 1)。就是之前一个 S 标签的结束时间戳。
  • d:标识当前 Segment 的 duration
  • r:设置当前的 Segment 出现的个数。
我们来看一个 DEMO:
DEMO 详细解释和说明,可以关注:前端小吉米,输入:MPD.timeline 获取。
后续还有另外一篇,深入理解 DASH 直播的文章。
全部回复1 显示全部楼层
w66133 发表于 2023-10-12 02:28:39|来自:北京 | 显示全部楼层
天哥真是高产👍

快速回帖

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则