作为一名开发者,当你想要在你的应用或网站中集成流畅的自适应视频流功能时,你很可能会遇到 DASH 和 MPD 这两个词。DASH 是当今主流的高效流媒体协议,而 MPD 则是它的核心与灵魂。简单来说,MPD 就是告诉播放器“视频在哪里、有什么版本、以及如何播放”的导航图。
DASH 的全称是 Dynamic Adaptive Streaming over HTTP。顾名思义,它是一种基于 HTTP 的自适应流媒体技术。它的核心思想是:
将视频文件切割成无数个小片段。
为同一视频提供多种不同质量(如分辨率、码率)的版本。
播放器根据当前网络速度,动态选择最合适质量的片段来下载和播放,从而保证流畅的观看体验。
而 MPD 的全称是 Media Presentation Description。它是一个 XML 格式的清单文件,包含了上述所有信息的元数据。播放器首先要做的就是获取这个 MPD 文件,然后才能开始智能地拉取视频片段。
我们可以把一个 MPD 文件想象成一本书的结构,这样理解起来就非常直观了。
<MPD>
根元素:书的封面,写着书名(mediaPresentationDuration
总时长)、出版日期(publishTime
)等信息。
<Period>
元素:书中的章节。一个直播流可能只有一个章节,而一部电影可能被分为正片和预告片两个章节。章节是按时间顺序排列的,一个放完再放下一个。
<AdaptationSet>
元素:章节下的分类。比如,一个章节里通常包含“视频”和“音频”两大类。它定义了同一类媒体流的共同属性,比如视频的编码格式是
AVC,音频的编码格式是 EC-3。
<Representation>
元素:分类下的具体版本。这是最关键的一环,它代表了视频或音频的一种质量规格。
<SegmentTemplate>
/ <SegmentList>
:定义了如何找到每个小片段。它提供了片段的下载路径模板。这是播放器拼图的核心。
层级关系总结:MPD
-> Period
(章节) -> AdaptationSet
(分类:视频/音频) -> Representation
(质量版本) -> SegmentTemplate
(
片段路径规则)
让我们通过一个真实的 MPD 文件(来自著名的 Big Buck Bunny 测试视频)来深入理解。这个文件描述了一个点播视频,总时长约为 634 秒(10分34秒)。它提供了从 180p 到 4K 共 10 种视频质量和 1 种音频质量。下载地址: https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd
<MPD mediaPresentationDuration="PT634.566S" minBufferTime="PT2.00S" profiles="urn:hbbtv:dash:profile:isoff-live:2012,urn:mpeg:dash:profile:isoff-live:2011" type="static" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd"> <BaseURL>./</BaseURL> <Period> <AdaptationSet mimeType="video/mp4" contentType="video" subsegmentAlignment="true" subsegmentStartsWithSAP="1" par="16:9"> <SegmentTemplate duration="120" timescale="30" media="$RepresentationID$/$RepresentationID$_$Number$.m4v" startNumber="1" initialization="$RepresentationID$/$RepresentationID$_0.m4v"/> <Representation id="bbb_30fps_1024x576_2500k" codecs="avc1.64001f" bandwidth="3134488" width="1024" height="576" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_1280x720_4000k" codecs="avc1.64001f" bandwidth="4952892" width="1280" height="720" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_1920x1080_8000k" codecs="avc1.640028" bandwidth="9914554" width="1920" height="1080" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_320x180_200k" codecs="avc1.64000d" bandwidth="254320" width="320" height="180" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_320x180_400k" codecs="avc1.64000d" bandwidth="507246" width="320" height="180" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_480x270_600k" codecs="avc1.640015" bandwidth="759798" width="480" height="270" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_640x360_1000k" codecs="avc1.64001e" bandwidth="1254758" width="640" height="360" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_640x360_800k" codecs="avc1.64001e" bandwidth="1013310" width="640" height="360" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_768x432_1500k" codecs="avc1.64001e" bandwidth="1883700" width="768" height="432" frameRate="30" sar="1:1" scanType="progressive"/> <Representation id="bbb_30fps_3840x2160_12000k" codecs="avc1.640033" bandwidth="14931538" width="3840" height="2160" frameRate="30" sar="1:1" scanType="progressive"/> </AdaptationSet> <AdaptationSet mimeType="audio/mp4" contentType="audio" subsegmentAlignment="true" subsegmentStartsWithSAP="1"> <Accessibility schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007" value="6"/> <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/> <SegmentTemplate duration="192512" timescale="48000" media="$RepresentationID$/$RepresentationID$_$Number$.m4a" startNumber="1" initialization="$RepresentationID$/$RepresentationID$_0.m4a"/> <Representation id="bbb_a64k" codecs="mp4a.40.5" bandwidth="67071" audioSamplingRate="48000"> <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/> </Representation> </AdaptationSet> </Period> </MPD>
1. 全局信息 (<MPD>
标签)
mediaPresentationDuration="PT634.566S"
: 整个媒体的总时长,634.566 秒。
minBufferTime="PT2.00S"
: 播放器为了平滑播放,至少需要预先下载2秒的数据。
type="static"
: 最关键属性之一! static
表示这是一个点播(VOD) 视频。所有视频片段都已生成完毕。
<BaseURL>./</BaseURL>
: 所有媒体片段路径的基础 URL。./
表示相对路径,片段文件夹与 MPD 文件在同一目录下。
2. 视频轨 (<AdaptationSet>
for Video)
mimeType="video/mp4"
: 容器格式是 MP4。
<SegmentTemplate>
:片段规则 - 这是播放器如何拼出文件 URL 的配方!
timescale="30"
+ duration="120"
: 120 / 30 = 4 秒
。每个视频片段都是 4 秒长。
initialization="$RepresentationID$/$RepresentationID$_0.m4v"
: 初始化文件路径。$RepresentationID$
是变量,会被替换为具体质量的
ID。
media="$RepresentationID$/$RepresentationID$_$Number$.m4v"
: 媒体片段路径。$Number$
是变量,代表片段序号。
示例:对于 id="bbb_30fps_1280x720_4000k"
的版本,它的第5个片段路径是:./bbb_30fps_1280x720_4000k/bbb_30fps_1280x720_4000k_5.m4v
<Representation>
:质量版本 - 这里列出了 10 种质量。
4K 版本示例:
<Representation id="bbb_30fps_3840x2160_12000k" codecs="avc1.640033" bandwidth="14931538" width="3840" height="2160" frameRate="30"/>
bandwidth="14931538"
表示码率 ~14.9 Mbps,这是播放器做切换决策的最关键数字。
低清版本示例:
<Representation id="bbb_30fps_320x180_200k" codecs="avc1.64000d" bandwidth="254320" width="320" height="180" frameRate="30"/>
码率仅为 ~254 kbps,非常节省流量。
3. 音轨 (<AdaptationSet>
for Audio)
通常只有一个音频流,因为不同语言会放在不同的 AdaptationSet
中。
音频的 <SegmentTemplate>
:
timescale="48000"
+ duration="192512"
: 192512 / 48000 ≈ 4.01 秒
。片段时长与视频的 ~4 秒对齐,方便音画同步。
音频的 <Representation>
:
codecs="mp4a.40.5"
: 代表 AAC-LC 音频编码。
bandwidth="67071"
: 码率约为 67 kbps。
<AudioChannelConfiguration value="2"/>
: 双声道立体声。
获取 MPD: 下载并解析这个 XML 文件。
理解结构: 知道这是一个点播视频,有 10 个视频质量和 1 个音频质量,所有片段都是约 4 秒一个。
下载初始化片段: 根据模板下载音视频的初始化片段(..._0.m4v
和 ..._0.m4a
)。
自适应循环:
监测网络: 计算当前下载速度。
选择质量: 比较当前网速和 bandwidth
值,选择最高可流畅播放的视频质量(如 720p
)。
下载媒体片段: 根据 media
属性模板,拼出下一个 4 秒视频片段的 URL 并下载。同时下载对应的音频片段。
解码播放: 将片段送入解码器进行播放。
持续循环: 每下载完一个片段,重新评估网络状况,重复此过程,直到播放结束。
静态 vs 动态:type="static"
表示点播(VOD),整个 MPD 信息是完整的。type="dynamic"
表示直播,MPD 会持续更新,包含minimumUpdatePeriod
等属性。
码率自适应逻辑:DASH 协议本身只提供了“导航图”,如何根据带宽选择最合适的 Representation
是播放器开发者需要实现的算法。可以使用开源库如 dash.js、Shaka Player 或 zwplayer,它们已经内置了成熟的算法。
调试工具:浏览器 F12 开发者工具的“网络”选项卡是观察 DASH 工作流程的最佳场所。你会看到对 .mpd
文件的请求,以及对大量.m4s
或 .m4v/.m4a
片段的请求。
MPD 文件是 DASH 流媒体系统的“大脑”和“导航图”。它通过清晰的 XML 结构,以一种松耦合的方式,高效地组织了复杂的多码率媒体流信息。通过上面示例的逐行解读,我们可以看到播放器如何依靠BaseURL
、SegmentTemplate
和 Representation
这些核心元素来拼凑出真实的媒体片段 URL,并根据 bandwidth
属性智能地完成自适应切换。理解这些,你就掌握了集成 DASH 流媒体功能的关键第一步。
zwplayer播放器是为数不多的支持dash格式多码率自适应播放、内嵌字幕播放的播放器,欢迎大家使用😀