Safari にて Token ありの AES+HLS ストリームを再生する方法
こんにちは、マルチメディアサポートチームです。
今回は Safari ブラウザ上でトークンを用いて AES で暗号化された HLS ストリームを再生するための Azure Media Services 側の設定手順を紹介します。
Azure Media Services は、Apple HTTP Live Streaming (HLS)、Microsoft Smooth Streaming (Smooth)、MPEG DASH などのストリーミングプロトコルを利用して様々なデバイス上でビデオコンテンツを再生できるサービスです。また AES、PlayReady、Widevine などの暗号化プロトコルを用いたコンテンツ保護機能も有しており、よりセキュアなストリーミングサービスを提供できるメリットがあります。今回のお話は、その中でも AES で暗号化された HLS ストリームを Safari ブラウザ上で再生する方法に特化した内容になります。
Azure Media Services からビデオコンテンツを AES で暗号化しながら配信する場合、デバイス側での動画再生ソフト (今回の場合 Safari ブラウザが対象) では、配信データ (ストリーム) をデコードするためのキーを取得することで再生が可能となります。その際のキーを取得する条件としてトークンの有無が選択でき、トークン無によるキーのリクエストであれば特に問題ありませんが、トークン有によるキーのリクエストの場合は動作再生ソフト側での対応が必要となります。残念ながら Safari の NativePlayer ではトークン通知処理が実装されていないために他の手段を用いる必要があります。
それが以下の英語版ブログで紹介されている Azure Media Services と Safari の間にプロキシサーバーを配置し、Safari の代替としてトークン通知処理を行う方法になります。
How to make Token authorized AES encrypted HLS stream working in Safari
大まかな処理の流れは以下の通りとなります。
実現方法としては、Github のサンプルコード (AESHLSSafari) をベースに Azure Media Services の配信 URL、プロキシサーバーの配信 URL、ならびにトークン情報を追加します。
AES Encrypted HLS stream playback in Safari
https://github.com/AzureMediaServicesSamples/AESHLSSafari
追加前
URI=”QualityLevels(960870)/Manifest(video,format=m3u8-aapl)”
追加後
URI=”<Proxy URL><Azure Media Servicesの 配信 URL (manifest は記載しない : https://~.ism/)>
QualityLevels(960870)/Manifest(video,format=m3u8-aapl)<token 情報>”
以下は各項番の補足説明になります。
Step 2 の Request (Video URL) について
Azure Media Services から配信される URL は以下の通りです。
Step 3 の Top PlayList について
以下はマニフェスト (Top PlayList) の内容です。
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=”audio”,NAME=”AAC_und_ch2_128kbps”,URI=”QualityLevels(125423)/Manifest(AAC_und_ch2_128kbps,format=m3u8-aapl)”
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=”audio”,NAME=”AAC_und_ch2_56kbps”,DEFAULT=YES,URI=”QualityLevels(53634)/Manifest(AAC_und_ch2_56kbps,format=m3u8-aapl)”
#EXT-X-STREAM-INF:BANDWIDTH=542987,RESOLUTION=320×180,CODECS=”avc1.64000d,mp4a.40.2″,AUDIO=”audio”
QualityLevels(389908)/Manifest(video,format=m3u8-aapl)
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=542987,RESOLUTION=320×180,CODECS=”avc1.64000d”,URI=”QualityLevels(389908)/Manifest(video,format=m3u8-aapl,type=keyframes)”
#EXT-X-STREAM-INF:BANDWIDTH=797524,RESOLUTION=640×360,CODECS=”avc1.64001e,mp4a.40.2″,AUDIO=”audio”
QualityLevels(638965)/Manifest(video,format=m3u8-aapl)
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=797524,RESOLUTION=640×360,CODECS=”avc1.64001e”,URI=”QualityLevels(638965)/Manifest(video,format=m3u8-aapl,type=keyframes)”
#EXT-X-STREAM-INF:BANDWIDTH=1145551,RESOLUTION=640×360,CODECS=”avc1.64001e,mp4a.40.2″,AUDIO=”audio”
QualityLevels(979500)/Manifest(video,format=m3u8-aapl)
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=1145551,RESOLUTION=640×360,CODECS=”avc1.64001e”,URI=”QualityLevels(979500)/Manifest(video,format=m3u8-aapl,type=keyframes)”
#EXT-X-STREAM-INF:BANDWIDTH=1649597,RESOLUTION=960×540,CODECS=”avc1.64001f,mp4a.40.2″,AUDIO=”audio”
QualityLevels(1472696)/Manifest(video,format=m3u8-aapl)
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=1649597,RESOLUTION=960×540,CODECS=”avc1.64001f”,URI=”QualityLevels(1472696)/Manifest(video,format=m3u8-aapl,type=keyframes)”
#EXT-X-STREAM-INF:BANDWIDTH=2392319,RESOLUTION=960×540,CODECS=”avc1.64001f,mp4a.40.2″,AUDIO=”audio”
QualityLevels(2199430)/Manifest(video,format=m3u8-aapl)
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=2392319,RESOLUTION=960×540,CODECS=”avc1.64001f”,URI=”QualityLevels(2199430)/Manifest(video,format=m3u8-aapl,type=keyframes)”
#EXT-X-STREAM-INF:BANDWIDTH=3548160,RESOLUTION=1280×720,CODECS=”avc1.64001f,mp4a.40.2″,AUDIO=”audio”
QualityLevels(3330390)/Manifest(video,format=m3u8-aapl)
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=3548160,RESOLUTION=1280×720,CODECS=”avc1.64001f”,URI=”QualityLevels(3330390)/Manifest(video,format=m3u8-aapl,type=keyframes)”
#EXT-X-STREAM-INF:BANDWIDTH=4859041,RESOLUTION=1920×1080,CODECS=”avc1.640028,mp4a.40.2″,AUDIO=”audio”
QualityLevels(4613052)/Manifest(video,format=m3u8-aapl)
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=4859041,RESOLUTION=1920×1080,CODECS=”avc1.640028″,URI=”QualityLevels(4613052)/Manifest(video,format=m3u8-aapl,type=keyframes)”
#EXT-X-STREAM-INF:BANDWIDTH=6134366,RESOLUTION=1920×1080,CODECS=”avc1.640028,mp4a.40.2″,AUDIO=”audio”
QualityLevels(5860924)/Manifest(video,format=m3u8-aapl)
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=6134366,RESOLUTION=1920×1080,CODECS=”avc1.640028″,URI=”QualityLevels(5860924)/Manifest(video,format=m3u8-aapl,type=keyframes)”
#EXT-X-STREAM-INF:BANDWIDTH=62973,CODECS=”mp4a.40.2″,AUDIO=”audio”
QualityLevels(53634)/Manifest(AAC_und_ch2_56kbps,format=m3u8-aapl)
Step 4 の Modified Top PlayList について
以下は修正されたマニフェストの URL です。
以下は修正されたマニフェスト (Top PlayList) の内容です。
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=”audio”,NAME=”AAC_und_ch2_128kbps”,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(125423)/Manifest(AAC_und_ch2_128kbps,format=m3u8-aapl)&token=<省略>“
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=”audio”,NAME=”AAC_und_ch2_56kbps”,DEFAULT=YES,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(53634)/Manifest(AAC_und_ch2_56kbps,format=m3u8-aapl)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=542987,RESOLUTION=320×180,CODECS=”avc1.64000d,mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(389908)/Manifest(video,format=m3u8-aapl)&token=<省略>
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=542987,RESOLUTION=320×180,CODECS=”avc1.64000d”,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(389908)/Manifest(video,format=m3u8-aapl,type=keyframes)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=797524,RESOLUTION=640×360,CODECS=”avc1.64001e,mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(638965)/Manifest(video,format=m3u8-aapl)&token=<省略>
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=797524,RESOLUTION=640×360,CODECS=”avc1.64001e”,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(638965)/Manifest(video,format=m3u8-aapl,type=keyframes)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=1145551,RESOLUTION=640×360,CODECS=”avc1.64001e,mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(979500)/Manifest(video,format=m3u8-aapl)&token=<省略>
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=1145551,RESOLUTION=640×360,CODECS=”avc1.64001e”,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(979500)/Manifest(video,format=m3u8-aapl,type=keyframes)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=1649597,RESOLUTION=960×540,CODECS=”avc1.64001f,mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(1472696)/Manifest(video,format=m3u8-aapl)&token=<省略>
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=1649597,RESOLUTION=960×540,CODECS=”avc1.64001f”,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(1472696)/Manifest(video,format=m3u8-aapl,type=keyframes)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=2392319,RESOLUTION=960×540,CODECS=”avc1.64001f,mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(2199430)/Manifest(video,format=m3u8-aapl)&token=<省略>
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=2392319,RESOLUTION=960×540,CODECS=”avc1.64001f”,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(2199430)/Manifest(video,format=m3u8-aapl,type=keyframes)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=3548160,RESOLUTION=1280×720,CODECS=”avc1.64001f,mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(3330390)/Manifest(video,format=m3u8-aapl)&token=<省略>
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=3548160,RESOLUTION=1280×720,CODECS=”avc1.64001f”,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(3330390)/Manifest(video,format=m3u8-aapl,type=keyframes)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=4859041,RESOLUTION=1920×1080,CODECS=”avc1.640028,mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(4613052)/Manifest(video,format=m3u8-aapl)&token=<省略>
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=4859041,RESOLUTION=1920×1080,CODECS=”avc1.640028″,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(4613052)/Manifest(video,format=m3u8-aapl,type=keyframes)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=6134366,RESOLUTION=1920×1080,CODECS=”avc1.640028,mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(5860924)/Manifest(video,format=m3u8-aapl)&token=<省略>
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=6134366,RESOLUTION=1920×1080,CODECS=”avc1.640028″,URI=”https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(5860924)/Manifest(video,format=m3u8-aapl,type=keyframes)&token=<省略>“
#EXT-X-STREAM-INF:BANDWIDTH=62973,CODECS=”mp4a.40.2″,AUDIO=”audio”
https://benlamhlsproxy.azurewebsites.net/api/ManifestProxy?playbackUrl=http%3a%2f%2famssamples.streaming.mediaservices.windows.net%2f9ead18f1-29f8-453c-8721-4becc00ff611%2fBigBuckBunnyTrailer.ism/QualityLevels(53634)/Manifest(AAC_und_ch2_56kbps,format=m3u8-aapl)&token=<省略>
Github にあるProxy サンプルは Azure WebApp となっており Token の扱いの部分だけを編集すれば確認できますので、ぜひお試しください。