CORS(Cross-Origin Resource Sharing / オリジン間リソース共有)とは、あるオリジンで実行されている JavaScript が別のオリジンのリソースを取得してよいかをブラウザが判断するためのセキュリティ規則です。HLS 再生は複数のリソースタイプに関与します。メインマニフェスト、バリアントプレイリスト、メディアセグメント、字幕、そして場合によっては暗号化キーです。これらのエンドポイントのいずれか1つでも誤ったヘッダーを返すと、URL 自体が技術的に有効であっても再生は失敗します。
比較に使用した正常な CORS レスポンスの例
Origin: https://freem3u8.com を付与して公開 Mux マスタープレイリストをリクエストしました。レスポンスは HTTP 200 と Access-Control-Allow-Origin: * を返し、ブラウザ側インスペクターは警告なしで単一ホスト名上の5つのバリアントを持つマスタープレイリストとして正常に認識しました。このレスポンスパターンを基準とし、認証情報が必要なストリームにはより厳格なオリジンルールを適用してください。
エラーがブラウザでのみ発生する理由
VLC、ffmpeg、またはネイティブのモバイルプレーヤーなどのツールは、ブラウザと同じウェブセキュリティポリシー(同一オリジンポリシーや CORS)を強制しません。そのため、ある環境では完全に正常に見えるストリームであっても、通常のウェブページ上では再生できないという事態が起こります。ブラウザベースのプレーヤーが有用なのは、まさにこのクライアント側の制約を正確に再現できるからです。
最も重要な HTTP レスポンスヘッダー
Access-Control-Allow-Origin: リクエスト元のサイトを明示的に許可するか、適切な場合は*を指定します。Access-Control-Allow-Methods: ブラウザが使用するメソッド(GET、HEAD、OPTIONS など)を許可します。Access-Control-Allow-Headers: カスタムヘッダーがリクエストに含まれる場合に必要となります。- 認証情報(Cookie や Authorization ヘッダー)を伴うリクエストの場合、ワイルドカード(
*)指定は使用できません。
公開ストリーム向けの最小限のヘッダー構成例
Cookie を必要としない公開・トークンなしのストリームの場合、まずは HLS 関連ファイル全体に対してシンプルな許可ルールを設定するのが一般的です。サーバー側の設定構文は環境によって異なりますが、レスポンスヘッダーの要件は共通です。
Access-Control-Allow-Origin: https://freem3u8.com
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Allow-Headers: Range
Access-Control-Expose-Headers: Content-Length, Content-Range
複数の信頼できるドメインにプレーヤーを埋め込む場合は、それらのオリジンを意図的にリストアップしてください。Cookie や認証情報を使用するストリームでは、認証フラグとワイルドカードオリジンを併用することはできません。
最初に確認すべきポイント
まずはマニフェスト URL から確認します。プレーヤーが最初の M3U8 ファイルを取得できなければ、ストリーム全体が初期化されません。マニフェストは読み込めるのに再生が始まらない場合は、子プレイリストとセグメントのリクエストを調査してください。トップレベルのマニフェストはオープンに設定されている一方で、参照先セグメントがより厳しいアクセスルールの別オリジンを指しているケースが頻繁に見られます。
単純リクエスト、プリフライトリクエスト、および Range
一部の HLS リクエストは単純な GET リクエストですが、ヘッダー、認証情報、またはプレーヤーの実装によってはブラウザによるプリフライト(事前確認)リクエストが発生します。プリフライトリクエストは OPTIONS メソッドを使用して、実際のリクエストが許可されているかをサーバーに問い合わせます。サーバーが GET には適切なヘッダーを返しても OPTIONS を拒否(403 や 405)すると、セグメントのダウンロード前にメディアリクエストが失敗します。
Range リクエストの処理もよくある盲点です。メディアプレーヤーは、特に fMP4 やシーク操作時にファイルの一部分のみを要求することがあります。ブラウザが Range ヘッダーを送信した際にサーバーが関連レスポンスヘッダーを許可・公開(Expose)していないと、「マニフェストは読めるのに再生やシークが壊れる」といった不可解な現象が発生します。
HLS リクエストチェーン全体の確認
メインマニフェスト
最初のリクエストであり、プレーヤーが利用可能な画質一覧を解析できるかを決定づけます。
バリアントプレイリスト
各解像度は別パスや別 CDN ホスト名に存在することがあり、個別にヘッダーが必要です。
メディアセグメント
.ts や fMP4 セグメントへのリクエストが拒否されると、解析完了後に再生が止まります。
暗号化キーと字幕
暗号化ストリームや字幕は別リクエストを発生させ、同様のブラウザアクセス検証が必要です。
現場でよく見られる障害パターン
よくあるミスの1つは、メイン API ドメインと同じヘッダーを返さない CDN ドメインから署名付きセグメント URL を生成してしまうことです。また、マニフェストへの GET は許可したものの、セグメントのオリジンが異なる応答をするためブラウザが後続リクエストを遮断してしまうケースも多発します。
HLS リクエストチェーンの1つの層でもブロックされると、たとえ最初の URL が正常に見えても、プレーヤーは再生時に障害として表面化させます。
サーバーおよび CDN の設定例
具体的な記述構文はインフラ構成によりますが、ブラウザが求める本質は同じです。マニフェスト、バリアント、セグメント、字幕、キーのすべてが互換性のあるクロスオリジンヘッダーを返さなければなりません。
# 公開 HLS ファイル向け Nginx location 設定例
location /hls/ {
add_header Access-Control-Allow-Origin "https://freem3u8.com" always;
add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always;
add_header Access-Control-Allow-Headers "Range" always;
add_header Access-Control-Expose-Headers "Content-Length, Content-Range" always;
}
AWS S3 や S3 互換ストレージの場合は、プレーヤーを設置しているウェブページ側ではなく、バケット側で CORS を設定してください。CDN を利用している場合は、.m3u8 ファイルだけでなく、すべての HLS オブジェクトタイプでヘッダーが転送または付与されていることを確認します。
CDN キャッシュとヘッダー伝播の確認
CORS 設定を変更した後は、CDN が実際に新しいヘッダーを配信しているか確認してください。オリジンストレージの設定を更新したにもかかわらず、古いポリシーのままキャッシュされたセグメント応答が返され続けるケースが多々あります。オリジンのストレージ URL だけでなく、公開されている CDN URL 上のレスポンスヘッダーを確認してください。CDN が .m3u8、.ts、.m4s、字幕、キーファイルごとに異なるキャッシュ動作を持つ場合は、それぞれ個別に検証が必要です。
- ヘッダー変更後は、キャッシュされたマニフェストおよび代表的なセグメントファイルをパージ(消去)または再検証する。
- リダイレクトによって、異なる CORS ルールを持つ別のホスト名へ飛ばされていないか確認する。
- トップレベルのマニフェストと、少なくとも1つの子プレイリストまたはセグメント URL の両方をテストする。
- Cookie や認証の前提崩れを検知するため、通常のブラウザとシークレットウィンドウの両方でヘッダーを比較する。
Range リクエストと公開ヘッダー(Expose Headers)
一部の配信フローではバイトレンジ(Byte-range)リクエストが使用されます。CDN が範囲指定に関連するリクエストヘッダーやレスポンスヘッダーを除去してしまうと、マニフェストが読めても再生に失敗することがあります。デバッグ時は、マニフェスト、子プレイリスト、そして実際のセグメント URL のレスポンスヘッダーを比較してください。
- プリフライトリクエストが発生する可能性があるため、
GET、HEAD、OPTIONSを許可する。 - HTML ページにのみ適用されるヘッダールールに依存しない。
- プレーヤーがメディアの範囲情報を検査できるよう、
Content-LengthとContent-Rangeを公開(Expose)する。 - 認証付きストリームと、公開用のワイルドカード CORS ルールは明確に分離する。
安易な公開プロキシによる一時しのぎを避ける
公開 CORS プロキシを使用すると一時的にテストを通過できる場合がありますが、プライバシー侵害、安定性低下、キャッシュ不整合、不正利用リスクなどの問題を引き起こします。本番環境の動画再生においては、ブラウザがリソース所有者から直接正しいポリシーを受け取れるよう、ストリームの配信元オリジンまたは CDN エッジでヘッダーを恒久的に修正してください。
修正結果の検証方法
サーバー側のヘッダーを調整したら、オンラインプレーヤーに戻り、同じストリームを再度テストします。マニフェストが読み込まれ画質オプションが表示されれば、トップレベルのアクセス問題は解決した可能性が高いです。その後さらに再生が止まる場合は、セグメントレベルのデバッグやコーデック互換性の検証へ進みます。
再テスト中は、ブラウザのネットワークパネルを開いたままにしておきます。再生が開始されたかどうかだけでなく、「どのリクエストがブロック状態から成功状態に変わったか」を確認することが有益な手がかりになります。適切な修正が施されていれば、マニフェスト、選択された子プレイリスト、最初の数個のメディアセグメントが、実際の利用者がアクセスするのと同じオリジンから互換性のあるヘッダーを返すようになります。
ブラウザおよび CDN 関連の公式参考文献
- MDN: オリジン間リソース共有 (CORS): 単純リクエスト、プリフライトリクエスト、認証情報、およびレスポンスヘッダーの仕様を解説しています。
- MDN: 原因: CORS ヘッダー 'Access-Control-Allow-Origin' の不足: allow-origin ヘッダーの欠落によるブラウザエラーについて詳述しています。
- Cloudflare CORS キャッシュドキュメント: ヘッダーの伝播と、オリジン変更後もキャッシュに古い CORS ヘッダーが残る理由を説明しています。