読者です 読者をやめる 読者になる 読者になる

Jsys的FFmpeg入門

この記事は JSYS16 Advent Calendar 2016 7日目の記事です。

はじめまして

 はじめまして、TumoiYorozuです。

 漢字表記だと百千万億 萬です。これで「つもい よろず」と読みます。「百千万億」とは実在した日本の名字です。漢字は4文字なのに発音は3文字……。

 主に情報系の分野や、映像・創作系のことをやっています。

 

 某大学の学園祭では情報システム局 映像部門 生中継担当というところで技術屋をしていました。 

 オープンソースのマルチメディアフレームワークであるGStreamerを使って、C++で生中継配信で使うビデオミキサーなどを書いていました。

 

はじめに

 この記事は7日目の記事ですが、8日に書いています。8日の担当の記事が公開されたあとに書き始めました。申し訳ありません。

 

というわけで

 さて、このアドベントカレンダーはよそ様の団体の 512倍雑な記事で許されています。

 ある日突如 Advent Calendar やろうぜという話が出て、同時に Jsys16 Advent Calendar のページが発行されていました。

 いやぁ、地味に続いているのがすごい。(昨日書き忘れてすみません)

 

 というわけで雑なことを書こうと思ったのですが、1日目の担当者(この Advent Calendar の首謀)に、「お前は技術的なことを書け!」と言われたので、雑なことを書きたいと思います。

 

さて

 皆さんは FFmpegというフリーソフトを知っているでしょうか?

 動画変換などでおなじみのソフトの1つです。自宅鯖でアニメを録画してうんたらこうたらしている人で使っている方もいるでしょう。

 学園祭生中継プロジェクトでも話を欠かすことのできないソフトの一つです。早速PCにインストールしましょう。

 Ubuntu などを使っている方は

$ sudo apt-get install

  Macなどの方は

$ brew install ffmpeg

できっと入るハズ。

  Windowsの人は FFmpeg の公式HPから Windows Builds をダウンロードして、適当なフォルダに展開してパスを通しましょう。(嗚呼、めんどくさい)

 

 これでコマンドラインから ffmpeg と打つだけで使えるようになります。

 

  さっそく、動画ファイルなどを用意して、コマンドを叩いてみましょう。

$ ffmpeg -i input.mp4 output.avi

  はい。これで input.mp4 という名前の mp4 を output.avi というaviに変換できます。

 

 FFmpegでは -i の後に入力のファイル名という決まりになっています。

 出力ファイル名を指定せずに実行すると入力ファイルの情報だけを表示してくれて、たとえば

$ ffmpeg -i input.mp4
ffmpeg version N-82597-gd316b21 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 5.4.0 (GCC)
configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
libavutil 55. 40.100 / 55. 40.100
libavcodec 57. 66.106 / 57. 66.106
libavformat 57. 58.100 / 57. 58.100
libavdevice 57. 2.100 / 57. 2.100
libavfilter 6. 67.100 / 6. 67.100
libswscale 4. 3.101 / 4. 3.101
libswresample 2. 4.100 / 2. 4.100
libpostproc 54. 2.100 / 54. 2.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '
input.mp4':
Metadata:
major_brand : mp42
minor_version : 0 compatible_brands: mp42mp41
creation_time : 2016-11-25T17:32:19.000000Z
Duration: 00:11:23.26, start: 0.000000, bitrate: 10226 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 9905 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
Metadata:
creation_time : 2016-11-25T17:32:19.000000Z
handler_name : Alias Data Handler
encoder : AVC Coding
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 317 kb/s (default)
Metadata:
creation_time : 2016-11-25T17:32:19.000000Z
handler_name : Alias Data Handler
At least one output file must be specified

といったように、ffmpegのバージョン、ビルド情報とともに様々なファイル情報を表示してくれます。

 よく見るべき項目のところを赤にしましたが、例えば Duration からこのファイルは 11分23秒のファイルで bitrate は 10226  kb/s、映像は H.264圧縮(Highプロファイル、yuv420pフォーマット)、解像度は 1280x720 で映像ビットレートは 9905 kb/s、 29.97 fpsである。音声はAAC(LC)でサンプルレート 48000 Hz、音声ビットレートは 317 kb/sということなどが分かります。

 

 ちなみに、ファイルの拡張子が正しくなくても、ファイルの内容を見てきちんと扱うことができます。mp4ファイルをaviやtxtなどに拡張子を変更してffmpegに食わしてみましょう。

 

 入力ファイルの数はいくつでもよく、例えば

$ ffmpeg -i audio.wav -i video.m2v output.mpeg

というコマンドだと audio.wav という音声ファイルと  video.m2v という映像ファイルをもとに、1つの output.mpeg というファイルに音声と映像をくっつけてくれます。

 

  入出力ファイル名に - (ハイフン)を指定すると標準入出力のことを指し、パイプなどで他のコマンドと組み合わせることができます。 

$ cat test.flv | ffmpeg -i - -f avi - > test.avi

  などと指定すれば cat コマンドで FFmpeg の標準入力に input.flv のバイナリを渡し、-f で出力のタイプを avi として標準出力に出力し、リダイレクトで test.avi に保存しています。

 標準入出力で変換するときの注意事項としては、mp4 などのシークが必要になるコンテナは扱うことができません。

 

 

 映像ファイルの他にも音声や画像ファイルなども扱え、

$ ffmpeg -i input.png output.jpeg 

 などとすると、png画像をjpeg画像に変換することができます。

 

 image_%03d.png などのように input を指定すると、連番pngなども扱えるようになります。

 

 

 FFmpeg には様々なコマンドがあり、これらを組み合わせることにより、より高度な変換ができます。例えば以下のコマンドで

ffmpeg -i input.mpeg -vcodec libx264 -vf yadif -an -pass 1  -y -f mp4 /dev/null 
ffmpeg -i
input.mpeg -vcodec libx264 -vf yadif -strict -2 -b:v 1572864 -pass 2 output.mp4

 ・2パスエンコード(2回エンコードを行って、1回目で解析、2回目で高画質が変換を行う。)

・映像コーディックに libx264 を使用

インターレース解除(-vf yadif)

・映像ビットレート1.5Mbps

・1回目の出力を /dev/null に捨てる。(2パスエンコード用のファイルはまた別に作成される)

などを行えます。

 

 

 FFmpeg の強力なオプションの一つに コーディックの指定方法として copy というものがあり、これを使用するとストリームの変換を行わずに、つまり無劣化でCPU処理も食わずに高速にコンテナの差し替えなどを行うことができます。

$ ffmpeg -i input.mts -vcodec copy output.mp4

 とすると、動画コーディックがH.264なMTSを、音声だけ変換処理をしながら爆速でmp4に変換できます。

 

 -vcodec の他にも音声コーディック指定の -acodec や、-vcodecの短縮形-c:v 、

-vcodec copy -acodec copy を短縮して-codec copy 、更に-c copy と短縮できたりします。

 これを使うと、先の音声と映像を結合するサンプルを以下のように

$ ffmpeg -i audio.wav -i video.m2v -c copy output.mpeg

 とすると、本当に単純にファイルを結合するだけになり、爆速で処理が終わります。もはや HDD の R/W がボトルネック

 

 

 さて、最後に情報システム局の生中継部門っぽい使い方も紹介しましょう。 

$ ffmpeg  -re -i input.mp4  -f flv rtmp://a.rtmp.youtube.com/live2/hogehoge

 といったコマンドで、 input.mp4からリアルタイムに(-reオプション)変換を行って、YouTube Liveにrtmpで送信しています。

 あらかじめH.264AACフォーマットで映像を用意しておいて -codec copy をするとあらかじめ用意した映像を無劣化で送信することもできます。

 rtmpは入力ソースとしても扱うことができ、 入力の rtmp の情報を確認すると言った使い方もできます。

 

おわりに

 以上、かんたんな FFmpeg の使い方でした。

 多くのコマンドは実行チェックを行っていないので、もしかしたらタイポなどしているかもしれませんが、動くと思います。(たぶん、きっと、Maybe…)

 Adobe Media Encoder などの映像変換ソフトなどもありますが、個人的経験ではFFmpegのほうが性能が高いように感じます。

 ただ、良くも悪くもすべてコマンドで実行というのが初心者には覚えずらず、使いづらいところかもしれません。が、最初は馴染みのオプションから覚えていけば、きっとそのうち友だちになれるでしょう。

 今のところ、FFmpegGUIで扱えるアプリでも作ろうかなと考えているところですが、いつ作るかは未定です。