WowzaでHTTPオリジン設定したときのキャッシュの違いを確認してみた

はじめに

清水です。先日以下のエントリでWowza on EC2 + CloudFrontの構成でのHLSライブ配信をやってみました。

設定の際にWowza Streaming Engineではアプリケーションを新規に追加し、その際に"Live HTTP Origin"を選択しました。対してWowzaでデフォルトで作成されているライブ配信用アプリケーションは"Live"で設定されているものになります。この2つのアプリケーションの違いはどのような点があるか、本エントリではHLS形式でアクセスするファイルのアドレスとキャシュの2点から確認してみたのでまとめてみたいと思います。結果としては以下2点がわかりました。

  • Live HTTP Originアプリケーションを選択した場合、大規模配信に適したキャッシュ設定が行われる
  • Liveアプリケーションではキャッシュをさせない設定になっている

なお、本エントリでも先日のエントリに引き続き、配信方式はHLS: HTTP Live Streaming(Cupertino Streaming)を使ったライブ配信を対象としています。

本エントリで使用するWowzaのアプリケーション名称について

本エントリでは次の2つのWowzaアプリケーションを使用しています。1つ目はCloudFrontなどのCDNを使わない場合の配信(今回はWowza 1台での配信を想定)で、アプリケーション追加画面で一番上段の"Live: Single server or origin"を選択して作成したものです *1。Wowzaでの設定時のアプリケーション名はsingle-server-appとしました。本エントリ上ではLiveアプリケーションと記載することとします。2つ目はCloudFrontなどのhttp対応のCDNを使用する場合のアプリケーションです。一番下の"Live HTTP Origin: Origin for non-Wowza edges"を選択して作成します。Wowzaでの設定時のアプリケーション名はhttp-origin-appとしました。本エントリ上ではLive HTTP Originアプリケーションと記載します。

wowza-httporigin-002

HLS形式のライブストリーミングの仕組みを確認

まずは今回対象としていますHLS: HTTP Live Streaming(Cupertino Streaming)での形式での配信について、アクセスするファイルの種類からその仕組みを確認しておきます。ライブストリーミング時には以下の2種類のファイルにアクセスします。

  • プレイリストファイル(拡張子m3u8)
  • セグメントファイル(拡張子ts)

プレイリストファイルには「どのファイルを再生するか」の情報が書かれています。プレイリストファイルの中身が他のプレイリストファイルの列挙、ということもあるのですが、プレイリストを辿っていけば最終的にはセグメントファイルを列挙したものとなります。この列挙されているセグメントファイルは上から下に動画の時間軸順となります。

対してセグメントファイルは動画ファイルそのものですが、1セグメントは数秒から数十秒程度の尺の動画となっています。セグメントファイル自体は動画全体に対して短いのですが、プレイヤー側で1つのセグメントファイルの再生が終わったら、連続してプレイリストに記載されている次のセグメントファイルを取得し再生するので、連続した動画再生となります。(なおセグメントファイルが映像と音声で分離している場合もあります。)

ライブストリーミング時には、プレイリストファイルは動的に変化し、最新のセグメントファイルが順次記載されていきます。また古いセグメントファイルの記載は消えています。プレイヤー側ではプレイリストファイルに記載されている最新のセグメントファイルを取得、再生して、そのセグメントの再生が終わるタイミングまでに再度プレイリストファイルを取得、最新のセグメントファイルを確認してこちらを取得、再生する、という動作イメージになります。

アプリケーションごとのアクセスするファイル名の違い

それではエンコーダから映像を流してHLSライブ配信を行いながら、Liveアプリケーション、Live HTTP Originアプリケーションのそれぞれで動画再生時にアクセスするファイルを確認してみます。

Liveアプリケーションの場合

まずはCloudFrontなどのCDNを使わない場合のLiveアプリケーション(single-server-app)について確認してみます。ライブ配信を視聴できるプレイリストへのURLは以下になります。

  • http://[Wowza on EC2のIP]/single-server-app/myStream/playlist.m3u8

まずはこのplaylist.m3u8ファイルにアクセスしてみます。

 $ curl http://[Wowza on EC2 PublicIP]/single-server-app/myStream/playlist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=2312588,CODECS="avc1.77.31,mp4a.40.2",RESOLUTION=1280x720
chunklist_w1029366019.m3u8

chunklistというプレイリストファイルが記載されていました。プレイリストファイルはこのように多段構成になっている場合もあります。例えばABR(Adaptive bitrate streaming)対応の場合はここで複数ビットレートのプレイリストが記載されることになります。

またこのchunklistのファイル名称ですが、アクセスするたびに変化があります。

 $ curl http://[Wowza on EC2 PublicIP]/single-server-app/myStream/playlist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=2312588,CODECS="avc1.77.31,mp4a.40.2",RESOLUTION=1280x720
chunklist_w861097887.m3u8
 $ curl http://[Wowza on EC2 PublicIP]/single-server-app/myStream/playlist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=2312588,CODECS="avc1.77.31,mp4a.40.2",RESOLUTION=1280x720
chunklist_w1055383413.m3u8
 $ curl http://[Wowza on EC2 PublicIP]/single-server-app/myStream/playlist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=2247164,CODECS="avc1.77.31,mp4a.40.2",RESOLUTION=1280x720
chunklist_w1215545129.m3u8

chunklistに続く、wから始まる10桁の数値がアクセスのたびに変化しています。この値ですがセッションIDのように扱われていて、例えば接続数のカウントなどに使用されているようです。

続いてchunklistのプレイリストファイルの中身を確認してみます。

 $ curl http://[Wowza on EC2 PublicIP]/single-server-app/myStream/chunklist_w1215545129.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:18
#EXT-X-MEDIA-SEQUENCE:13
#EXTINF:17.3,
media_w1215545129_13.ts
#EXTINF:8.0,
media_w1215545129_14.ts
#EXTINF:6.834,
media_w1215545129_15.ts

このchunklistのプレイリストファイルでセグメントファイルが列挙されていますね。セグメントファイルは見たまま、末尾の値が小さいものが古く、大きいものが新しいファイルとなります。(ここではmedia_w1215545129_15.tsが最新のセグメントファイルです。) 最新のセグメントファイルの長さは6.8秒ほどなので、6、7秒したら再度chunklistプレイリストファイルを取得してみます。

 $ curl http://[Wowza on EC2 PublicIP]/single-server-app/myStream/chunklist_w1215545129.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:18
#EXT-X-MEDIA-SEQUENCE:14
#EXTINF:8.0,
media_w1215545129_14.ts
#EXTINF:6.834,
media_w1215545129_15.ts
#EXTINF:12.2,
media_w1215545129_16.ts

最後の行、セグメントファイルの番号がインクリメントされていますね。プレイヤーではこの最後の(=最新の)ファイルを常に読み続けることでライブ配信を実現しています。またEXT-X-MEDIA-SEQUENCEの値も変わっています。また各セグメントファイル名に先ほどのchunkilstプレイリストファイルと同じwで始まる10桁の数値が含まれていることがわかります。

Live HTTP Originアプリケーションの場合

続いてCloudFrontなどのhttp対応のCDNを使用する場合のLive HTTP Originアプリケーション(http-origin-app)について確認してみます。ライブ配信を確認できるプレイリストへのURLは下記で、今回はCloudFrontなどを経由せずオリジンとなるWowzaへ直接アクセスして確認してみました。

  • http://[Wowza on EC2のIP]/http-origin-app/myStream/playlist.m3u8

このplaylist.m3u8ファイルにアクセスしてみます。

 $ curl http://[Wowza on EC2 PublicIP]/http-origin-app/myStream/playlist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=2391916,CODECS="avc1.77.31,mp4a.40.2",RESOLUTION=1280x720
chunklist.m3u8

多段構成のプレイリストとなっていました。Liveアプリケーション(single-server-app)の場合とは異なり、chunklistの後にwから始まる10桁の数値はありませんね。またアクセスするたびに変わるということもありませんでした。

続いてこのchunklisltプレイリストファイルの中身を確認してみます。

 $ curl http://[Wowza on EC2 PublicIP]/http-origin-app/myStream/chunklist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:16
#EXT-X-MEDIA-SEQUENCE:54
#EXTINF:8.0,
media-u2hr70b5o_54.ts
#EXTINF:8.0,
media-u2hr70b5o_55.ts
#EXTINF:6.833,
media-u2hr70b5o_56.ts

こちらもchunklistのプレイリストファイル内にセグメントファイルが列挙されていました。最新のセグメントファイルの長さが6.8秒ですので、少しして再度chunklistプレイリストファイルを取得してみます。

 $ curl http://[Wowza on EC2 PublicIP]/http-origin-app/myStream/chunklist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:16
#EXT-X-MEDIA-SEQUENCE:55
#EXTINF:8.0,
media-u2hr70b5o_55.ts
#EXTINF:6.833,
media-u2hr70b5o_56.ts
#EXTINF:12.2,
media-u2hr70b5o_57.ts

セグメントファイルが更新されていました。この挙動についてはLiveアプリケーションの場合と同様ですね。ただセグメントファイルの命名規則、mediaの後に続く文字列がLiveアプリケーションの場合と少し異なります。

  • Liveアプリケーション
    • media_w[10桁の数値]_[セグメントの番号].ts
  • Live HTTP Originアプリケーション
    • media-[9文字の英数字]_[セグメント番号].ts

Live HTTP Originアプリケーションの場合はこの9文字の英数字について、エンコーダ側のエンコード処理を一度停止ののち、再度開始することで値が変わることが確認できました。

 $ curl http://[Wowza on EC2 PublicIP]/http-origin-app/myStream/playlist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=2442397,CODECS="avc1.77.31,mp4a.40.2",RESOLUTION=1280x720
chunklist.m3u8

 $ curl http://[Wowza on EC2 PublicIP]/http-origin-app/myStream/chunklist.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:16
#EXT-X-MEDIA-SEQUENCE:8
#EXTINF:16.0,
media-u6vos6rjd_8.ts
#EXTINF:5.233,
media-u6vos6rjd_9.ts
#EXTINF:13.834,
media-u6vos6rjd_10.ts

おそらくエンコード処理を開始するたびにセッションIDのような一意の値が割り振られていると考えられます。

ファイル名の違いについてのまとめ

LiveアプリケーションとLive HTTP Originoアプリケーションでアクセスするファイル名について確認してみました。それぞれの違いをまとめてみます。

  • Liveアプリケーション
    • playlist.m3u8 → chunklistプレイリストファイル → セグメントファイル の3階層
    • chunklistプレイリストファイルはアクセスのたびにIDが変わる
    • セグメントファイルのファイル名もそのchunklistのIDが含まれたものとなる
  • Live HTTP Originアプリケーション
    • playlist.m3u8 → chunklistプレイリストファイル → セグメントファイル の3階層
    • chunklistプレイリストファイルの名称はchunklist.m3u8で固定
    • セグメントファイルのファイル名はIDが振られている
    • エンコーダ側のエンコード処理を開始するたびにIDが変わる

アプリケーションごとのキャッシュ設定の違い

アプリケーションによってアクセスするプレイリスト、メディアファイルにIDが含まれるか、アクセスごとにIDが変化するか、といった違いがありました。続いてはアクセスしているこれらのファイルのキャッシュ設定(Cache-Controlヘッダ)を確認してみます。

Liveアプリケーションの場合

playlist.m3u8とchunklistプレイリストファイル、セグメントファイルのそれぞれについてヘッダ情報からCache-Controlを確認してみます。結果としてはいずれもno-cacheが設定されていました。

playlist.m3u8

 $ curl -I http://[Wowza on EC2 PublicIP]/single-server-app/myStream/playlist.m3u8
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Expose-Headers: Date, Server, Content-Type, Content-Length
Server: WowzaStreamingEngine/4.6.0
Cache-Control: no-cache
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS, GET, POST, HEAD
Access-Control-Allow-Headers: Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Date: Mon, 19 Jun 2017 11:45:23 GMT
Content-Type: application/vnd.apple.mpegurl
Content-Length: 136

chunklistプレイリストファイル

 $ curl -I http://[Wowza on EC2 PublicIP]/single-server-app/myStream/chunklist_w1215545129.m3u8
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Expose-Headers: Date, Server, Content-Type, Content-Length
Server: WowzaStreamingEngine/4.6.0
Cache-Control: no-cache
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS, GET, POST, HEAD
Access-Control-Allow-Headers: Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Date: Mon, 19 Jun 2017 11:45:30 GMT
Content-Type: application/vnd.apple.mpegurl
Content-Length: 187

セグメントファイル

 $ curl -I http://[Wowza on EC2 PublicIP]/single-server-app/myStream/media_w1215545129_16.ts
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Expose-Headers: Date, Server, Content-Type, Content-Length
Server: WowzaStreamingEngine/4.6.0
Cache-Control: no-cache
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS, GET, POST, HEAD
Access-Control-Allow-Headers: Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Date: Mon, 19 Jun 2017 11:45:43 GMT
Content-Type: video/MP2T
Content-Length: 3503004

Live HTTP Originアプリケーションの場合

こちらもplaylist.m3u8、chunklistプレイリストファイル、セグメントファイルのそれぞれについてヘッダ情報からCache-Controlを確認してみました。こちらはプレイリストファイルについてはmax-age=1が設定され、セグメントファイルについてはmax-age=3600が設定されていました。

playlist.m3u8

 $ curl -I http://[Wowza on EC2 PublicIP]/http-origin-app/myStream/playlist.m3u8
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Expose-Headers: Date, Server, Content-Type, Content-Length
Server: WowzaStreamingEngine/4.6.0
Cache-Control: max-age=1
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS, GET, POST, HEAD
Access-Control-Allow-Headers: Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Date: Mon, 19 Jun 2017 10:49:29 GMT
Content-Type: application/vnd.apple.mpegurl
Content-Length: 126

chunklistプレイリストファイル

 $ curl -I http://[Wowza on EC2 PublicIP]/http-origin-app/myStream/chunklist.m3u8
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Expose-Headers: Date, Server, Content-Type, Content-Length
Server: WowzaStreamingEngine/4.6.0
Cache-Control: max-age=1
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS, GET, POST, HEAD
Access-Control-Allow-Headers: Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Date: Mon, 19 Jun 2017 10:49:31 GMT
Content-Type: application/vnd.apple.mpegurl
Content-Length: 183

セグメントファイル

 $ curl -I http://[Wowza on EC2 PublicIP]/http-origin-app/myStream/media-u2hr70b5o_59.ts
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Expose-Headers: Date, Server, Content-Type, Content-Length
Server: WowzaStreamingEngine/4.6.0
Cache-Control: max-age=3600
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS, GET, POST, HEAD
Access-Control-Allow-Headers: Content-Type, User-Agent, If-Modified-Since, Cache-Control, Range
Date: Mon, 19 Jun 2017 10:49:41 GMT
Content-Type: video/MP2T
Content-Length: 3409004

キャッシュ設定の違いについてのまとめと考察

LiveアプリケーションとLive HTTP OriginアプリケーションのCache-Controlヘッダは以下となっていました。

  • Liveアプリケーション
    • プレイリストファイル、セグメントファイルともno-cache
  • Live HTTP Originアプリケーション
    • プレイリストファイルはmax-age=1
    • セグメントファイルはmax-age=3600

ライブ配信時にアクセスされるプレイリストファイル、セグメントファイルの2種について、CDNを使って負荷分散を行う場合には以下のようにキャッシュされることが望ましいと考えられます。

まずプレイリストファイルについてはライブ配信時、時間の経過とともに必ず更新されますので、長期間キャッシュされては困ります。プレイヤーでセグメントファイルの再生が終わり次にプレイリストを取得したとき、プレイリストが更新されていないという自体は避けなければなりません。またセグメント間隔にあわせた値でもリアルタイム性が損なわれる(クライアントがリクエストするタイミングによっては遅延が大きくなる)ことが考えられます。そのため例えば1秒程度の、割りと短めの時間だけどキャッシュさせることでオリジンの負荷が軽減できる値が望ましいと言えます。

対してセグメントファイルはなるべく長くキャッシュさせる、という方針となります。動画(映像、音声)の本体はこちらのセグメントファイルになるので、キャッシュさせオリジンへのリクエスト数を減らすことで、オリジンのネットワーク帯域負荷を減らすことができます。またセグメントファイルについては一度生成されれば変わることはありません。

以上を踏まえて、CloudFrontのようなCDN(HTTPキャッシュを使うもの)を使用する場合にはLive HTTP Originアプリケーションで設定されるCache-Controlの値はベストなものとなっていますね。先日のエントリでWowza on EC2 + CloudFrontの構成でのHLSライブ配信を行ってみた際、CloudFront側のキャッシュ設定についてはデフォルトのUse Origin Cache Headersのままでした。オリジン側のキャッシュ設定が適切に行われていますのでCloudFront側でキャッシュ設定を別途行わなくても大規模な配信にも耐えれる構成になっています。対してLiveアプリケーションの場合は接続数のカウントなどの目的のためIDが振られますが、このIDを維持するためあえてキャッシュをさせないようCache-Controlヘッダで指定しているのではないかと考えられます。

まとめ

Wowza Streaming EngineでCloudFrontなどのCDNを使用する場合に選択するLive HTTP Originアプリケーションについて、Liveアプリケーションとの違いをHLS配信時におけるアクセスするファイル名とキャッシュ設定の観点から確認してみました。結果、Live HTTP Originを設定したアプリケーションではCloudFrontのようなCDNと連携した場合に別途キャッシュ設定を行わなくても済むよう、適切なCache-Controlヘッダが設定されていることがわかりました。またLiveアプリケーションについてはアクセスするたびにセッションを管理するようなIDが振られていること、またそのIDの維持のために適切なCache-Controlヘッダが設定されていることがわかりました。

実はWowza on EC2 + CloudFrontの構成を試した時、はじめのうちはLive HTTP Originアプリケーション設定に気が付かずLiveアプリ ケーションでの設定で行っていました。しかし設定部分ではまってしまい、アクセスするファイルとそのキャッシュ設定を確認したところ今回のことがわかった次第です。CloudFrontなどCDNサービスを利用する場合は各ファイルのキャッシュ設定(Cache-Controlヘッダ)をしっかり確認することが重要ですね。

脚注

  1. WowzaでOrigin/Edge構成を構築する場合にも、オリジンはLiveを選択します。