あなたのプライベートHLSストリームは、視聴者のためではなくあなたのために読み込まれる
サーバーがカメラに届くからページは読み込まれるが、プレイリストを取得するのは依然としてブラウザだ。誰がその要求をするのかを決め、それから連鎖を検証する。
ノートPCでページを試すとプレイヤーが起動し、チケットは閉じられる。向こう側の視聴者が同じページを開くと、いつまでも終わらない回転インジケーターが出る。よくある説明は「VPNはサーバー上にあるので再生できるはずだ」というものだが、プレイリストを要求しているのはブラウザであり、ブラウザには独自のネットワーク経路がある。プライベートアクセスを持つサーバーに埋め込まれたページが、そのアクセスを読み込む相手に貸し出すことはない。
これは、http://10.5.5.9:8080/live/stream.m3u8 のようなHLSソースを再生する既存のASP.NETページの話であり、このアドレスは例示用のプライベートアドレスだ。うまく機能する構成は二つあり、そのうちの一つはおそらくあなたが作ったものではない。
迷信:ページが読み込めたらメディア経路が証明される
そのページのHTMLはあなたのウェブサーバーから、ウェブサーバーが持つ経路を通って届く。プレイリストとセグメントはメディアのオリジンから、要求する側のコンポーネントが持つ経路を通って届く。プレイヤーが視聴者のブラウザで動くとき、この二つは別のクライアントであり、別の送信元アドレスであり、しばしば別の障害領域だ。前者の成功は後者について何も語らない。
あなたのテストが実際に証明したのは、見た目よりずっと狭いこと、つまりあなたのマシンが公開ページとプライベートなメディアホストの両方に同時に届くということだけだ。視聴者のマシンは実験に一度も加わっていない。
プレイリストが次に要求するもの
RFC 8216 は、セグメントを列挙するメディアプレイリストと、別のプレイリストを列挙するマスタープレイリストを区別し、相対URIをそれを含むプレイリストのURIに対して解決する。見落とされやすいのはまさにこの規則だ。ひとつの .m3u8 ファイルを取得できたことは、取得したファイルが索引であってメディアではないため、再生テストにはならない。
プレイヤーと同じように連鎖をたどる:選択されたプレイリストを開き、それが名指すリソースを要求し、その後に続くリダイレクトを追う。到達可能なウェブサーバー経由で配信されるプレイリストでも、視聴者を到達不能なプライベートアドレスへ向けることはある。同じように、相対プレイリストを別のURLへ移すとその項目を解決する基準が変わるため、最初に見えるURLだけを書き換えて止めると、有効に見えるのに再生できないプレイリストができあがる。
直接視聴:視聴者に経路が必要
視聴者がメディアホストへ直接到達する想定なら、その端末には承認されたVPNか別のプライベート経路、実際に使った名前を解決するDNS、それらの宛先への到達許可、そしてメディアサービスが要求する認証が必要だ。どれもサーバー上ではなく視聴者の端末で確認する。VPNプロファイルを入れたまま接続していないスマートフォンのブラウザは、よくある、そして完全に再現可能な失敗だ。
この構成はソースをプライベートに保ち、アクセスの要件を視聴者側へ押し出す。これは技術的な決定であると同時にポリシーの決定でもあるので、それを前提に設計する前に、想定するすべての視聴者がその経路を持てることを確認する。
サーバー側配信:単一の制御された入口
もう一つの選択肢は、プライベート経路でソースを取得し、視聴者向けのリソースだけを再公開する認可済みのメディアフロントエンドだ。プレイリスト、セグメント、鍵などのリソースをこの単一の入口と一貫させておかないと、プレイヤーはフロントエンド経由で書き換えられたプレイリストを、セグメントは視聴者が到達できないアドレスから直接取得してしまう。
そのフロントエンドでソースと許可する経路を制限する。利用者が与えた任意のURLは、便利なプロキシをあなたの内部ネットワークへの無制限の取得手段に変えてしまい、再生できないストリームよりはるかに悪い問題になる。文字列を後から検証するのではなく、オリジンと経路の接頭辞を許可リストに入れる。
既存のHLSソースでは、まず制御された転送で足りるかを確認する(途中にVPNがあるからといってトランスコードが必要になるわけではない)。次に、到達可能な応答と対応形式は別の条件であるため、実際のブラウザとコーデックの組み合わせを検証する。オリジンのTLS、認証、ブラウザのセキュリティ要件はそのまま保つ——埋め込みプレイヤーはそれらの例外ではない。
URLではなく連鎖をテストする
実際に各要求を行うコンポーネントから検査を実行し、各段階をそれぞれ独立した結果として扱う:
curl -s http://10.5.5.9:8080/live/stream.m3u8
curl -s -o /dev/null -w '%{http_code}\n' http://10.5.5.9:8080/live/segment-000123.tsそのうえで、机の上のテストパターンではなく意図したストリームを使い、視聴者自身のブラウザで繰り返す。ページの読み込み、プレイリストの読み込み、セグメントの取得、認可の失敗は四つの異なる結果であり、修正済みと言う前に四つすべてを観察したい。古い例がそうやって再生したからといって旧式のブラウザプラグインを入れず、足りない部分はたいてい視聴者の経路か署名されていないセグメントURLだと考えよう。
構成が意図的に選ばれたものになったら、一行に書き出す:誰がどの経路でメディアを取得し、視聴者が何を要求してよいのか。その一文が、このストリームは誰のためのものかという将来の議論のほとんどを決着させる。