iOS, macOS における HTTP Live Streaming (HEVC) 用のメディアファイルを FFmpeg で作成するにあたり

スポンサーリンク

iOS, macOS における HTTP Live Streaming (HEVC) の再生機能は共に今日現在ではベータ版の機能であるため、再生できるかどうかについては記載していません。

環境はこちら。ハードウェア支援が無いとリアルタイムの変換が厳しいのでもう最近はビデオカードを購入して NVENC のみです。QSV は Linux でやるには CPU と OS の制限が厳しすぎて・・・。

そう、時代はまさに hevc_nvenc、一番安い GTX 1050 でも HEVC の変換速度、x9 くらいです。1万数千円の投資でこの効果はなかなか大きいと思います。

  • Intel(R) Core(TM) i3-4170 CPU @ 3.70GHz
  • Ubuntu 16.04.2
  • GeForce GTX 1050
  • LINUX X64 (AMD64/EM64T) DISPLAY DRIVER 384.59
  • FFmpeg N-86877

なお、NVIDIA のドライバや FFmpeg は新しめのものを使用する必要がありそうです。FFmpeg は snapshot 版を。

また、この内容は FFmpeg の vcodec には依存しない話だと思うので、libx265 でもいけるんじゃないかなと思います。(試してないですが)

まず、Apple が一般に公開している HTTP Live Streaming (HLS) のサンプルを見てみます。

HTTP Live Streaming Examples
https://developer.apple.com/streaming/examples/

Advanced stream (HEVC/H.264) を見てみると、”HEVC variants compatible with macOS v10.13 or later, iOS 11 or later, and tvOS 11 or later” と。

その中で、例えば Nine HEVC video variants Gear 6 – 1280×720 @ 2.4 Mbps のメディアファイルをダウンロードして ffmpeg で見てみます。

ffmpeg -i main.mp4 
ffmpeg version N-86877-g8e275a7 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609
  configuration: --disable-shared --enable-static
  libavutil      55. 69.100 / 55. 69.100
  libavcodec     57.102.100 / 57.102.100
  libavformat    57. 76.100 / 57. 76.100
  libavdevice    57.  7.100 / 57.  7.100
  libavfilter     6. 95.100 /  6. 95.100
  libswscale      4.  7.101 /  4.  7.101
  libswresample   2.  8.100 /  2.  8.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'main.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp41mp42isomhlsf
    creation_time   : 2017-06-06T02:40:23.000000Z
  Duration: 00:10:10.00, start: 10.016667, bitrate: 2433 kb/s
    Stream #0:0(eng): Video: hevc (Main 10) (hvc1 / 0x31637668), yuv420p10le(tv, bt709, progressive), 1280x720 [SAR 1:1 DAR 16:9], 2427 kb/s, 60 fps, 60 tbr, 6k tbn, 6k tbc (default)
    Metadata:
      creation_time   : 2017-06-06T02:40:23.000000Z
      handler_name    : Core Media Video
    Stream #0:1(eng): Subtitle: eia_608 (c608 / 0x38303663), 0 kb/s (default)
    Metadata:
      creation_time   : 2017-06-06T02:40:23.000000Z
      handler_name    : Core Media Closed Caption

次に FFmpeg で HEVC な HLS のメディアセグメントを何も考えずに作成してみます。

ffmpeg -i mokyu.mp4 -acodec aac -ab 128k -ar 48000 -ac 2 -s 1280x720 -vcodec hevc_nvenc -b:v 1000k -hls_segment_type fmp4 mokyu.m3u8

プレイリストを見てみます。なるほど、fragmeted MP4 の場合は、EXT-X-MAP 用に init.mp4 が作成され続けるようです。

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:9
#EXT-X-MEDIA-SEQUENCE:3
#EXT-X-MAP:URI="init.mp4"
#EXTINF:8.341667,
mokyu3.m4s
#EXTINF:8.341667,
mokyu4.m4s
#EXTINF:8.341667,
mokyu5.m4s
#EXTINF:8.341667,
mokyu6.m4s
#EXTINF:0.834167,
mokyu7.m4s

メタ的な情報も init.mp4 で見られるようです。

ffmpeg -i init.mp4 
ffmpeg version N-86877-g8e275a7 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609
  configuration: --disable-shared --enable-static
  libavutil      55. 69.100 / 55. 69.100
  libavcodec     57.102.100 / 57.102.100
  libavformat    57. 76.100 / 57. 76.100
  libavdevice    57.  7.100 / 57.  7.100
  libavfilter     6. 95.100 /  6. 95.100
  libswscale      4.  7.101 /  4.  7.101
  libswresample   2.  8.100 /  2.  8.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'init.mp4':
  Metadata:
    major_brand     : iso5
    minor_version   : 512
    compatible_brands: iso6mp41
    encoder         : Lavf57.76.100
  Duration: N/A, bitrate: N/A
    Stream #0:0(und): Video: hevc (Main) (hev1 / 0x31766568), yuv420p(tv), 1280x720 [SAR 1:1 DAR 16:9], 29.97 tbr, 30k tbn, 29.97 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp (default)
    Metadata:
      handler_name    : SoundHandler

Apple のサンプルと FFmpeg が生成するファイルの情報を比べるといろいろなところが微妙に異なっているようです。

で、いろいろと調べてみると、

  • Apple のサンプル (hvc1 / 0x31637668)
  • FFmpeg の成果物 (hev1 / 0x31766568)

この差が一番大きいようです。

FFmpeg でも Apple のサンプルと同じようにするためにはオプションに

-tag:v hvc1

を追加すればよいようです。

FFmpeg のコミットログを見ると、Apple のソフトウェアに対応するために定義を追加したとのこと。

If AVCodecParameters.codec_tag is ‘hvc1’ use it instead of ‘hev1’ for
h.265 streams. QuickTime (and other Apple software) requires ‘hvc1’.

movenc: allow alternative hvc1 h.265 codec tag
https://github.com/FFmpeg/FFmpeg/commit/369a3e111cb8015c3a3acc5c2c15728c8f37084f

実際に使用してみるには、例えば、

ffmpeg -i mokyu.mp4 -acodec aac -ab 128k -ar 48000 -ac 2 -s 1280x720 -vcodec hevc_nvenc -tag:v hvc1 -b:v 1000k -hls_segment_type fmp4 mokyu.m3u8

これを実行した後、再度 init.mp4 を見てみると、(hvc1 / 0x31637668) に変わってますね。

ffmpeg -i init.mp4 
ffmpeg version N-86877-g8e275a7 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609
  configuration: --disable-shared --enable-static
  libavutil      55. 69.100 / 55. 69.100
  libavcodec     57.102.100 / 57.102.100
  libavformat    57. 76.100 / 57. 76.100
  libavdevice    57.  7.100 / 57.  7.100
  libavfilter     6. 95.100 /  6. 95.100
  libswscale      4.  7.101 /  4.  7.101
  libswresample   2.  8.100 /  2.  8.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'init.mp4':
  Metadata:
    major_brand     : iso5
    minor_version   : 512
    compatible_brands: iso6mp41
    encoder         : Lavf57.76.100
  Duration: N/A, bitrate: N/A
    Stream #0:0(und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv), 1280x720 [SAR 1:1 DAR 16:9], 29.97 tbr, 30k tbn, 29.97 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp (default)
    Metadata:
      handler_name    : SoundHandler

というわけで、WWDC 2017 で公開されている情報では HLS の HEVC は fragmented MP4 (fMP4) のみとのことなので、H.264、MPEG2-TS から HEVC fMP4 へとシフトしていかなければなりませんね。

さて勉強勉強