Video on demand (VOD) HLSをPCで作成

こんにちは、動画チームのhagi＠streampackです。

#はじめに

今回は"Video on demand (VOD) HLSをPCで作成"について書きたいと思います。
mp4をそのまま置いてプログレッシブダウンロードでVODを提供することもできますが、HLSにしてABRや暗号化と組み合わせることでダウンロードをめんどくさくすることが可能な上、再配布も簡単にできないようにすることができます。

#環境

## 配信について

HLSは特別な配信サーバーは必要ないです。
インターネットからアクセスできてプレイヤーが必要なファイルをダウンロードできれば再生できます。

今回は配信環境はs3としますがwebサーバーであれば配信可能です。

## HLSの作成

ffmpeg、mediafilesegmenter(OSX)、Media Converter(AWS)などありますが今回は"簡単"に"ローカルPC"で作成という自己テーマなので簡単に利用できるツールと思い、そこでWindows/Mac/Linux用バイナリやソースコードがある[bento4](https://www.bento4.com)を使います。

動画のHLS作成環境はMAC(OSX)としていますが他のOSでも大きく変わらないと思います。

# bento4の準備

## bento4とは

bento4(https://www.bento4.com)

>A fast, modern, open source C++ toolkit for all your MP4 and MPEG DASH media format needs

要約：MP4とMPEG DASH用のツールキット

あれ、HLSは？

HLSについては[こちら](https://www.bento4.com/developers/hls/)に記述

>While Bento4 is an MP4 file format library, and HLS uses the MPEG2 TS (Transport Stream) format, Bento4 includes a set of tools and functions that allow the conversion from MP4 to MPEG2 TS, as well as tools to create the .m3u8 playlists for HLS (HTTP Live Streaming).

意訳：MP4からMPEG2 TSの変換もできるのでHLSもできますよー

**ただし入力ファイルはMP4である必要がある。**

# bento4のインストール

1. ダウンロードページに行く https://www.bento4.com/downloads/
2. OSに対応したパッケージをダウンロードする(今回はMAC OSX用）
3. ダウンロードしたzipファイルを解凍

以上

# mp4のhls化

上記で解凍したパッケージにはbinフォルダーがあり、いくつものコマンドが準備されています。各コマンドの一覧や詳細は[こちら](https://www.bento4.com/documentation/)をご参照ください。

例：

```
Bento4-SDK-1-5-1-622.universal-apple-macosx/bin
aac2mp4			mp42avc			mp42ts			mp4dashclone		mp4dump			mp4extract		mp4iframeindex		mp4rtphintinfo
libBento4C.dylib	mp42hevc		mp4compact		mp4dcfpackager		mp4edit			mp4fragment		mp4info			mp4split
mp42aac			mp42hls			mp4dash			mp4decrypt		mp4encrypt		mp4hls			mp4mux			mp4tag
```

HLS化で利用するのが `mp42hls`です。

[Usage](https://www.bento4.com/documentation/mp42hls/)
>usage: mp42hls [options] <input>

一番簡単な使い方が

1.HLSの格納フォルダーを作成 - コマンド実行場所が格納場所となってしまうため。
`$ mkdir <dir>`
2.作成したフォルダーに移動
`$ cd <dir>`
3.コマンド実行 
`$ mp42hls <動画>`

例：

```
$ mkdir demohls
$ cd demohls
$ ../Downloads/Bento4-SDK-1-5-1-622.universal-apple-macosx/bin/mp42hls ../Downloads/Videos/demovid.mp4
$ ls
segment-0.ts	segment-1.ts	segment-2.ts	segment-3.ts	segment-4.ts	segment-5.ts	segment-6.ts	segment-7.ts	stream.m3u8
```

## 作成されたファイルについて

コマンドを実行しますと下記のファイルが作成されます。

```
segment-0.ts	segment-1.ts	segment-2.ts	segment-3.ts	segment-4.ts	segment-5.ts	segment-6.ts	segment-7.ts	stream.m3u8
```  

*.m3u8 - プレイリスト
*.ts - mpeg2 ts データファイル

### プレイリスト

```
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:7.382375,
segment-0.ts
#EXTINF:6.965292,
segment-1.ts
#EXTINF:7.090417,
segment-2.ts
#EXTINF:6.923583,
segment-3.ts
#EXTINF:6.923583,
segment-4.ts
#EXTINF:7.173833,
segment-5.ts
#EXTINF:7.007000,
segment-6.ts
#EXTINF:0.959292,
segment-7.ts
#EXT-X-ENDLIST
```

プレイリストには動画再生の順番や各ファイルの再生時間が記述されています。
プレイヤーはこのファイルの情報を元に動画を再生します。

### ts データファイル

分割されたデータファイルです。

# 配信

1.プレイリスト+tsファイルを全てs3にアップロードします。
　　　　場合によってはPublicにするのを忘れずに
2.プレーヤーにアップロードされたs3のプレイリストを指定します。(Safariであればそのまま再生ができるはずです。)

```
https://s3-ap-northeast-1.amazonaws.com/XXXXXXXX/demo/segment.m3u8
```

# オプション例

## AES-128暗号化を利用したい

フォーマット

```
mp42hls --encryption-key <key hexvalue> --encryption-key-uri <key location> <video name>
```

実行例

```
$ mp42hls --encryption-key 47de45c1b3931ab8baf4f7394bbecc02 --encryption-key-uri demo.key demovid.mp4
$ ls
demo.key	segment-0.ts	segment-1.ts	segment-10.ts	segment-2.ts	segment-3.ts	segment-4.ts	segment-5.ts	segment-6.ts	segment-7.ts	segment-8.ts	segment-9.ts	stream.m3u8
```

マニフェスト内容

EXT-X-KEYにAES-128と鍵のURIが記述されていることを確認

```
$ cat stream.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="demo.key"
#EXTINF:6.715042,
segment-0.ts
#EXTINF:6.506500,
segment-1.ts
#EXTINF:8.133125,
segment-2.ts
#EXTINF:6.965292,
segment-3.ts
#EXTINF:6.464792,
segment-4.ts
#EXTINF:10.093417,
segment-5.ts
#EXTINF:6.506500,
segment-6.ts
#EXTINF:6.589917,
segment-7.ts
#EXTINF:6.673333,
segment-8.ts
#EXTINF:6.339667,
segment-9.ts
#EXTINF:7.507500,
segment-10.ts
#EXT-X-ENDLIST
```

### AES-128鍵の作成方法

いくつもの方法があると思いますがここではopensslでの作成方法を記述いたします。

適当な16byteの値を使って鍵を作成

```
$ openssl rand 16 > demo.key
```

鍵のhex値を確認

```
＄ xxd -ps demo.key
47de45c1b3931ab8baf4f7394bbecc02
```


## ファイル名を指定したい

###　マニフェストのみ

フォーマット

```
$ mp42hls --index-filename <manifest filename>.m3u8 <video name>
```

実行例

```
$ mp42hls --index-filename demomanifest.m3u8 demovid.mp4
$ ls
demomanifest.m3u8	segment-0.ts		segment-10.ts		segment-3.ts		segment-5.ts		segment-7.ts		segment-9.ts
demovid.mp4		segment-1.ts		segment-2.ts		segment-4.ts		segment-6.ts		segment-8.ts
```

### マニフェスト+データファイル名

フォーマット

```
$ mp42hls --index-filename <manifest filename>.m3u8 --segment-filename-template <segment filename>.%d.ts --segment-url-template <segment filename>.%d.ts <video name>
```

実行例

```
$ mp42hls --index-filename demomanifest.m3u8 --segment-filename-template demoseg%d.ts --segment-url-template demoseg%d.ts demovid.mp4
$ ls
demomanifest.m3u8	demoseg1.ts		demoseg2.ts		demoseg4.ts		demoseg6.ts		demoseg8.ts		demovid.mp4
demoseg0.ts		demoseg10.ts		demoseg3.ts		demoseg5.ts		demoseg7.ts		demoseg9.ts
```

マニフェスト内容

```
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:6.715042,
demoseg0.ts
#EXTINF:6.506500,
demoseg1.ts
#EXTINF:8.133125,
demoseg2.ts
#EXTINF:6.965292,
demoseg3.ts
#EXTINF:6.464792,
demoseg4.ts
#EXTINF:10.093417,
demoseg5.ts
#EXTINF:6.506500,
demoseg6.ts
#EXTINF:6.589917,
demoseg7.ts
#EXTINF:6.673333,
demoseg8.ts
#EXTINF:6.339667,
demoseg9.ts
#EXTINF:7.507500,
demoseg10.ts
#EXT-X-ENDLIST
```

## segment長を指定したい

フォーマット

```
$ mp42hls --index-filename <manifest filename>.m3u8 --segment-filename-template <segment filename>.%d.ts --segment-url-template <segment filename>.%d.ts --segment-duration <segment length>　<video name>
```

実行例

```
$ mp42hls --index-filename demomanifest.m3u8 --segment-filename-template demoseg%d.ts --segment-url-template demoseg%d.ts --segment-duration 18 demovid.mp4
$ ls
demomanifest.m3u8	demoseg0.ts		demoseg1.ts		demoseg2.ts		demoseg3.ts		demoseg4.ts		demovid.mp4
```

マニフェスト内容

EXT-X-TARGETDURATIONをご確認ください。

```
$ cat demomanifest.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-TARGETDURATION:19
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:18.226542,
demoseg0.ts
#EXTINF:18.435083,
demoseg1.ts
#EXTINF:18.184833,
demoseg2.ts
#EXTINF:19.936583,
demoseg3.ts
#EXTINF:3.712042,
demoseg4.ts
#EXT-X-ENDLIST
```

# 最後に

VODのHLS化はだいぶハードルが下がりmp4同様にウェブサーバーからの配信が可能です。
s3から配信すれば設定すらほぼいらずとなります。

またBento4はHLS作成以外にもMP4を操作して動画と音声を分けたり、MPEG-DASHを作成したり、動画に音声をつけたりも可能です。

https://www.bento4.com/documentation/

ぜひお試しください！