CloudFront + S3 + HLS形式ストリーミングの動画サイトがカクカク再生されてしまう

構成

サーバー:CloudFront + S3構成
動画構成:mp4をHLS形式(M3U8ファイル + 複数のTSファイル)
クライアント:video.js

事象

動画を再生するとカクカク再生される

原因・理由・対策

原因1

video.jsがいけてなさそう

(理由)
video.jsの動作をChromeのdeveloper toolで眺めていたところ、どうもプリフェッチタイミングと切り替えに関する作り込みがいけてなさそうな気がした。
具体的には、プリフェッチのタイミングがTSファイルが次のに切り替わるぎりぎりな位から行い出すので、もう少し早めに動いてくれてもよさそうな気が。
(オプションパラメータで指定できるのかもしれないけど、後述するhls.jsにしたら問題解決したのでそこまで追ってない)
また、致命的なのが、切り替えタイミングの処理が何故かもたつく場合が多く、動画は既にローカルにダウンロードしているのに、何故か切り替わりに時間がかかっている。
ディスクキャッシュから再生している場合でもその事象が時たまに発生するため、ネットワーク側ではなくvideo.jsの問題と結論づけた。

(対策)
hls.jsに切り替えた。
結果、他の原因分析行わなくてもいいのではないかと思う位スムーズに再生される様になった。
Chrome developer toolで眺めていると、遅からず早からずな良きなタイミングで次の動画のプリフェッチ処理を行っていた。

原因2

TSファイルの分割単位が細かすぎる

(理由)
自分がTSファイルを作成する際に、利用しているソフトのデフォルト値(5秒)のままにしていた。
そのため、頻繁にダウンロード処理が入る & 切替処理が発生するため、カクカクする原因を生み出していた。

(対策)
5秒→15秒に変更した。
分割単位が小さいメリットとして、その動画が再生されない場合のトラフィック量を下げれるのと、もし早送りされた場合にその動画始まりまでの待ち時間を短くできるので、今の画質で3MB位に収まるサイズが15秒だったので15秒とした。
(はじめは30秒にしようとしたが、TSファイルサイズが5MB超えるとさすがに大きすぎると思ったので)

原因3

CloudFrontのヒット率が1%である

(理由)
何か自分が設定不備っているのであろうが、正直意味の分からない動きばかりする(※1)のと、原因1の対策打つ事でほぼ改善したので、こちらは一旦白旗振る事にした。

※1
基本的にはキャッシュミス(x-cache:Miss from cloudfront)が発生する。
なのに、たまにキャッシュヒットする場合もあれば、1時間すら経っていない & エッジポイント(NTR51-C1)変わってないのにすぐキャッシュアウトされてしまう。

(対策)
以下の対応を実施したのであるが、全く改善の兆しがない。
・BehaviorをDefaultのみとするのではなく、拡張子単位に定義する
・Viewer Protocol PolicyをRedirect HTTP to HTTPSからHTTPS Onlyに変更
 実験していると、何故か一時期https://~でアクセスしたリクエストはキャッシュインされないのに、http://~でアクセスしたリクエストはキャッシュされる様な事象が散見された。
 そのため、http://~でわざわざアクセスしてくる人も超レアケースかと思い、思い切って閉じたら、思い通りキャッシュされなくなってしまった。
・Allowd HTTP MethodsをGET, HEADからGET, HEAD, OPTIONSに変更
 POSTやDELETEは発行されたくないので(誤ってこちらが提供してしまっていた場合にやられるのを防ぐため)、OPTIONSのみ開放したが変化無
・MinimumTTL/MaximumTTL/DefaultTTLを2592000(約1カ月)に変更
 全く効果無
 なお、S3側のヘッダーは何も付加していないので、こちらを試す必要はあるのかもしれないが、コンソールから全部一括で行えない(ので一旦やっていない
 (CloudBerryやLambdaでやればいいだけではあるが)
・Cache Based on Selected Request Headers, Forward Cookies, Query String Forwading and CachingをNoneに設定
 これは元からそうしてる
・Smooth StreamingをYesに設定
 これをNoにはしたことないが、キャッシュされる/されないには関係ないと考えている
・Compress Objects AutomaticallyをYes→Noに設定
 変更したが効果無
 なお、クライアント端末が貧弱な可能性もありそうなので、通信経路の速さを期待して、あえてNoのままにした
Curlコマンドで事前に動画アクセス
 一時期改善が見られキャッシュインされる様になったが、1週間経ったら何故かキャッシュアウトされていた
 (想定では1カ月キャッシュインされている想定なのに…)

キャッシュアウトされたままという記事があまり見つからなかったので、手詰まり感があり、またそこまで今は困ってないので一旦調査は断念した。
結果としては、video.js → hls.jsにしたら大幅に改善した。
なお、hls.jsにした場合は、きちんと実装していないとiOSブラウザで再生ができなくなってしまうので、必ず検証しましょう(私は検証したら、見事やらかしていた[まじめに検証して良かった])。

残課題

hls.jsを用いると、偶発的ではあるが頻繁に早送り・巻戻しを行うと、Windows版のChromeでは止まってしまう現象を確認している。
但し、AndroidChromeや、iOSSafariでは特に発生していない。
オプション与えないといけないのではあろうが、他の作業進めないといけなかったので、一旦調査を止めている。