MPEG-DASH完全ガイド:プロトコル原理、Dash.js実装とHLS比較
HLSの次に最も重要なストリーミングプロトコルがMPEG-DASHです。YouTube、Netflixが使用し、ISO国際標準です。HLSと比較して、DASHはより柔軟でオープンですが、エコシステムはHLSほど成熟していません。このガイドでは、DASHの原理から実装までをカバーします。
DASHの基本
DASH(Dynamic Adaptive Streaming over HTTP)はMPEGが2012年にリリースしたストリーミング標準です:
- HTTPベース:標準HTTPサーバーで配信、特別なサーバー不要
- アダプティブビットレート(ABR):ネットワーク状況に応じて品質を自動切り替え
- オープン標準:ISO/IEC 23009-1、ロイヤリティフリー
- コーデック非依存:H.264、H.265、VP9、AV1などをサポート
DASHの動作原理
- コンテンツ準備:ビデオを複数の品質レベルにエンコード
- セグメント分割:各品質を2-10秒のセグメントに分割
- MPD生成:メディアプレゼンテーション記述(MPD)ファイルを作成
- クライアント再生:プレーヤーがMPDを読み込み、ネットワーク状況に応じてセグメントを順次ダウンロード
HLSとの構造比較
| 特徴 | HLS | DASH |
|---|---|---|
| 標準化団体 | Apple | MPEG (ISO) |
| インデックスファイル | M3U8(テキスト) | MPD(XML) |
| セグメント形式 | TS、fMP4 | fMP4、TS |
| ブラウザネイティブサポート | Safari | なし |
| JSライブラリ | hls.js | dash.js |
| レイテンシ | 5-30秒 | 5-30秒 |
| 低遅延サポート | LL-HLS | LL-DASH |
| DRM | FairPlay、Widevine、PlayReady | Widevine、PlayReady |
| 主要ユーザー | Apple、Twitch | YouTube、Netflix |
MPDファイル構造
MPD(Media Presentation Description)はDASHのマニフェストファイル、XML形式:
xml
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011"
type="static"
mediaPresentationDuration="PT1H30M0S"
minBufferTime="PT2.0S"
profiles="urn:mpeg:dash:profile:isoff-live:2011">
<Period>
<!-- ビデオ適応セット -->
<AdaptationSet mimeType="video/mp4" contentType="video">
<!-- 720p -->
<Representation id="v1" bandwidth="2000000" width="1280" height="720" codecs="avc1.4d401f">
<BaseURL>video_720p/</BaseURL>
<SegmentList duration="2">
<SegmentURL media="segment-1.m4s"/>
<SegmentURL media="segment-2.m4s"/>
<!-- ... -->
</SegmentList>
</Representation>
<!-- 1080p -->
<Representation id="v2" bandwidth="4000000" width="1920" height="1080" codecs="avc1.4d4028">
<BaseURL>video_1080p/</BaseURL>
<SegmentList duration="2">
<SegmentURL media="segment-1.m4s"/>
<SegmentURL media="segment-2.m4s"/>
</SegmentList>
</Representation>
</AdaptationSet>
<!-- オーディオ適応セット -->
<AdaptationSet mimeType="audio/mp4" contentType="audio">
<Representation id="a1" bandwidth="128000" codecs="mp4a.40.2">
<BaseURL>audio/</BaseURL>
<SegmentList duration="2">
<SegmentURL media="segment-1.m4s"/>
<SegmentURL media="segment-2.m4s"/>
</SegmentList>
</Representation>
</AdaptationSet>
</Period>
</MPD>主要な要素
- MPD:ルート要素、メディア全体の情報
- Period:期間、異なるコンテンツセグメントを表現
- AdaptationSet:適応セット、ビデオまたはオーディオ
- Representation:特定の品質レベル
- SegmentList/SegmentTemplate:セグメントのリストまたはテンプレート
Dash.jsブラウザ実装
基本的な再生
html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
</head>
<body>
<video controls style="width: 640px; height: 360px;"></video>
<script>
const video = document.querySelector('video');
const player = dashjs.MediaPlayer().create();
player.initialize(video, 'https://example.com/stream.mpd', true);
</script>
</body>
</html>高度な設定
javascript
const player = dashjs.MediaPlayer().create();
// 設定
player.updateSettings({
streaming: {
buffer: {
bufferTarget: 30, // ターゲットバッファ(秒)
bufferTimeAtTopQuality: 30,
bufferTimeAtTopQualityLongForm: 60
},
abr: {
autoSwitchBitrate: true, // 自動ビットレート切り替え
initialBitrate: { video: 2000000 }, // 初期ビットレート
maxBitrate: { video: 5000000 } // 最大ビットレート
}
}
});
player.initialize(video, 'stream.mpd', true);
// イベントリスナー
player.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, () => {
console.log('ストリーム初期化完了');
});
player.on(dashjs.MediaPlayer.events.QUALITY_CHANGE_REQUESTED, (e) => {
console.log(`品質切り替え: ${e.oldQuality} → ${e.newQuality}`);
});品質の手動切り替え
javascript
// 利用可能な品質を取得
const bitrates = player.getBitrateInfoListFor('video');
console.log('利用可能な品質:', bitrates);
// 特定の品質に設定
player.setRepresentationForTypeByIndex('video', 0, true); // 最高品質
player.setRepresentationForTypeByIndex('video', bitrates.length - 1, true); // 最低品質FFmpegでのDASHセグメント生成
基本的なDASH生成
bash
# 単一品質のDASHセグメント生成
ffmpeg -i input.mp4 \
-c:v libx264 -preset fast -crf 23 \
-c:a aac -b:a 128k \
-f dash \
-seg_duration 2 \
-adaptation_sets "id=0,streams=v id=1,streams=a" \
output.mpd複数品質のDASH生成
bash
# 複数品質レベルを生成
ffmpeg -i input.mp4 \
-filter_complex "[0:v]split=3[v1][v2][v3]; \
[v1]scale=640:360[v1out]; \
[v2]scale=1280:720[v2out]; \
[v3]scale=1920:1080[v3out]" \
-map "[v1out]" -c:v:0 libx264 -b:v:0 800k \
-map "[v2out]" -c:v:1 libx264 -b:v:1 2000k \
-map "[v3out]" -c:v:2 libx264 -b:v:2 4000k \
-map a:0 -c:a:0 aac -b:a:0 128k \
-map a:0 -c:a:1 aac -b:a:1 128k \
-map a:0 -c:a:2 aac -b:a:2 128k \
-f dash \
-seg_duration 2 \
-adaptation_sets "id=0,streams=v:0,v:1,v:2 id=1,streams=a:0,a:1,a:2" \
output.mpdDASH vs HLS:どちらを選ぶべきか
DASHを選ぶ場合
- Androidとウェブが主なターゲット
- YouTubeやNetflixのような大規模ストリーミング
- 低遅延ストリーミングが必要(LL-DASH)
- オープン標準とコーデック柔軟性を重視
HLSを選ぶ場合
- iOSユーザーが多い
- Safariネイティブサポートが必要
- 成熟したエコシステムが必要
- Twitchのようなライブストリーミングプラットフォーム
CMAFで両方をサポート
CMAF(Common Media Application Format)はHLSとDASHの両方で使用できる共通フォーマットです:
bash
# CMAFセグメントを生成
ffmpeg -i input.mp4 \
-c:v libx264 -c:a aac \
-f dash \
-seg_duration 2 \
-use_template 1 \
-use_timeline 1 \
-format_options "movflags=cmaf" \
output.mpd同じセグメントをHLSとDASHの両方で使用でき、ストレージと帯域幅を節約できます。
よくある問題
| 問題 | 原因 | 解決策 |
|---|---|---|
| Safariで再生できない | DASHネイティブ非サポート | HLSまたはdash.js使用 |
| 品質切り替えが頻繁 | ABR設定が適切でない | バッファターゲットを増やす |
| セグメントダウンロード失敗 | CORS問題 | サーバーにCORSヘッダー追加 |
| レイテンシが高い | 通常のDASH | LL-DASH使用 |
| MPD解析エラー | XMLフォーマットエラー | MPDファイルを検証 |
まとめ
MPEG-DASHはHLSに次ぐ重要なストリーミングプロトコルです:
- オープン標準:ISO国際標準、ロイヤリティフリー
- 柔軟性:コーデック非依存、DRM柔軟
- 大規模ユーザー:YouTube、Netflixが採用
- 低遅延:LL-DASHでサブ秒遅延可能
クイックリファレンス:
- 基本再生: dash.js +
player.initialize(video, 'stream.mpd', true) - FFmpeg生成:
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -f dash output.mpd - 複数品質: filter_complexで複数スケール生成
- iOSサポート: HLSまたはCMAF使用