Apple HLS 最新情報キャッチアップ #WWDC2017


こんにちは、とっしーこと @toshi0383 です。

さて、WWDC 2017にて、HLSがRFCの仕様として正式に承認されたことが発表されました。

HLSは長い間Apple独自仕様の "draft" 仕様の状態で、Webやアプリの開発者としてはどこまで本気で投資して良いものやら本質的にはよく分からない状態でした。これが正式な仕様にランクアップしたということは、これまでHLS周辺技術に投資してきた開発者にとっては結構ハッピーなニュースなのではないでしょうか。
最新版のドラフトがアップされるので見てねということでした。で、今しがたチェックしたら上がってました。
https://developer.apple.com/streaming/HLS-WWDC-2017-Preliminary-Spec.pdf

他にも色々重要事項が発表されていたのですが、細かいことはすぐ忘れてしまうので、備忘も兼ねてまとめておこうと思います。主に以下のセッションの話題になります。

Advances in HTTP Live Streaming
https://developer.apple.com/videos/play/wwdc2017/504/

# HEVC/H.265
新しいOSからHEVCがサポートされます。
![Screen Shot 2017-06-11 at 21.02.59.png](https://qiita-image-store.s3.amazonaws.com/0/35008/b92b5f67-37b8-aae1-c66e-80754c3ee3b3.png "Screen Shot 2017-06-11 at 21.02.59.png")

HEVC自体はFacetimeアプリでA8チップからサポートされていましたが、開発者には非公開の状態でした。iOS11からA9チップであればハードウェアデコードがサポートされるそうです。そうでなくでもソフトウェアデコードはサポートされるようなので、基本的には何も心配することはなさそうです。

## コンテナフォーマットと暗号化
ただし、なんとHEVCはtsではサポートされず、fmp4のみとのこと。

> No support for HEVC in MPEG-2 TS

長い間HLSのコンテナフォーマットとして使われてきたts(transport stream)は今後非推奨になっていく雰囲気のようです。寂しいような気もしますが、何か目の上のたんこぶが取れるような気がするのは私だけでしょうか。

暗号化に関しては "同じようにcommon encryptionのcbcsスキームを使用できる" とのことです。が、表にある通りFairPlayはソフトウェアデコードの場合はサポートされません。HEVCでFairPlayを利用できるようになるのは、現実的にはもう少し先の話なのかもしれません。

## 古いOSとの互換性

```
CODECS= "hvc1.2.4.L123.B0,..."
```

古いOSとの互換性を保つために `CODEC` 属性を使いましょうという話でした。
WWDCセッション動画のプレイリストもちょうどいい例になりますね。

```
$ curl https://devstreaming-cdn.apple.com/videos/wwdc/2017/504op4c3001w2f222/504/hls_vod_mvp.m3u8 | head
#EXTM3U
#EXT-X-VERSION:4

#EXT-X-STREAM-INF:BANDWIDTH=1096572,AVERAGE-BANDWIDTH=1096572,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x360
0640/0640.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=548286,AVERAGE-BANDWIDTH=548286,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x360,URI="0640/0640_I-Frame.m3u8"

#EXT-X-STREAM-INF:BANDWIDTH=6176320,AVERAGE-BANDWIDTH=6176320,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1920x1080
1920/1920.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=3088160,AVERAGE-BANDWIDTH=3088160,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1920x1080,URI="1920/1920_I-Frame.m3u8"
```

マスタープレイリストでは複数コーデックが混ざっても大丈夫ということで、HEVCで配信するプレイリストとAVC1で配信するプレイリストをクライアント側で使い分けてもらうことができるようです。

# IMSC1
新しい字幕フォーマットがサポートされるそうです。
自分的に需要がなかったのでここは割り切って省略します。

# EXT-X-GAP
新しいタグが追加されました！
配信側のエラーに対してクライアント側がフェイルセーフに振る舞うための仕組みなようです。
例えばABR(Adaptive Bitrate)で配信中、特定のビットレートのパッケージングに一時的に失敗したような場合、正しい情報の代わりに `EXT-X-GAP` を書き込むことで、クライアント側は無駄に動画をフェッチしに行ったりせず、エラー状態から復帰するのを待機することができるということです。その間もし他のビットレートのプレイリストが正常に更新されていれば、そちらにシームレスにスイッチすることでユーザは配信に異常があったことにすら気づかない、というユースケースを想定しているようです。もちろん、iOSであればAVPlayerがこの辺りよしなにハンドリングしてくれるということなのでしょう。

![Screen Shot 2017-06-11 at 23.06.20.png](https://qiita-image-store.s3.amazonaws.com/0/35008/72247779-dc86-5e8b-57cc-c6f2050d760d.png "Screen Shot 2017-06-11 at 23.06.20.png")

主にライブ中継で活躍しそうですが、見逃し配信するような場合にも、上記のような異常があったコンテンツでもある程度安全に再生できるというのは配信側としては嬉しいのではないでしょうか。

mpd(MPEG-DASH)でもこういうことできるのかな？

# 変数サポート
これは結構派手な機能ですね。これまではURIを一括で変更するような手段がなかったので、割と重宝するのではないでしょうか？
プロダクション環境でのユースケースとして、CDNに配置したコンテンツへのアクセス制御が挙げられていました。

![Screen Shot 2017-06-11 at 21.57.52.png](https://qiita-image-store.s3.amazonaws.com/0/35008/7e14b72a-1fff-fb12-a92f-eefb3a35c45b.png "Screen Shot 2017-06-11 at 21.57.52.png")

# ライブ映像同期
個人的に一番テンションが上がったのがこれです。複数のプレイヤー間でライブ映像の時刻を同期できるようになりました。デモをやっていましたが、全くなんの問題なく動いていて逆に拍子抜けというか、この辺りの作り込みはさすがバッチリ決めてくるなという印象を受けました。

![Screen Shot 2017-06-11 at 23.14.30.png](https://qiita-image-store.s3.amazonaws.com/0/35008/079ebee1-32e8-679f-a3cd-29b65f5c11ec.png "Screen Shot 2017-06-11 at 23.14.30.png")

![Screen Shot 2017-06-11 at 23.14.40.png](https://qiita-image-store.s3.amazonaws.com/0/35008/0fbc5d2a-c381-df4c-880b-39ec78e3aa2d.png "Screen Shot 2017-06-11 at 23.14.40.png")

`EXT-X-PROGRAM-DATE-TIME` というタグを使いますが、アプリ側もこれを想定したコードを書く必要があり、公開されている `SyncStartTV` というサンプルコードを参考にするといいようです。(デモで使っていたアプリ)

# preferredPeakBitRate
プレイヤー側で最大ビットレートを設定できるようになりました。例えばコレクションビューセルに動画の最初の部分をプレビューとして表示する場合などに使えそうですね。

# ダウンロードしたコンテンツの管理
- 設定アプリから削除できるようになった！
- `AVAssetDownloadStorageManagementPolicy` で有効期限もしくは重要度を設定できる

# AVAggregateAssetDownloadTask

ダウンロード用の新しいクラスが追加されました。主に複数オーディオがある場合等に便利に使えるようですが、こちらも個人的に需要がないため割愛します。

# FairPlay
FairPlayに関してもいくつかアップデートがありました。

## AVContentKeySession
まず嬉しいのはiOS11からコンテンツの再生とキーの取得が別々に実行できるようになったことですね。このクラスを使えば、事前にライセンスサーバにアクセスしてキーを取得しておくことができます。実際にキーをロードするのは再生する直前にしといてねとのことでした。

## オフライン再生用のキーの2段階の有効期限
`Dual Expiry Windows for Persistent Keys` こういう訳であっているのかな。。？
要するにキー自体(storage)の有効期限と、キーを使って再生できる有効期限を設定できるようになりました。
storageの有効期限内にユーザが再生を開始したら新しいキーを取得して、そのキーで再生できる有効期限を管理するという仕組みのようです。いわゆるレンタル機能ですね。

![Screen Shot 2017-06-11 at 22.24.14.png](https://qiita-image-store.s3.amazonaws.com/0/35008/78d1088e-7f72-b5f0-ab67-a9755f6c5fd6.png "Screen Shot 2017-06-11 at 22.24.14.png")

最初のキーはその時点で無効になるとのこと。
![Screen Shot 2017-06-11 at 22.24.53.png](https://qiita-image-store.s3.amazonaws.com/0/35008/1a30b512-31dc-3438-6817-c8b180c58f62.png "Screen Shot 2017-06-11 at 22.24.53.png")

# まとめ
WWDC 2017で発表のあったHLS関連の話題を雑にまとめてみました。
業界的にはライブ配信が盛り上がりを見せる昨今、Appleも動画視聴のユーザ体験についてちゃんと考えてきているなあという印象を受けました。昨年はfmp4対応とOffline FPSってなくらいでしたが、今年は新しい動画エンコード仕様への対応という大きなアップデートにとどまらず、プレイリストレベルでのエラーハンドリングの仕組みやライブ映像同期など、結構かゆいところの新機能まで盛りだくさんでしたね。
~~こんなに一生懸命やってくれるならFairPlayもCommon Encryptionのmandatory仕様にきちんと対応してくれるとかいっそMPEG-DASHに乗り換えちゃうとか他にも色々できることはあるんじゃないかという気持ちになりそうですがそういうのはグッと飲み込んで、~~ まずは新しいOSの登場を心待ちにしたいと思います📺