ffmpeg を使い、HTTP Live Streaming(HLS)をファイルに保存し、保存したファイルからストリーミングを行う方法について

  • 110
    Like
  • 0
    Comment
More than 1 year has passed since last update.

追記

2016/02/16 に ffmpeg version 3.0 がリリースされました

ver 3.0 では libaacplus libvo-aacenc が削除されるなど、コーデックとコンテナの統廃合が行われたようです。

このエントリは ffmpeg version 2.x について記述しているため、
ver 3.x ではそのままでは動かない部分があるかもしれません。ご留意ください。

また、 libfdk_aac が使えない場合は、 libfaac を使用してください。

本文

ffmpeg を使い HLS を使ったストリーミングを mp4 フォーマットで保存したり、その反対に mp4 からストリーミングを行う(m3u8 と ts ファイルを生成する)方法について説明します。

まずは、ffmpeg をインストールします。既にインストールされている場合は、AAC, H264, MP4, MPEG-2 TS が利用可能かどうかを確認します。

ffmpeg で利用できる format と codec を確認する

$ ffmpeg -formats$ ffmpeg -codecs で利用可能なフォーマットとコーデックを確認できます。

ffmpeg version 2.8.1 Copyright (c) 2000-2015 the FFmpeg developers
  built with Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/2.8.1 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libvo-aacenc --enable-libxvid --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libfdk-aac --enable-libopenjpeg --disable-decoder=jpeg2000 --extra-cflags='-I/usr/local/Cellar/openjpeg/1.5.2_1/include/openjpeg-1.5 ' --enable-nonfree --enable-vda
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libavresample   2.  1.  0 /  2.  1.  0
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
File formats:
 D. = Demuxing supported
 .E = Muxing supported
 --
 D  aac             raw ADTS AAC (Advanced Audio Coding)
 DE h264            raw H.264 video
  E mp4             MP4 (MPEG-4 Part 14)
 DE mpegts          MPEG-TS (MPEG-2 Transport Stream)
ffmpeg version 2.8.1 Copyright (c) 2000-2015 the FFmpeg developers
  built with Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/2.8.1 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libvo-aacenc --enable-libxvid --enable-vda
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libavresample   2.  1.  0 /  2.  1.  0
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
Codecs:
 D..... = Decoding supported
 .E.... = Encoding supported
 ..V... = Video codec
 ..A... = Audio codec
 ..S... = Subtitle codec
 ...I.. = Intra frame-only codec
 ....L. = Lossy compression
 .....S = Lossless compression
 -------
 DEV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_vda ) (encoders: libx264 libx264rgb )
 DEA.L. aac                  AAC (Advanced Audio Coding) (decoders: aac aac_fixed ) (encoders: aac libvo_aacenc )

利用できないコンテナやコーデックがある場合は、ffmpeg を再インストールする必要があります。

ffmpeg で AAC が利用できるように以下のオプションを付けてインストールしてください。既にインストール済みの場合は brew uninstall ffmpeg の後に再インストールします。

$ brew install ffmpeg --with-fdk-aac --with-libvo-aacenc

ffmpeg options

ffmpeg の代表的なオプションについて、簡単に説明しておきます。

  • MAIN OPTIONS

    • -i 入力ファイル名の指定。URLも指定できます(-i http://domain:port/path/file.ext)
      • 複数指定が可能です -i a.ext -i b.ext
      • 連番指定が可能です -i "test_0%01d.png" とすると test_00.pngtest_09.png を自動的に読み込みます(存在しないファイルはエラーにならず無視されます)
    • -f 出力フォーマットの指定です
    • -y 出力ファイル名と同名のファイルがある場合に上書します
    • -fs 出力ファイル名の最大サイズを指定します。単位はbyteです
    • 出力ファイル名。printf に似た書式で連番のファイル名を指定する事も可能です (例: media%03d.ts)
  • VIDEO OPTIONS

    • -b 動画部分のビットレートを指定します。初期設定は 200kbps です
    • -r フレームレートを指定します。初期設定は25です
    • -s 動画のサイズを 幅x高さで指定します。(例: 800x600)
    • -aspect アスペクト比を指定します
    • -vn ビデオをカットします。音声だけを取り出します
    • -vcodec ビデオコーデックを指定します。指定しない場合は入力ファイルと同じコーデックになります
    • -movflags faststart 録画終了後にメタデータをmp4ファイルの先頭部分に移動します。再生開始までの時間が短縮されます
  • AUDIO OPTIONS

    • -ar サンプリング周波数を指定します
    • -ac 音声のチャンネル数を指定します
    • -an オーディオをカットします。映像だけを取り出します
    • -acodec 音声コーデックを指定します。指定しない場合は入力ファイルと同じコーデックになります

ffmpeg ではオプションを指定する順番によって結果が異なります。映像系のオプションは音声系と混ぜずに連続で指定するようにしてください。

また上手く行かない場合は、オプションの順番を変えてみてください。

HLSのストリーム を mp4 に保存する

さてやっと本題です、以下のコマンドで、HLS のストリームを mp4 に直接保存できます。

$ ffmpeg -i https://example.com/.../playlist.m3u8 -movflags faststart -c copy -bsf:a aac_adtstoasc rec.mp4

映像と音声を分離する

以下のコマンドを使うと、input.mp4 の映像と音声を別々のファイル(audio.m4a, video.mp4)に分離できます。

$ ffmpeg -i input.mp4 -bsf:a aac_adtstoasc -vn -acodec copy audio.m4a
$ ffmpeg -i input.mp4 -bsf:a aac_adtstoasc -vcodec copy -an video.mp4

以下のコマンドで、stream/a001.ts から stream/a001.aac を抽出できます。

$ ffmpeg -i stream/a000.ts -acodec copy stream/a000.aac

mp4 ファイルをストリーミングする

input.mp4 を HLS でストリーミング可能なように stream/playlist.m3u8 と stream/a{nnn}.ts を生成します。
以下のコマンドを改行せず一行で書いてください。

$ ffmpeg
    -i input.mp4                  // input source
    -vcodec libx264               // video codec    (H264)
    -movflags faststart           // video fast decode(mov box moov to header)
    -vprofile baseline -level 3.0 // video profile  (Baseline, Lv 3.0)
    -g 150                        // ?
    -b:v 519k                     // video bitrate  (519kbps)
    -s 768x432                    // video size     (768 x 432 px)
//  -acodec libfaac               // audio codec    (AAC)
    -acodec libfdk_aac
    -b:a 63.4k                    // audio bitrate  (63.4kbps)
    -ar 44100                     // audio sampling rate (44.1kHz)
    -flags +loop-global_header
    -map 0
    -bsf h264_mp4toannexb
    -f segment
    -segment_format mpegts
    -segment_time 5               // ts duration
    -segment_list stream/playlist.m3u8  // playlist filename 
    stream/v%03d.ts               // ts file name format

例.

$ ffmpeg -i input.mp4 -vcodec libx264 -movflags faststart -vprofile baseline -level 3.0 -g 150 -b:v 519k -s 768x432 -acodec libfdk_aac -b:a 63.4k -ar 44100 -flags +loop-global_header -map 0 -bsf h264_mp4toannexb -f segment -segment_format mpegts -segment_time 5 -segment_list stream/playlist.m3u8 stream/a%03d.ts

hls_time

-segment_time n でイメージ通りの秒数を持つtsを作成できない場合は、 -segment_time の代わりに -hls_time を使ってみてください。

$ ffmpeg -i input.mp4 -vcodec libx264 -movflags faststart -vprofile baseline -level 3.0 -g 150 -b:v 519k -s 768x432 -acodec libfdk_aac -b:a 63.4k -ar 44100 -flags +loop-global_header -map 0 -bsf h264_mp4toannexb -f segment -segment_format mpegts -hls_time 5 -segment_list stream/playlist.m3u8 stream/a%03d.ts

ファイルの情報を見る

ffprobe コマンドで mp4 ファイルの情報を見ることができます。
(ffprobe コマンドは ffmpeg をインストールすると一緒にインストールされます)

$ ffprobe input.mp4

> Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
>   Metadata:
>     major_brand     : isom
>     minor_version   : 512
>     compatible_brands: isomiso2avc1mp41
>     encoder         : Lavf56.40.101
>   Duration: 00:02:02.81, start: 0.000000, bitrate: 591 kb/s
>     Stream #0:0(und): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p, 432x768, 519 kb/s, 26.89 fps, 90k tbr, 90k tbn, 180k tbc (default)
>     Metadata:
>       handler_name    : VideoHandler
>     Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 63 kb/s (default)
>     Metadata:
>       handler_name    : SoundHandler

以下のオプションも利用できます。

  • -show_format Show information about the container format of the input multimedia stream.
  • -show_packets Show information about each packet contained in the input multimedia stream.
  • -show_frames Show information about each frame and subtitle contained in the input multimedia stream.
  • -show_streams Show information about each media stream contained in the input multimedia stream.
  • -show_programs Show information about programs and their streams contained in the input multimedia stream.
  • -count_frames Count the number of frames per stream and report it in the corresponding stream section.
  • -count_packets Count the number of packets per stream and report it in the corresponding stream section.
  • -of json output to JSON format.

プログラムから簡単にチェックできるように、JSON で出力することもできます。

$ ffprobe -of json -show_format  rec.mp4  >  a.format.json    # format 情報を取得
$ ffprobe -of json -show_packets rec.mp4  >  a.packet.json    # パケット情報を取得
$ ffprobe -of json -show_streams rec.mp4  >  a.stream.json    # 映像と音声ストリームの情報を取得

ffprobe の他に mediainfo コマンドでも情報をみることができます。

$ mediainfo input.mp4

> General
> Complete name                            : input.mp4
> Format                                   : MPEG-4
> Format profile                           : Base Media
> Codec ID                                 : isom
> File size                                : 8.66 MiB
> Duration                                 : 2mn 2s
> Overall bit rate mode                    : Variable
> Overall bit rate                         : 591 Kbps
> Encoded date                             : UTC 1904-01-01 00:00:00
> Tagged date                              : UTC 1904-01-01 00:00:00
> Writing application                      : Lavf56.40.101
>
> Video
> ID                                       : 1
> Format                                   : AVC
> Format/Info                              : Advanced Video Codec
> Format profile                           : Baseline@L3
> Format settings, CABAC                   : No
> Format settings, ReFrames                : 1 frame
> Format settings, GOP                     : M=1, N=30
> Codec ID                                 : avc1
> Codec ID/Info                            : Advanced Video Coding
> Duration                                 : 2mn 2s
> Bit rate                                 : 519 Kbps
> Width                                    : 432 pixels
> Height                                   : 768 pixels
> Display aspect ratio                     : 0.562
> Frame rate mode                          : Variable
> Frame rate                               : 26.889 fps
> Minimum frame rate                       : 0.850 fps
> Maximum frame rate                       : 90 000.000 fps
> Color space                              : YUV
> Chroma subsampling                       : 4:2:0
> Bit depth                                : 8 bits
> Scan type                                : Progressive
> Bits/(Pixel*Frame)                       : 0.058
> Stream size                              : 7.60 MiB (88%)
> Encoded date                             : UTC 1904-01-01 00:00:00
> Tagged date                              : UTC 1904-01-01 00:00:00
>
> Audio
> ID                                       : 2
> Format                                   : AAC
> Format/Info                              : Advanced Audio Codec
> Format profile                           : LC
> Codec ID                                 : 40
> Duration                                 : 2mn 2s
> Bit rate mode                            : Variable
> Bit rate                                 : 63.4 Kbps
> Maximum bit rate                         : 65.1 Kbps
> Channel(s)                               : 2 channels
> Channel(s)_Original                      : 1 channel
> Channel positions                        : Front: C
> Sampling rate                            : 44.1 KHz
> Compression mode                         : Lossy
> Stream size                              : 950 KiB (11%)
> Encoded date                             : UTC 1904-01-01 00:00:00
> Tagged date                              : UTC 1904-01-01 00:00:00

MP4のコンテナ構造(box)をビジュアル化するツールもあります。

ブラウザ上で動作するツールもあります。
- MP4Box.js / ISOBMFF Box Structure Viewer

MP4 Reader と MP4Box.js の解析結果の細部(stbl以下のbox)が異なる場合が見られます。参考程度に見ておくと良いでしょう。

参考になさってください。