hls.jsの通信をhookして復号鍵をAPI経由でリクエストする
こんにちは、kz_moritaです。\
HLS動画を暗号化する際に、外部のDRMサービスを使用せずに動画の閲覧権限管理を行いたかったので、動画の復号鍵をAPI経由で取得できるようなシステムについて考えてみました。
全体のアーキテクチャ 今回はHLSのプレイリストファイルのURLがバレても、サービスが提供する動画プレイヤー以外では動画を再生できないといったものを想定しています。 APIで認証情報をチェックできるという前提のもと、以下のような構成を考えています。
動画再生までの手順としては以下のような感じです。
APIから動画情報を取得してくる 動画情報に含まれるHLSのプレイリストファイル(.m3u8) へのパスを指定して動画プレイヤーで再生開始 動画プレイヤーをhookして、鍵リクエストだったらAPIサーバーに鍵を取りに行く 鍵リクエスト以外であれば、通常通りHLSファイルが配置されている場所にリクエストを投げて再生する 鍵リクエストかどうかの判定 鍵リクエストかどうかを判定するために、鍵のURLをdummyのURL Scheme を持ったものにします。上記の例では、 video://decryptkey がそれにあたります。このURLであったら、リクエストをAPIへのものに差し替えて通信することで認証付きで復号鍵を取得しようという作戦です。
暗号化されたHLS動画の復号鍵の指定は、メディアプレイリストの #X-EXT-KEY タグで指定します。
具体的には以下のようなプレイリスト生成します。
#EXT-X-KEY:METHOD=AES-128,URI="video://decryptkey",IV=0x000000000000000000000000000000 Hls.js で通信をhookする処理 Hls.jsを用いる時は以下のようにHls.jsを初期化します。
// Videoタグを取得 (id="video" を想定) var videoTag = document.getElementById('video') var config = { /* ... */} var hls = new Hls(config) hls.loadSource("https://example.com/video.m3u8") hls.attachMedia(videoTag) 通信をhookする際には、loaderをconfigで渡すとロード処理をカスタマイズすることができます。
https://github.com/video-dev/hls.js/blob/master/docs/API.md#loader
デフォルトのローダーは以下のものが使われているので、このLoaderの loadInternal メソッドを overrideすることで通信の挙動をカスタマイズできます。
https://github.com/video-dev/hls.js/blob/master/src/utils/xhr-loader.js
それでは実際に通信をhookしてAPIを叩くようなコードを書いてみます。
// Customize した loadInternalメソッド var customLoadInternal = function() { let xhr, context = this.