hls.jsのCORS問題を解決する

ストリーミングサイトから動画マニフェストを抽出できるプログラムを開発しています。

こいつで抽出した動画マニフェストを、これまた自作の簡易プレイヤーで再生しているのですが、CORSの制限により読み込めないことが増えてきました。そろそろこの問題をどうにかしたい。

本題に入る前に、読み込みに失敗している原因は本当にCORSなのでしょうか。ここの確認から始めます。開発者ツールのネットワークタブから該当のURLを見つけ、適切なOriginを設定してから再送信してみて、成功するかをテストします。Originは禁止ヘッダーなので、本来はクライアントサイドから変更することはできませんが、開発者ツールからなら可能です。

さらっと書きましたが、そう、Originを変更することはできないのです。hls.jsにはリクエストヘッダーをカスタマイズできるメソッド(xhrSetup、fetchSetup)も用意されていますが、Originを含め禁止ヘッダーについては変更不可。

さて、自作の簡易プレイヤーとは、hls.jsを読み込んだだけのシンプルなHTMLファイルです。こいつをブックマークして使っていました。ソースコードはだいたい↓のような感じ。

<html>
  <head>
    <title>HLS Player</title>
    <script src="hls.min.js"></script>
    <style></style>
  </head>
  <body>
    <video></video>
  </body>
</html>

くどいですがOriginをどうにもできない以上、このまま運用するのは無理そうです。CORSの制限を受けない運用手段を用いなくてはいけません。ですが、わざわざ環境を構築したりだとか、新たにコードを書いたり書き直したりとかは面倒くさい。簡単に作り、気軽に使いたい。

そんな都合のいい方法が?……あるんですよね。拡張機能です。

拡張機能はCORSの制限を受けません。ただ通信そのものが厳格に制限されているため、権限がないとどこにもアクセスできません。逆説的には権限さえ与えればいいということになりますね。

ちなみに、ユーザースクリプトでもCORSの制限を受けないHTTPリクエスト(GM_xmlhttpRequest)が利用できます。ユーザースクリプトとは、ページにコードを挿入して機能させる仕組みですが、今回は用途が違う感じがしたので見送りました。

拡張機能と聞くと、学習負荷がかかるイメージを持つかも知れませんが、ローカルのHTMLファイルを開くぐらいなら簡単にできます。

まずHTMLファイルは基本そのままでOK。ただしインラインスクリプトを含んでいるなら、JavaScriptファイルに移植してから外部ファイルとして読み込みます。またCDNのリソースを使っているような場合も同じで、ローカルに保存してから外部ファイルとして読み込みます。

<html>
  <head>
    <title>HLS Player</title>
    <script src="hls.min.js"></script>
    <script src="script.js"></script>
    <style></style>
  </head>
  <body>
    <video></video>
  </body>
</html>

次はHTMLファイルを開く仕組みを作ります。拡張機能ボタンを押したら開くようにするのが簡単でしょう。なぜならこのボタンは作る必要がないですから。

拡張機能ボタンのクリックをトリガするイベントリスナであるonClicked、タブを開くメソッドのcreate()を使います。コードは↓。background.jsとして保存します。HTMLファイルはplayer.htmlとしています。

chrome.action.onClicked.addListener(()=>{
  chrome.tabs.create({
    url: 'player.html'
  });
});

最後にmanifest.jsonを作成します。

{
  "manifest_version": 3,
  "name": "HLS Player",
  "version": "0.1",
  "description": "HLS動画を手軽に再生するためのプレイヤーです。",
  "author": "Sasabee",
  "action": {
    "default_title": "プレイヤーを開く"
  },
  "background": {
    "service_worker": "background.js",
    "scripts": [
      "background.js"
    ]
  },
  "host_permissions": [
    "<all_urls>"
  ]
}

通信権限はhost_permissionsの項目です。アクセスするURLが限定されているのなら、マッチパターンで絞り込むことも可能です。"<all_urls>"は全てのURLへのアクセス権限を与えます。

scriptsの項はChromium系には必要ありませんが、Firefoxではこれがないと読み込めません。

あとはブラウザに読み込ませるだけ。Firefoxならabout:debugging#/runtime/this-firefoxから。ChromeとEdgeは拡張機能ページのデベロッパーモードを有効にすると、作った拡張機能をインストールできます。

……なのですが、ひとつ注意点。Firefoxではローカルの拡張機能を恒久的に使用することができないため、Firefoxでの実用はむずかしいです。Edgeも使用し続けることはできるのですが、起動するたびに警告してきます。Chromeはストアの拡張機能と同じように使えます。

お知らせ

現在お知らせはありません。

最近の投稿

シェア