みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

MPEG DASHで動画を配信する時のCloudFrontのCORS設定

MPEG DASHを使ってアダプティブストリーミングで動画を配信しようと挑戦したところ,CORSで躓いたのでまとめます.

目標

  • shaka-playerを使ってDASHでアダプティブストリーミングする.

  • 動画を配信するためにAmazon S3を使い,CloudFrontでキャッシュする.

問題点

動画を貼り付けるWebサイトは,動画を配信するCloudFrontとは別のオリジンなので,オリジン間リソース共有 (CORS)に対応する必要があります.

shaka-playerのリスクエスト

以下のshaka-playerのデモで,どのようなリクエストが行われるかを確認します.

https://shaka-player-demo.appspot.com/demo/#asset=https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd;panel=HOME

最初にdash.mpdを読み込みます.内容の一部は以下のようになります.

<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version v2.4.1-c731217-release-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT60S">
  <Period id="0">
...
    <AdaptationSet id="6" contentType="video" maxWidth="720" maxHeight="576" frameRate="12800/512" par="5:4">
      <Representation id="6" bandwidth="492476" codecs="avc1.4d400d" mimeType="video/mp4" sar="1:1" width="300" height="240">
        <BaseURL>video_240p_242k_h264.mp4</BaseURL>
        <SegmentBase indexRange="860-1071" timescale="12800">
          <Initialization range="0-859"/>
        </SegmentBase>
      </Representation>
      <Representation id="7" bandwidth="991296" codecs="avc1.4d4015" mimeType="video/mp4" sar="1:1" width="450" height="360">
        <BaseURL>video_360p_400k_h264.mp4</BaseURL>
        <SegmentBase indexRange="862-1073" timescale="12800">
          <Initialization range="0-861"/>
        </SegmentBase>
      </Representation>
      <Representation id="12" bandwidth="162364" codecs="avc1.4d400c" mimeType="video/mp4" sar="1:1" width="180" height="144">
        <BaseURL>video_144p_108k_h264.mp4</BaseURL>
        <SegmentBase indexRange="860-1071" timescale="12800">
          <Initialization range="0-859"/>
        </SegmentBase>
      </Representation>
...
    </AdaptationSet>
  </Period>
</MPD>

アダプティブストリーミングでは,解像度が異なる複数の動画ファイルを用意し,ネットワーク回線の状態に応じて,shaka-playerがどのファイルを再生するのかを切り替える仕組みです.

Chromeのインスペクタでネットワークを確認します.

f:id:atsuhiro-me:20201002132147p:plain

このように,1つの動画ファイルをそのままダウンロードするのではなく,Rangeヘッダーを使って,動画ファイルを少しずつダウンロードします.

これらの動作により,必要なデータのみをダウンロードすることができるので,動画配信にかかるコストを減らすことができます.

CORSの設定

CORSでは,origin, method, headerの全てが許可されなければいけません.上記の配信において,Rangeヘッダーを許可しなければなりません.Amazon S3のCORS configurationで以下の設定をします.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedHeader>range</AllowedHeader>
</CORSRule>
</CORSConfiguration>

CloudFrontで,rangeヘッダーを含めてCORSに対応できるように設定します.DistributionsのBehavioursの編集画面を開きます.

まず,Allowed HTTP Methods を,GET, HEAD, OPTIONS にします.preflightリクエストのCORSに対応するために,OPTIONSを明示的に許可しなければなりません.

Cache Based on Selected Request Headers を,Whitelistにします.そして,Whitelist Headersに,

  • Access-Control-Request-Headers
  • Access-Control-Request-Method
  • Origin
  • Range

の4個を追加します.これにより,shaka-playerがCloudFrontにリクエストを送信すると,S3にもこれらのヘッダーが送信され,CORSの設定が有効となります.

以上で,CORSが正しく適応されるようになりました.

参考