HLS は、かなり現実的な HTTP の使い方
HLS は HTTP Live Streaming の略です。Apple が 2009 年に作りました。もともとは iPhone や Safari で動画を安定して配信するための仕組みで、専用プロトコルよりも、普通の HTTP と小さなファイルの組み合わせを選んでいます。
プレーヤーはまずテキストのプレイリストを読み、そこに書かれた動画セグメントを順番に取りに行きます。ライブ配信なら、プレイリストが少しずつ更新されます。VOD なら、最後まで並んだリストを読み進めます。
Anoiona Tools の M3U8 プレーヤーに URL を貼ると、最初に問題になるのもここです。その M3U8 をブラウザが読めるか。そこに書かれたセグメントへアクセスできるか。動画のデコードより前で止まっているケースはかなり多いです。
M3U8 は動画本体ではなく案内板
M3U8 は UTF-8 のプレイリストです。先頭に #EXTM3U があり、#EXT-X- で始まるタグがストリームの情報を持ちます。
よく見るのは master playlist です。これは複数の品質をまとめる入口になります。
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=900000,RESOLUTION=640x360
360p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2800000,RESOLUTION=1280x720
720p/index.m3u8
もう一段進むと media playlist があります。こちらは実際のセグメントを並べます。
#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:1200
#EXTINF:6.000,
segment-1200.ts
#EXTINF:6.000,
segment-1201.ts
VOD では最後に #EXT-X-ENDLIST が入ることが多いです。ライブでは入らず、プレーヤーが数秒おきに同じ media playlist を読み直します。#EXT-X-MEDIA-SEQUENCE が増えていれば新しいセグメントが出ています。止まっていれば、配信側が更新できていないかもしれません。
セグメントが実際の映像を運ぶ
M3U8 は地図で、映像データはセグメントにあります。昔から多いのは .ts の MPEG-TS セグメントです。最近の構成では fMP4 を使い、初期化セグメントと .m4s のチャンクに分かれることもあります。
セグメント長は体感に響きます。6 秒前後はよくある設定です。短くするとライブ遅延を下げやすい一方で、HTTP リクエストが増えます。長くすると CDN には優しいことがありますが、品質切り替えやライブ追従は鈍くなります。
テストでは、プレイリストが読めるだけで安心しないほうがいいです。セグメントだけ CORS で止まる、署名 URL が期限切れになる、Cookie や Referer が必要になる、ブラウザがコーデックを扱えない。こういう失敗は普通に起きます。
Safari と HLS.js の役割分担
Safari と iOS のブラウザは HLS をネイティブに扱えます。つまり、<video> に M3U8 URL を直接入れるだけで再生できることがあります。
const video = document.querySelector("video");
video.src = "https://example.com/live/master.m3u8";
await video.play();
これは素直で速い方法です。ブラウザ内部の HLS 実装に任せられるので、余計な JavaScript の処理が少なく済みます。ただし、細かな品質制御や診断情報は取りにくくなります。
Chrome、Edge、Firefox のデスクトップ環境では、M3U8 をそのまま再生できないことがよくあります。そこで HLS.js を使います。HLS.js は playlist と segment を読み、必要に応じてメディアを変換し、Media Source Extensions 経由で video 要素に渡します。
import Hls from "hls.js";
const hls = new Hls();
hls.loadSource("https://example.com/live/master.m3u8");
hls.attachMedia(video);
Anoiona Tools の M3U8 プレーヤーもこの考え方です。Safari のようにネイティブ HLS が使える場合は直接再生します。そうでない場合は HLS.js を使い、manifest の解析結果やエラーを見ながら状態を表示します。
プレーヤー側で見ている細かいところ
入力された URL は HTTP または HTTPS か確認します。再生が始まると、ローカルの履歴、共有リンク、iframe 用コードをブラウザ内で作ります。履歴は localStorage なので、サーバーに再生リストを保存する設計ではありません。
master playlist に複数の variant があれば、品質選択を表示します。Auto と具体的な解像度、ビットレートを選べる形です。単一の media playlist だけなら選ぶものがないため、UI は出しません。
もう少し低いレイヤーでは、MPEG-TS の修復リトライもあります。一部の .ts セグメントは、先頭に余計なバイトが混ざっていて、TS パケットの同期バイト 0x47 が期待位置に来ません。標準再生が致命的な media/parsing エラーになったとき、プレーヤーは一度だけ、先頭付近を走査して 188 バイト周期の同期位置を探すローダーで再試行します。壊れた配信を何でも直すものではありませんが、テスト用の粗いストリームでは役に立つ場面があります。
実際にテストするときの見方
最初は M3U8 を直接確認します。
curl -I "https://example.com/live/master.m3u8"
curl "https://example.com/live/master.m3u8" | head
200 が返り、本文が #EXTM3U で始まるかを見ます。相対パスがある場合は、Web ページの URL ではなく、M3U8 ファイル自身の場所を基準に解決されます。
次に、media playlist に書かれたセグメントをひとつ選んで確認します。
curl -I "https://example.com/live/720p/segment-1201.ts"
ここで 403、404、ログインページへのリダイレクト、CORS エラーが出るなら、プレーヤーの前に配信条件を直す必要があります。ブラウザの DevTools では m3u8、ts、m4s で Network を絞ると、どのリクエストが止まっているか見つけやすいです。
ライブ配信では、数回リロードして media sequence が進むかも見ます。進まないライブ playlist は、プレーヤーから見ると待つしかありません。
HLS は仕組みとしては扱いやすいです。ただ、ひとつの URL ではなく、プレイリスト、セグメント、レスポンスヘッダー、コーデックの連鎖で動いています。どこで切れているかを分けて見ると、原因はかなり絞れます。