ffmpeg でファイルから4K HEVC疑似ライブストリーミング

# はじめに

こんにちは streampack の木村です。

4K HEVC ライブ配信は業務として何回か経験があって、配信本番では小職が一年間働いても買えるのかコレ？？的な超高級なハードウェア エンコーダーを使ったりしますが、検証になるとそんなものは当然持っていないので、んじゃ ffmpeg でやるべ！　と意気揚々と挑んでハマったので備忘録です。

# やりたいこと

やりたいことは単純です！

**4K HEVC ライブ → Streaming Server → MPEG-DASH → Player** 

これを手元にあるもので実現したいっ！

上記を踏まえて下記を用意しました。

- ffmpeg （ライブエンコーダー代わり AWS EC2）
- Wowza Streaming Engine （AWS EC2）
- ExoPlayer （Samsung Galaxy S8）


# コンテンツの準備

http://4ksamples.com/ から適当なものを拝借

```
$ ffprobe Samsung_UHD_Soccer_Barcelona_Atletico_Madrid.ts
ffprobe version 3.4.2 Copyright (c) 2007-2018 the FFmpeg developers
  built with Apple LLVM version 9.0.0 (clang-900.0.39.2)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.4.2 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --disable-jack --enable-gpl --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma --enable-nonfree
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100
  libavdevice    57. 10.100 / 57. 10.100
  libavfilter     6.107.100 /  6.107.100
  libavresample   3.  7.  0 /  3.  7.  0
  libswscale      4.  8.100 /  4.  8.100
  libswresample   2.  9.100 /  2.  9.100
  libpostproc    54.  7.100 / 54.  7.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Samsung_UHD_Soccer_Barcelona_Atletico_Madrid.ts':
  Metadata:
    major_brand     : iso4
    minor_version   : 1
    compatible_brands: iso4hvc1
    creation_time   : 2014-06-03T22:43:24.000000Z
  Duration: 00:03:52.00, start: 0.040000, bitrate: 45839 kb/s
    Stream #0:0(und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv), 3840x2160 [SAR 1:1 DAR 16:9], 45730 kb/s, 50 fps, 50 tbr, 50k tbn, 50 tbc (default)
    Metadata:
      creation_time   : 2014-06-03T22:43:24.000000Z
      handler_name    : Encoded with IFME v3.2.1.0
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 117 kb/s (default)
    Metadata:
      creation_time   : 2014-06-03T22:43:31.000000Z
      handler_name    : Track 1
```

このままだと ffmpeg で流せないので再エンコードしてフォーマットもMP4にします。

```
$ ffmpeg -i Samsung_UHD_Soccer_Barcelona_Atletico_Madrid.ts -acodec copy -c:v libx265 -x265-params keyint=60:min-keyint=60:scenecut=0:no-open-gop=1 -b:v 10000k -r 30 -minrate 10000k -maxrate 10000k -bufsize 20000k -preset fast -movflags faststart hevcuhd.mp4
```

# 設定

## Wowza Streaming Engine

1. Wowza Streaming Engine Manger コンソールにアクセスして live アプリケーションを開きます。
ここで MPEG-DASH が有効であることを確認します。（デフォルトでは有効になっているはず）

    <img width="1231" alt="スクリーンショット 2018-05-10 15.03.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/172426/423c88b3-34e1-6d15-3b82-e3aee445804c.png">

2. live > Stream Files に移動して、`+ Add Stream File` をクリックします。

    <img width="1235" alt="スクリーンショット 2018-05-10 15.01.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/172426/4dbe4043-1646-60bc-30fd-69104096fb6d.png">

3. ダイアログが開くので以下のように入力します。

    `Stream File` 名は任意の名前の後ろに`.stream`が必要です。
    `Stream URI` には `udp://0.0.0.0:{任意のUDPポート番号}` とします。

    **注：Wowza EC2に対してこのポート番号の UDP インバウンドを Security Group で通す必要があります。**

    <img width="576" alt="スクリーンショット 2018-05-10 15.02.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/172426/5dbd1fd0-fc51-2477-7ac1-d850be51250d.png">

4. `+Add`をクリックすると Stream File に追加されるので、Actions の `Connect to this stream` をクリックします。

    <img width="1233" alt="スクリーンショット 2018-05-10 15.19.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/172426/6fecd0c1-b957-d12a-dd4a-4d89f1d58c13.png">

5. ダイアログが開くので何も弄らずに `OK` をクリックします。

    <img width="569" alt="スクリーンショット 2018-05-10 15.21.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/172426/3d561b28-5a58-9f84-fd95-cea1787c4954.png">

6. live > Incoming Streams で Stream File が `Active` になっていることを確認します。

<img width="1228" alt="スクリーンショット 2018-05-10 15.27.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/172426/ddb3eaa0-cb2f-b732-57fc-ff68035e6dab.png">

Wowza の設定は以上で完了です！

**注： 以降、Wowza 起動直後や、再起動後には上記 4.と 5. を行う必要があります**

# ライブ配信

それでは早速ライブ配信をはじめてみましょう！

## ffmpeg

以下のコマンドで ４K HEVC ファイルをループさせ、Wowza に UDP でストリームを投げつけます。

```
ffmpeg -re -stream_loop -1 -i hevcuhd.mp4 -vcodec copy -acodec copy -flags +loop-global_header -f mpegts udp://{Wowza の IP アドレス}:6000?pkt_size=1316
```

**<font color="Red">ハマった点</font>**

初め ffmpeg での投げ先を　`udp://{Wowza の IP アドレス}:6000` のみを指定して試しましたが、Wowza 側でストリームを受け付けずに困り果てていたところ `?pkt_size=1316` を付け加えろ！ とどっかに書いてあったので試したところうまく行きました！

## Wowza

Wowza Streaming Engine Manger の live > Monitoring でストリームが入力されているか確認します。
10Mbps でエンコしたので約10Mbpsの入力が確認できます。

![Image uploaded from iOS.png](https://qiita-image-store.s3.amazonaws.com/0/172426/9899502c-1487-3bae-3cd8-fb9ab1b9f2a0.png)

# 再生

それでは実際に Player で視聴してみましょう。
相変わらずウチは HEVC を再生できるのが、スマホしかないので ExoPlayer で視聴します。

## ExoPlayer

こんな感じでデプロイします。

|Streaming Method|Streaming URL|
|---|---|
|MPEG-DASH|http://{Wowza IP アドレス}:1935/live/4Kdash.stream/manifest.mpd|
|HLS|http://{Wowza IP アドレス}:1935/live/4Kdash.stream/playlist.m3u8|


![Image uploaded from iOS (1).jpg](https://qiita-image-store.s3.amazonaws.com/0/172426/0958c12e-a1a9-270b-f5be-3b1fd19050e8.jpeg)

### 視聴

一応再生できました！
`video/hevc` と `3840x2160` が表示されていますね。

![Screenshot_20180510-162943_ExoPlayer.jpg](https://qiita-image-store.s3.amazonaws.com/0/172426/21cc40a5-8f4f-c8f9-dfd5-6a190a72451c.jpeg)

HLS の方も ExoPlayer なら再生可能ですよ。

# まとめ

一応当初の目的どおり、無料のツールを組み合わせて 4K HEVC ライブ配信を行うことができました！
（Wowzaは有償版を利用しましたが、テストだけなら開発者ライセンスで同じことができます）


しかしながら、たまにブロックノイズが乗って画面が乱れたりします。
何だろう、何がいけないのだろうか・・・

原因不明ですが、テストなので取り敢えずここまで！