AWS Media Servicesを使ってタイムシフト再生機能付きライブ配信をしてみた!

AWS Media Servicesを使ってタイムシフト再生可能なライブ配信を行ってみました。MediaPackageのStartover Windowを指定し プレイリストリクエスト方法を変更、さらに再生プレイヤー側の対応を行いました。
2018.07.29

はじめに

清水です。AWS Media Servicesを使うとAWSのフルマネージドサービスのみでライブ配信環境を構築できます。今回は単純なライブ配信に加えてタイムシフト再生ができるように設定してみたのでまとめてみたいと思います。

タイムシフト再生とは

ライブ映像を見ながらユーザ側で任意に巻き戻して途中からの再生や、ライブの開始地点から最新のライブ地点までなら任意の場所を再生できる機能です。HDDレコーダーなどでも同様のことができますね。「追っかけ再生」とか、「DVR(Digital Video Recorder)」などとも言われます。

AWS Media Servicesを使ってタイムシフト再生付きのライブ配信を行うポイント

AWS Media Servicesを使ったライブ配信の方法については、例えば以下のエントリで紹介しています。

タイムシフト再生付きのライブ配信を行うため、MediaStoreではなくMediaPackageを使用しましました。後述しますがMediaPackageのStartover windowsという箇所を設定して、タイムシフト再生ができるようにします。あわせてMediaPackageへプレイリストをリクエストする際、パラメータを付与することでタイムシフト再生用の情報を含んだ状態のプレイリストが得られます。

これに加えて、再生プレイヤー側でもひと手間必要です。今回はMediaPackageからの出力はHLS形式とし、以下のエントリと同様にVideo.jsのvideojs-contrib-hlsを使って再生プレイヤーを用意しましたが、これだけではシークバーがなく(LIVEを選択することしかできない)タイムシフト再生ができません。今回はここに「videojs-dvrseekbar」というVideo.jsのプラグインを使うことでタイムシフト再生(DVR)対応の再生プレイヤーとしました。こちらも詳細は後述します。

タイムシフト再生のためのAWS Elemental MediaPackageの設定

まずはタイムシフト再生を行うにあたりAWS Media Servicesの設定を行っていきます。はじめはAWS Elemental MediaPackageです。マネージメントコンソールからChannelを作成します。Endpointを使いする際、Startover windowを有効にします。またどのぐらいの時間タイムシフトを有効にするかを秒数で指定します。今回は10800秒=3時間としてみました。その他の項目は任意です。今回はMediaPackageの出力をHLS形式としています。

タイムシフト再生のためのAWS Elemental MediaLiveの設定

続いてAWS Elemental MediaLiveの設定を行います。出力形式としてHLSを指定して、MediaPackageに出力します。具体的な手順はタイムシフトを行わない場合と同様です。個人的には最近MediaStoreでの配信ばかりしていたので、CDN SettingsをHls webdavにすることに注意しました。(Fields for the HLS Group - AWS Elemental MediaLive

タイムシフト再生用のプレイリストを取得する

AWS Media Services側の設定ができたので、実際にライブ配信を開始してみます。Media LiveのChannelをStartし、配信エンコーダ(今回はOBS Studioを使用)から映像を送信します。

映像配信後、マネージメントコンソールから確認できるMediaPackageのEndponit URL(https://[16桁の英数字].mediapackage.ap-northeast-1.amazonaws.com/out/v1/[32桁の英数字]/index.m3u8)のものを確認してみますが、通常のライブ配信と同様のプレイリストしか得られません。例えば下記のような具合ですね。プレイリストには10個のtsファイルしか含まれていない状態で、いくらライブを続けても10個のまま(=通常のライブ配信のプレイリスト)です。

$ curl https://[16桁の英数字].mediapackage.ap-northeast-1.amazonaws.com/out/v1/[32桁の英数字]/index.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=5059831,RESOLUTION=1280x720,CODECS="avc1.64001F,mp4a.40.2"
index_1.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1759831,RESOLUTION=640x360,CODECS="avc1.4D401E,mp4a.40.2"
index_2.m3u8


$ curl 'https://[16桁の英数字].mediapackage.ap-northeast-1.amazonaws.com/out/v1/[32桁の英数字]/index_1.m3u8'
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:1331
#EXTINF:6.006,
index_1_1331.ts?m=1532678712
#EXTINF:6.006,
index_1_1332.ts?m=1532678712
#EXTINF:6.006,
index_1_1333.ts?m=1532678712
#EXTINF:6.006,
index_1_1334.ts?m=1532678712
#EXTINF:6.006,
index_1_1335.ts?m=1532678712
#EXTINF:6.006,
index_1_1336.ts?m=1532678712
#EXTINF:6.006,
index_1_1337.ts?m=1532678712
#EXTINF:6.006,
index_1_1338.ts?m=1532678712
#EXTINF:6.006,
index_1_1339.ts?m=1532678712
#EXTINF:6.006,
index_1_1340.ts?m=1532678712

MediaPackageでタイムシフト再生分を含んだプレイリストを取得するには、別途リクエスト時にパラメータを指定する必要があります。ドキュメントには以下のようにまとまっています。

今回はHLS Endpointを使用しているので「HLSパラメータのルール」の項目を参考に、以下のようにクエリパラメータ表記でパラメータを付与しました。([ISO 8601の日付形式]=YYYY-MM-DDTHH:MM:SS+HH:MM)

  • https://[16桁の英数字].mediapackage.ap-northeast-1.amazonaws.com/out/v1/[32桁の英数字]/index.m3u8?start=[ISO 8601の日付形式]&end=[ISO 8601の日付形式]

具体的には以下になります。

  • https://[16桁の英数字].mediapackage.ap-northeast-1.amazonaws.com/out/v1/[32桁の英数字]//index.m3u8?start=2018-07-27T19:20:00+09:00&end=2018-07-27T22:00:00+09:00

このパラメータを付けてMediaPackageにリクエストすると、タイムシフト再生に対応したプレイリストが返ります。具体的には、ライブ配信のみの場合は10個のtsしか含まれていなかったものが時間に応じた分のtsファイル情報が含まれます。状況によりますがけっこう膨大な量のtsファイル情報となります。(例えば1000個のtsファイル情報=全体のファイル行数としては2000行以上、、など)

全部掲載すると膨大になりますので、headとtailで抜粋したものが下記のようになります。

$ curl -s 'https://[16桁の英数字].mediapackage.ap-northeast-1.amazonaws.com/out/v1/[32桁の英数字]/index.m3u8?start=2018-07-27T19:20:00+09:00&end=2018-07-27T22:00:00+09:00'
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=5059831,RESOLUTION=1280x720,CODECS="avc1.64001F,mp4a.40.2"
index_1.m3u8?start=2018-07-27T19:20:00+09:00&end=2018-07-27T22:00:00+09:00
#EXT-X-STREAM-INF:BANDWIDTH=1759831,RESOLUTION=640x360,CODECS="avc1.4D401E,mp4a.40.2"
index_2.m3u8?start=2018-07-27T19:20:00+09:00&end=2018-07-27T22:00:00+09:00

$ curl -s 'https://[16桁の英数字].mediapackage.ap-northeast-1.amazonaws.com/out/v1/[32桁の英数字]/index_1.m3u8?start=2018-07-27T19:20:00+09:00&end=2018-07-27T22:00:00+09:00' | head -n 20
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:7
#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-MEDIA-SEQUENCE:538
#EXTINF:6.006,
index_1_538.ts?m=1532678712
#EXTINF:6.006,
index_1_539.ts?m=1532678712
#EXTINF:6.006,
index_1_540.ts?m=1532678712
#EXTINF:6.006,
index_1_541.ts?m=1532678712
#EXTINF:6.006,
index_1_542.ts?m=1532678712
#EXTINF:6.006,
index_1_543.ts?m=1532678712
#EXTINF:6.006,
index_1_544.ts?m=1532678712
#EXTINF:6.006,

$ curl -s 'https://[16桁の英数字].mediapackage.ap-northeast-1.amazonaws.com/out/v1/[32桁の英数字]/index_1.m3u8?start=2018-07-27T19:20:00+09:00&end=2018-07-27T22:00:00+09:00' | tail -n 20
#EXTINF:6.006,
index_1_1098.ts?m=1532678712
#EXTINF:6.006,
index_1_1099.ts?m=1532678712
#EXTINF:6.006,
index_1_1100.ts?m=1532678712
#EXTINF:6.006,
index_1_1101.ts?m=1532678712
#EXTINF:6.006,
index_1_1102.ts?m=1532678712
#EXTINF:6.006,
index_1_1103.ts?m=1532678712
#EXTINF:6.006,
index_1_1104.ts?m=1532678712
#EXTINF:6.006,
index_1_1105.ts?m=1532678712
#EXTINF:6.006,
index_1_1106.ts?m=1532678712
#EXTINF:6.006,
index_1_1107.ts?m=1532678712

タイムシフト再生用にAmazon CloudFrontを設定する

MediaPackageへのリクエストの際にタイムシフト用のパラメータをつけることで、タイムシフトに対応したプレイリストを取得することができました。さて実際にライブ配信を行う場合にはCDNを介してエンドユーザに配信することとなると思います。MediaPackageとCloudFrontの連携については下記のエントリのようになります。

ただし、タイムシフト用にMediaPackageにクエリパラメータ表記でリクエストを行う際には注意が必要です。CluodFrontはデフォルトではクエリ文字列を無視してキャッシュを行います。(Query String Forwarding and CachingがNone (Improves Caching)。クエリ文字列パラメータに基づくコンテンツのキャッシュ - Amazon CloudFront)そのためデフォルトではクエリ文字列をオリジンに転送せず、タイムシフト用のプレイリストが取得できません。(MediaPackageに直接リクエストを投げるとタイムシフト用プレイリストが返るが、CloudFrontを経由するとライブ配信のみのプレイリストになってしまう… という具合ですね。)

以下の用にクエリ文字列をすべてオリジンに転送する、もしくは特定のクエリ文字列をオリジンに転送するよう、CloudFrontディストリビューションを設定します。

タイムシフト再生用にvideojs-dvrseekbarをVideo.jsプレイヤーに設定する

ここまでの設定で、リクエストに対してタイムシフト再生の情報が含まれたプレイリストファイルが返るようになりました。ただこれをVideo.js(videojs-contrib-hls)のsrc、m3u8ファイルの指定部分に記載してブラウザから開いてみても、シークバーで再生時間を変更できそうにありません。Video.js側でタイムシフト再生(DVR)に対応し、シークバーで操作できるよう設定する必要があります。今回はVideo.jsのプラグインの一つである「videojs-dvrseekbar」を利用してこれを実現しました。

videojs-contrib-hlsのプラグイン使用設定をベースに、ライブラリの読み込みとplayer変数の指定部分で一部、videojs-dvrseekbarを使用するよう設定する必要があります。具体的には以下のようになります。

<body>
  ...
  <script src="https://vjs.zencdn.net/6.6.3/video.js"></script>
  <script src="./videojs-contrib-hls.js"></script>
  <script src="./videojs-dvrseekbar.js"></script>
  <script>
    var player = videojs('example-video');
    // player.play();
    player.dvrseekbar();
  </script>
</body>

5行目でvideojs-dvrseekbar.jsを読み込んでいます。これは下記ページからダウンロードしました。

また8,9行目で、palyer.play()ではなくplayer.dvrseekbar()と呼び出す関数を変えています。

以上を設定することで、以下のようにタイムシフト再生用のシークバーがついた再生プレイヤーとなります。これでシークして好きなところを視聴できますね!

まとめ

AWS Media Servicesを使ってタイムシフト再生可能なライブ配信を行ってみました。設定のポイントとしては、(1) MediaPackageのStartover Windowの指定、(2) プレイリストリクエスト方法(含むクエリ文字列の処理)、(3) 再生プレイヤー側の対応、の3点かと思いますが、これらをきちんと設定すれば容易にタイムシフト再生ができます。フルマネージドなAWS Media Servicesを使うことでストレージの管理が不要であることも嬉しいですね!引き続きAWS Media Servicesでいろいろと検証を進めてみたいと思います。