欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > 音视频学习(三十一):DASH协议

音视频学习(三十一):DASH协议

2025/4/2 9:09:28 来源:https://blog.csdn.net/www_dong/article/details/146772864  浏览:    关键词:音视频学习(三十一):DASH协议

DASH(Dynamic Adaptive Streaming over HTTP,动态自适应流媒体传输)是一种基于 HTTP 的流媒体传输协议,类似于 HLS,但更通用,支持 MPEG-2 TSISO Base Media File Format(MP4) 等封装格式。它允许客户端根据网络状况动态切换码率,确保流畅播放。

特点

  • 基于 HTTP:使用普通 Web 服务器进行内容分发,无需专用流媒体服务器。
  • 自适应码率:客户端可根据带宽动态调整播放的码率,避免卡顿。
  • 多种封装格式:支持 MP4(fMP4)MPEG-2 TS 等容器格式。
  • CDN 友好:DASH 片段是普通的 HTTP 文件,易于缓存和分发。
  • 支持多种音视频编码:H.264、H.265、VP9、AV1 等。

工作流程

DASH 采用**分片(Segment)+ 清单文件(MPD,Media Presentation Description)**的方式传输流媒体内容。

基本组件

组件作用
MPD(Media Presentation Description)描述 DASH 播放列表,定义视频流的可用分辨率、码率、分片 URL。
Segment(媒体分片)视频/音频数据被切割成多个小片段,每个片段几秒钟,客户端可选择合适的分片下载。
Representation(表示)一个视频的不同码率/分辨率的版本,如 360p, 720p, 1080p。
AdaptationSet(适配集合)一组 Representation,通常是不同的音视频流,如多种语言音轨、不同清晰度视频流。

DASH 播放过程

  1. 客户端请求 MPD 文件
    • 例如 https://example.com/video/manifest.mpd
  2. 解析 MPD,获取可用码率、分辨率、片段 URL
  3. 根据网络情况,选择合适的码率(Representation)
  4. 下载首个分片(Segment)并开始播放
  5. 动态调整码率
    • 如果网络带宽增加,切换到更高清的流;
    • 如果网络变差,降级到低码率流,保证不卡顿。
  6. 持续请求新片段
    • 例如 https://example.com/video/segment_1.m4s, segment_2.m4s,直到播放完毕。

MPD 文件结构

MPD 是 XML 格式的清单文件,定义视频流的不同清晰度和码率。

示例:

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" type="static" mediaPresentationDuration="PT10M"><Period><AdaptationSet mimeType="video/mp4" segmentAlignment="true"><!-- 1080p 版本 --><Representation id="1080p" bandwidth="5000000" width="1920" height="1080" codecs="avc1.640028"><BaseURL>1080p/</BaseURL><SegmentTemplate timescale="1000" media="segment_$Number$.m4s" startNumber="1" /></Representation><!-- 720p 版本 --><Representation id="720p" bandwidth="2500000" width="1280" height="720" codecs="avc1.64001F"><BaseURL>720p/</BaseURL><SegmentTemplate timescale="1000" media="segment_$Number$.m4s" startNumber="1" /></Representation></AdaptationSet></Period>
</MPD>

字段说明解释:

  • MPD:根元素,定义整个 DASH 播放内容。
  • Period:表示一个播放周期(多个 Period 可用于直播)。
  • AdaptationSet:定义一组可互换的流,如不同分辨率的视频。
  • Representation
    • id="1080p":该流的 ID,表示 1080p 版本。
    • bandwidth="5000000":码率 5Mbps。
    • codecs="avc1.640028":H.264 编码。
  • BaseURL:片段所在的路径。
  • SegmentTemplate
    • media="segment_$Number$.m4s":片段命名格式,如 segment_1.m4ssegment_2.m4s
    • startNumber="1":从 segment_1.m4s 开始播放。

DASH的模式

VOD(点播)

  • type="static"(静态 MPD),MPD 预先定义好所有片段,适用于点播视频
  • 片段是固定的,不会实时更新。

Live(直播)

  • type="dynamic"(动态 MPD),MPD 会不断更新,支持直播流。

  • 直播 MPD 示例:

    <MPD type="dynamic" minimumUpdatePeriod="PT5S"><Period><AdaptationSet><SegmentTemplate media="live_$Number$.m4s" startNumber="1000" /></AdaptationSet></Period>
    </MPD>
    
    • minimumUpdatePeriod="PT5S":每 5 秒更新一次 MPD。
    • startNumber="1000":直播流的分片编号从 1000 开始。

DASH 与 HLS 对比

特性DASHHLS
开发组织MPEGApple
封装格式MP4(fMP4)、TSTS、fMP4
码率切换客户端自适应客户端自适应
加密支持 Widevine、PlayReady、FairPlay主要支持 FairPlay
CDN 兼容性更适合 Apple 生态
播放器支持支持 HTML5、ExoPlayer、Shaka PlayerApple 设备原生支持
直播支持
  • DASH 适用于 PC、Android、Windows 设备,但 iOS 设备上不原生支持。
  • HLS 是 Apple 生态的标准,iPhone/iPad/Safari 直接支持。

DASH 播放器

常见的 DASH 播放器:

  • Shaka Player(Google):开源,支持 DRM(推荐)
  • dash.js(官方):MPEG-DASH 官方播放器
  • ExoPlayer(Android):支持 DASH、HLS
  • Video.js + Dash Plugin:支持 DASH 播放

示例:使用 dash.js 在 HTML5 中播放 DASH 视频:

<video id="video" controls></video>
<script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
<script>var player = dashjs.MediaPlayer().create();player.initialize(document.getElementById("video"), "https://example.com/video/manifest.mpd", true);
</script>

DASH应用(c++)

C++ 解析 DASH MPD 文件

MPD 文件是 XML 格式,可以使用 TinyXML2RapidXMLpugixml 解析它。

// c++ 使用 TinyXML2 解析MPD文件
#include <iostream>
#include <string>
#include <vector>
#include "tinyxml2.h"using namespace tinyxml2;
using namespace std;struct Representation {string id;int bandwidth;int width, height;string codecs;string baseURL;string segmentTemplate;int startNumber;
};vector<Representation> parseMPD(const string& xmlFile) {XMLDocument doc;if (doc.LoadFile(xmlFile.c_str()) != XML_SUCCESS) {cerr << "Failed to load MPD file!" << endl;return {};}vector<Representation> representations;XMLElement* mpd = doc.FirstChildElement("MPD");if (!mpd) return representations;XMLElement* period = mpd->FirstChildElement("Period");if (!period) return representations;XMLElement* adaptationSet = period->FirstChildElement("AdaptationSet");while (adaptationSet) {XMLElement* representation = adaptationSet->FirstChildElement("Representation");while (representation) {Representation rep;rep.id = representation->Attribute("id");representation->QueryIntAttribute("bandwidth", &rep.bandwidth);representation->QueryIntAttribute("width", &rep.width);representation->QueryIntAttribute("height", &rep.height);rep.codecs = representation->Attribute("codecs");XMLElement* baseURL = representation->FirstChildElement("BaseURL");if (baseURL) rep.baseURL = baseURL->GetText();XMLElement* segmentTemplate = representation->FirstChildElement("SegmentTemplate");if (segmentTemplate) {rep.segmentTemplate = segmentTemplate->Attribute("media");segmentTemplate->QueryIntAttribute("startNumber", &rep.startNumber);}representations.push_back(rep);representation = representation->NextSiblingElement("Representation");}adaptationSet = adaptationSet->NextSiblingElement("AdaptationSet");}return representations;
}int main() {string xmlFile = "dash.mpd";vector<Representation> reps = parseMPD(xmlFile);for (const auto& rep : reps) {cout << "ID: " << rep.id << " | Bandwidth: " << rep.bandwidth << " | Resolution: " << rep.width << "x" << rep.height << " | URL: " << rep.baseURL << endl;}return 0;
}

解析结果示例:

ID: 1080p | Bandwidth: 5000000 | Resolution: 1920x1080 | URL: https://example.com/dash/1080p/
ID: 720p | Bandwidth: 2500000 | Resolution: 1280x720 | URL: https://example.com/dash/720p/

C++ 下载 DASH 片段

// c++使用 libcurl 下载 DASH 片段
#include <iostream>
#include <fstream>
#include <curl/curl.h>using namespace std;size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {((ofstream*)userp)->write((char*)contents, size * nmemb);return size * nmemb;
}bool downloadSegment(const string& url, const string& filename) {CURL* curl = curl_easy_init();if (!curl) return false;ofstream file(filename, ios::binary);if (!file.is_open()) return false;curl_easy_setopt(curl, CURLOPT_URL, url.c_str());curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);CURLcode res = curl_easy_perform(curl);curl_easy_cleanup(curl);file.close();return (res == CURLE_OK);
}int main() {string url = "https://example.com/dash/1080p/segment_1.m4s";string filename = "segment_1.m4s";if (downloadSegment(url, filename)) {cout << "Download successful: " << filename << endl;} else {cerr << "Download failed!" << endl;}return 0;
}

C++ 生成 DASH MP4 片段

可以使用 FFmpeg 进行 MP4 分片:

ffmpeg -i input.mp4 -c copy -map 0 -f dash -segment_time 4 output.mpd

或者用 GPAC MP4Box

MP4Box -dash 4000 -frag 4000 -segment-name segment_ output.mp4

DASH 播放(C+++WebRTC/SRS)

如果要搭建 DASH 服务器,可以使用 SRS(Simple Realtime Server):

./objs/srs -c conf/dash.conf

SRS 支持 DASH 直播,将流转换为 DASH 格式,MPD 地址类似:

http://yourserver/live/output.mpd

然后可以在前端使用 dash.js 播放:

<video id="video" controls></video>
<script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
<script>var player = dashjs.MediaPlayer().create();player.initialize(document.getElementById("video"), "http://yourserver/live/output.mpd", true);
</script>

常见问题

1. 为什么 DASH 播放有延迟?

  • DASH 直播默认会有几秒钟缓存,减少卡顿。如果要降低延迟,可以调整 SegmentTimelinebuffering settings

2. DASH 适合 WebRTC 低延迟直播吗?

  • 不适合。DASH 主要用于 VOD 和传统直播,WebRTC 更适合低延迟交互式直播。

总结

  • DASH 是 HTTP 传输协议,不依赖专用流媒体服务器
  • 支持自适应码率,确保流畅播放
  • 适用于 VOD 和直播,兼容各种编码格式
  • 播放器支持需要额外集成(如 dash.js、Shaka Player)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词