iOSで AVPlayer に .m3u8 を投げ渡すと、まるで魔法のように画質が切り替わります。
しかし、OSの内部では**「魔法ではなく、泥臭い計測と算数」**が行われています。
プレイヤーが現在の電波状況(ネットワーク品質)を割り出すロジックの裏側を覗いてみましょう。
1. 「パケットの到達時間」からスループットを逆算する
プレイヤーは、数秒の動画の塊(セグメント:.ts や .mp4)をHTTP/HTTPSで1つダウンロードするたびに、以下の計算を行っています。
[\text{通信速度 (bps)} = \frac{\text{ダウンロードしたセグメントのファイルサイズ (bits)}}{\text{リクエスト開始から完了までの時間 (seconds)}}]
これが、先ほどのコードで取得した observedBitrate(ガチの実測値) の正体です。
電波の強さ(電波バーの1本〜4本)を直接見ているのではなく、**「今、動画の切れ端が何秒で届いたか」**という実績ベースで世界を見ています。
2. 急な変化に惑わされない「移動平均(Moving Average)」
「一瞬だけパケ詰まった」「一瞬だけ超爆速になった」というノイズでいちいち画質をガタガタ変えていたら、ユーザーの目が疲れてしまいます。
そこで AVFoundation(OSの動画再生エンジン)は、直近数個のセグメントのダウンロード速度に対して、指数移動平均などのフィルタリングをかけています。
プレイヤーは「過去のトレンドを含めた、なだらかな通信速度の予測値」を算出し、それをベースに次の画質を決定しているのです。
🏗️ 仕組みの核心:マスターとメディアの「スイッチング・アーキテクチャ」
電波の予測値(スループット)が出たら、次は**「どの画質に切り替えるか」**の判定フェーズです。ここで HLS の .m3u8 の構造が牙を剥きます。
プレイヤーの脳内で行われている「脳内会議」をシーケンス風に表すとこうです。
ユーザー ──(動画再生して)──> [ AVPlayer ]
│
├─① まず「マスタープレイリスト」を解析
│ ├─ 1080p: 5,000,000 bps (5Mbps)
│ ├─ 720p: 2,500,000 bps (2.5Mbps)
│ └─ 360p: 800,000 bps (0.8Mbps)
│
├─② 最初のセグメントを落として電波計測
│ └─ 「実測 3.2Mbps 出てるな」と判断
│
├─③ 脳内会議:「5Mbpsは無理だけど、2.5Mbpsならいける!」
│
└─④ 「720pのメディアプレイリスト」へ突撃
└─ 720pのセグメントを順番に要求し始める
境界線(スレッショルド)の罠:なぜギリギリの電波だと画質が落ちるのか?
マスタープレイリストに書かれている BANDWIDTH=2500000(2.5Mbps)という値は、プレイヤーに対する**「この画質で再生したければ、最低でもこれだけの帯域を常に用意しろよ」という挑戦状**です。
実測値(observedBitrate)がこの数値を下回った、あるいは下回りそうだと判断された瞬間、プレイヤーは命を守るために(バッファが枯渇して動画が止まるのを防ぐために)、即座に1つ下の画質(360p)のメディアプレイリストへ乗り換えます。
⚡️ アプリ開発者が介入できる「ポリシー制御」の仕組み
OSにお任せの自動切り替え(ABR)ですが、アプリ側から**「大人の事情(大容量通信の制限や、逆に最高画質の強制)」**を突きつけることができます。
AVFoundationが提供しているプロパティは、この「脳内会議」のルールを書き換える強力な権限を持っています。
┌────────────────────────────────────────────────────────┐
│ [ AVPlayerItem ] │
│ │
│ ■ preferredPeakBitRate (上限の壁) │
│ → 通信速度が 100Mbps あっても、ここで指定した │
│ ビットレート以上の画質は「絶対選ばせない」 │
│ │
│ ■ preferredStartingBitRate (最初の賭け) │
│ → 電波の実測値がまだゼロの「再生開始の1秒目」、 │
│ どの画質からガチャを引くかの初期値を指定する │
└────────────────────────────────────────────────────────┘
技術的な使い分けの妙
-
preferredPeakBitRate: ユーザーがアプリ内で「画質制限モード」をONにした時や、前述のNWPathMonitorでpath.isConstrained(低データモード)を検知した時に、上限を1,500,000(1.5Mbps)等に設定します。これにより、OSはどれだけ爆速な5G環境にいても、1080pのような贅沢なストリームを要求しなくなります。 -
preferredStartingBitRate: デフォルトだとOSは「まぁ安全圏からいくか」と低画質(360pなど)から読み込み始め、電波が良いと分かってから徐々に1080pに上げていきます。最初から絶対に綺麗な画質でドカンと見せたいリッチなアプリ(例:映画配信アプリなど)では、この初期値を高めに設定して勝負をかけます。