🎬

アダプティブストリーミングについての基礎知識

に公開

本記事はいちぴろ・エクスプローラ Advent Calendar 2025 Day6の記事です。

はじめに

この記事では、YouTubeやNetflixなどで使われている アダプティブストリーミング(Adaptive Bitrate Streaming/ABR) の基本的な仕組みや用語を、ふんわりと紹介します。
HLSやMPEG-DASHといったプロトコルの概要から、マニフェストファイル(m3u8/MPD)の中身の違い、実際に触るときに使えるライブラリ・ツールまでをざっと触れていきます。

自己紹介

広島市立大学公認サークル「いちぴろ・エクスプローラ」のゆ〜りんです。
普段は動画ストリーミングや情報指向ネットワーク周りの研究・開発をしていて、HLSやMPEG-DASHを触りながら「どうすればネットワーク全体の帯域を節約しつつ、そこそこキレイに再生できるか?」みたいなことを研究しています。
今回の記事も、そうした研究や趣味の中で触ってきた知識を、自分なりに整理してまとめたものになります。

アダプティブストリーミングってなに?

YouTubeやNetflixを見ていて、

  • 回線が速いときは1080pや4Kでスムーズに再生
  • 電車の中など回線が不安定なときは480pくらいに落ちるけど、止まらず再生される

みたいな経験があると思います。

この「ネットワーク状況に合わせて自動で画質(ビットレート)を切り替えながら配信する仕組み」が、アダプティブストリーミング(Adaptive Bitrate Streaming/ABR)です。

代表的な方式はこのあたりです。

  • HLS (HTTP Live Streaming)
    Appleが提案した方式で、iOS/macOS/Safariでの再生と相性が良い。
  • MPEG-DASH (Dynamic Adaptive Streaming over HTTP)
    標準化団体MPEGが作った方式。ブラウザやプレイヤーライブラリ経由で幅広く使われている。

どちらも「HTTPで小さい動画ファイルをちょっとずつ取ってきて再生する」という思想は一緒です。

アダプティブストリーミングの定義

ここでは、アダプティブストリーミングを次のように定義します。

同じコンテンツを複数のビットレート/解像度にエンコードしておき、クライアント側がネットワークの状況などを見ながら、 どのビットレートのセグメントを取得するかを逐次選択するストリーミング方式

ポイントを分解すると、こんな感じになります。

  1. 複数バージョンを用意する
    例)240p/480p/720p/1080p… を事前にエンコードしておく。

  2. 細かいかたまり(セグメント)に分割する
    2〜6秒くらいの小さな.tsや.m4sファイルに分ける。

  3. HTTP経由で配信する
    特別な専用プロトコルではなく、普通のHTTP(S)で配る。

  4. クライアントが選ぶ
    サーバではなく、プレイヤー側がスループットやバッファ量を見ながら
    「次は720pのセグメントにしよう」
    「ネットワークの帯域が足りなさそうなので一段下げよう」
    などを自律的に決める。

アダプティブストリーミングで帯域に応じて解像度が切り替わるイメージ
アダプティブストリーミングで帯域に応じて解像度が切り替わるイメージ

上の図のように、時間とともに利用可能な帯域が変動すると、プレイヤーはそれに合わせて1080p/720p/480p…のように取得するセグメントのビットレートを切り替えていきます。

マニフェストファイルとセグメント(tsファイルなど)

アダプティブストリーミングでは、ざっくりいうと

  • 設計図:マニフェストファイル
  • 実データ:セグメントファイル(ts/m4sなど)

という2段構成になっています。

マニフェストファイル(プレイリスト)

HLSやDASHでは、配信の「設計図」となるテキストファイルが用意されています。

  • HLS:.m3u8 ファイル(拡張M3U)
  • MPEG-DASH:.mpd ファイル(XML)

ここには以下のような情報が書かれています。

  • 利用できるビットレートや解像度(代表ビットレート、解像度、コーデック)
  • それぞれのセグメントファイルへのパス
  • セグメントの長さや開始時刻
  • ライブかVODか

などなど...

プレイヤーはまずこのマニフェストを取得し、中身を解析して

  • どのビットレートから再生を始めるか
  • 次はどのURLを取りに行くか

を決めます。

MPDとm3u8の中身を比べてみる

ここから少し踏み込んで、MPEG-DASHのMPDとHLSのm3u8を、実際の中身ベースでざっくり比較してみます。

例:HLSのm3u8(マスタープレイリスト)

master.m3u8
#EXTM3U
#EXT-X-VERSION:3

# 720p
#EXT-X-STREAM-INF:BANDWIDTH=3000000,RESOLUTION=1280x720
720p/index.m3u8

# 480p
#EXT-X-STREAM-INF:BANDWIDTH=1500000,RESOLUTION=854x480
480p/index.m3u8

この「マスタープレイリスト」には、

  • どのビットレート/解像度のバリエーションがあるか
  • それぞれのバリエーション用のメディアプレイリストのURL

が書かれています。
各 720p/index.m3u8/480p/index.m3u8の中に、さらにセグメント一覧が並びます。

index.m3u8
# たとえば720p/index.m3u8(メディアプレイリスト)
#EXTM3U
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0

#EXTINF:4.0,
720p_000.ts
#EXTINF:4.0,
720p_001.ts
#EXTINF:4.0,
720p_002.ts
...

HLSは

  • マスター(バリエーション一覧)
  • メディア(各ビットレートのセグメント一覧)

という2段構成になっているのがポイントです。

例: MPEG-DASHのMPD

同じような内容を、DASHではこんな感じで書きます。

index.mpd
<?xml version="1.0"?>
<MPD type="static" minBufferTime="PT4S"
    mediaPresentationDuration="PT60S"
    xmlns="urn:mpeg:dash:schema:mpd:2011">

  <Period id="1" start="PT0S">
    <AdaptationSet id="1" contentType="video" mimeType="video/mp4" codecs="avc1.4d401f">

      <!-- 720p -->
      <Representation id="v720" width="1280" height="720" bandwidth="3000000">
        <BaseURL>720p/</BaseURL>
        <SegmentTemplate media="segment_$Number$.m4s"
                         initialization="init.m4s"
                         startNumber="0" duration="4" />
      </Representation>

      <!-- 480p -->
      <Representation id="v480" width="854" height="480" bandwidth="1500000">
        <BaseURL>480p/</BaseURL>
        <SegmentTemplate media="segment_$Number$.m4s"
                         initialization="init.m4s"
                         startNumber="0" duration="4" />
      </Representation>

    </AdaptationSet>
  </Period>
</MPD>

DASHでは

  • XMLで、1つのMPDファイルの中に
    • 期間(Period)
    • 映像/音声などのセット(AdaptationSet)
  • 各ビットレートのバリエーション(Representation)
    セグメントURLのパターン(SegmentTemplate)や初期化セグメント(init.m4s)の場所

などをまとめて記述します。

MPDとm3u8の違いざっくりまとめ

  • フォーマット
    • m3u8: テキストベースで、#EXTINFなどのタグを並べるシンプルな形式
    • MPD: XMLベースで、階層構造がはっきりしている
  • 構造
    • HLS:
      • マスタープレイリストとメディアプレイリストが分かれている
      • セグメントURLを1行ずつ列挙することが多い
    • DASH:
      • 1つのMPDの中にバリエーションや期間をまとめて書く
      • SegmentTemplateやSegmentTimelineで、パターンやタイムラインを表現できる
  • 時間の扱い
    • HLS: #EXTINF:4.0のように「このセグメントは4秒」と書いて積み上げるイメージ
    • DASH: PT4S(ISO 8601形式)のようにdurationを書いたり、SegmentTimelineで詳細に管理できる

どちらも「やりたいこと」は似ていますが、設計思想や表現の仕方が少し違うので、実際に中身を見比べてみると理解が早まります。

セグメントファイル(ts/m4sなど)

実際の動画データは、数秒ごとの小さな動画ファイルとして保存されています。

  • HLSの古典的な形:.ts(MPEG-TS)
  • 近年のLow-Latency HLS/DASH:.m4s(fMP4)もよく使われる

イメージとしては、ビットレートごとに時間軸に沿ってセグメントが並んでいて、その中から「次はどのレベルを取るか」を選びながら再生していきます。

アダプティブストリーミングの技術要素

適応アルゴリズム(ABRアルゴリズム)

どのビットレートに切り替えるかを決めるロジックもいろいろ研究されています。

  • スループットベース
    最近ダウンロードできていた速度から、安全に再生できそうなビットレートを選ぶ。

  • バッファベース
    再生バッファに何秒分たまっているかで判断。バッファが薄いと低ビットレートに落とす。

  • ハイブリッド
    スループットとバッファの両方を見て決める方式。

低遅延配信や5G/モバイル環境を意識した新しいアルゴリズムもいろいろ出てきています。

低遅延HLS/DASH

スポーツ中継やライブ配信では

  • 視聴者同士でタイムラグを小さくしたい
  • SNSでネタバレされたくない

といった理由から、Low-Latency HLS/Low-Latency DASHのニーズも高まっています。

  • セグメントを細かく刻む
  • HTTP/1.1のchunked transferを使って、生成しながら配信する
  • サーバ・CDN側のチューニングが必要

など、通常のVODよりも設計ポイントが増えます。

開発に使用できるツールやライブラリ

「実際に触ってみたい」「自分でプレイヤーを組み込みたい」人向けに、よく使われるツールやライブラリをざっと挙げておきます。

ブラウザ向けプレイヤーライブラリ

  • Shaka Player
    Google製のJavaScriptプレイヤー。DASH/HLS両方対応。
    ABRアルゴリズムやDRM(Widevineなど)との連携機能が豊富。

https://github.com/shaka-project/shaka-player

  • hls.js
    ブラウザのMedia Source Extensions (MSE)を使って、
    HLS(.m3u8)をほとんどのモダンブラウザで再生できるライブラリ。

https://github.com/video-dev/hls.js

  • dash.js
    MPEG-DASH用のリファレンス実装的なプレイヤー。
    プロトタイピングや検証に使いやすいです。
    公式ドキュメントとサンプルプレイヤーはこちら:

https://dashjs.org/

サーバ・エンコーダ・配信基盤

  • Wowza Streaming Engine/Wowza Streaming Cloud
    ライブ配信・トランスコード・パッケージングまで一通り対応した商用ソフト。
    30日間有効な無料トライアルアカウントの発行も行えるため、個人利用も行えます。
    評価版ダウンロードやチュートリアルは公式サイトから取得できます:

https://www.wowza.com/products/streaming-engine

  • FFmpeg
    ローカルでHLS/DASHセグメントを生成したり、ライブ入力をパッケージングしたりできるツール。

DRMやCDNなどの課題

実際に商用サービスとして配信する段階になると、コンテンツ保護(DRM)やCDN 配信周りで課題が増えてきます。

DRM(デジタル著作権管理)

  • 配信側はコンテンツを暗号化し、再生側はライセンスサーバから鍵を取得して復号する。
  • ブラウザでは EME (Encrypted Media Extensions) 経由でWidevineなどのDRMと連携するのが一般的。
  • 各プラットフォームでサポートしているDRMが違うので、マルチデバイス対応しようとすると構成が一気に複雑になる。

CDN(コンテンツ配信ネットワーク)

アダプティブストリーミングは大量の小さいファイルをさばくので、オリジンサーバ1台だけだとすぐ限界が来ます。
そこでCDNが必要になります。

  • 世界中のエッジサーバにキャッシュして、ユーザから近い場所から配信する。
  • ただしビットレートがたくさんあるとキャッシュ効率が落ちたり、セグメント長やライブ更新の仕方によってキャッシュヒット率が変わったりする。
  • マルチCDN(複数ベンダを切り替える)を使うケースも増えており、どのCDNを選ぶか、どのリージョンに置くか、といった運用課題も出てくる。

低遅延・スケーラビリティ

  • 通常のHLS/DASHだと20〜30秒くらい遅延が出ることも多い。
  • スポーツ中継やeスポーツ配信では、より短い遅延が求められる。

低遅延化すると、セグメントの刻み方やCDNの構成が変わるため、

  • サーバ側のリソース設計
  • キャッシュ戦略
  • 視聴者数が増えたときのスケール

などもあわせて考える必要が出てきます。

さいごに

アダプティブストリーミングは、

  • 表側は「画質が勝手にいい感じに変わってくれる便利な仕組み」
  • 裏側は「マニフェスト・セグメント・CDN・ネットワーク制御が全部絡んだ総合的な技術」

みたいな世界です。

この記事では

  • HLS/DASHのざっくりとした仕組み
  • マニフェスト+セグメントの考え方
  • 使えるツール・ライブラリ
  • DRM/CDN周りの課題

を駆け足気味で紹介しました。

もし興味が湧いたら、

  • ローカルでFFmpegを使ってHLSを作ってみる
  • Shaka Player/hls.jsで、帯域を変えながら画質が変わる様子を観察してみる

あたりから始めると、ABRの挙動について理解が深まるのではないかなと思います。
この記事が「ABRなんとなく分かったかも」の入口になればうれしいです。

補足: サンプル動画「Big Buck Bunny」について

アダプティブストリーミングの検証用コンテンツとして、チュートリアルやサンプルでBig Buck Bunnyというウサギのアニメ映画がよく使われます。

https://peach.blender.org/

Blender Foundationが公開しているオープンムービーで、オープンソース系のライセンス(Creative Commons)で配布されており、条件を守れば研究用途や商用利用も可能なことが、サンプルとして広く使われている理由のひとつです。
自分で試験的な配信環境を構築する際も、こういったオープンなコンテンツを使うと安心です。

Discussion