PLAY DEVELOPERS BLOG

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

【入門編】いつかどこかで使えるかもしれない FFmpeg コマンドの紹介

みなさん、こんにちは。ソリューション技術部の叶です。

今回は、FFmpeg に関するテックブログをお届けします。 PLAY の開発において、動画ファイルは、とても重要な役割を果たしています。私は日々、FFmpeg で生成した動画ファイルを使い、開発や検証をしています。そこで、今回は、私がよく使用する便利な FFmpeg のコマンドを紹介したいと思います。なお、本記事では Caminandes の動画ファイルを動画素材として使用しています。*1

FFmpeg とは何か?

FFmpeg は、オープンソースのマルチメディアフレームワークであり、動画や音声のエンコード、デコード、変換処理などの多くのマルチメディアの処理を行うことができるソフトウエアです。FFmpeg は、コマンドラインツールとして提供されており、さまざまなプラットフォーム(Windows、macOS、Linuxなど)で動作します。ffmpeg.org

FFmpeg の主な機能

  1. 動画や音声のエンコードとデコード:多くの動画や音声コーデックのエンコード(圧縮)とデコード(展開)をサポートしています。(ただし、一部のコーデック、例えば、H.264、H.265、VP9 などは、FFmpeg 単体ではエンコードすることができず、対応するライブラリをリンクして FFmpeg をビルドする必要があります。)
  2. フォーマット変換:異なるファイルフォーマットに動画や音声を変換することができます。
  3. 動画の加工:動画や音声に対してフィルタを適用し、色調補正、サイズの変換、ウォーターマークの追加などの処理を行うことができます。

基本的な使い方

FFmpeg はコマンドラインツールであるため、ターミナルやコマンドプロンプトで、コマンドを入力して使用します。基本的な使い方は以下のようになります。

$ ffmpeg [グローバルオプション] [入力ファイルのオプション] -i [入力ファイル] [出力ファイルのオプション] [出力ファイル]
  • 入力ファイル:変換や処理を行いたい動画や音声ファイルを指定します。
  • 出力ファイル:処理結果を保存するファイル名を指定します。
  • オプション:具体的な処理内容を指定するためのもので、例えば、動画を特定のコーデックでエンコードしたり、音声を別のフォーマットで保存したりする際に使用します。なお、オプションには、グローバルオプションと入力ファイルのオプション、出力ファイルのオプションの 3 種類があります。同じオプションでも、どのオプションとして指定するかで、FFmpeg の動作が変わってきます。

解像度の変換

まずは、FFmpeg の操作に慣れるという意味で、解像度を変換してみます。

例えば、元の動画の解像度が 1080p(1920px x 1080px)であり、アスペクト比が 16:9 の動画ファイルを、720p(1280px x 720px)に変換したいときは、以下のようなコマンドを使用します。

$ ffmpeg -i input.mp4 -vf "scale=1280:-1" output.mp4

これにより、input.mp4 の解像度が 720p に変換され、output.mp4 が出力されます。ここでの注意点は、scale フィルタを使用するときは、入力ファイルのアスペクト比(幅と高さの比)を維持する必要があることです。変換時にアスペクト比を維持しないと、元の動画が引き伸ばされてしまいます。したがって、解像度を変換するときは、入力ファイルのアスペクト比を維持するように、FFmpeg のオプションを指定します。FFmpeg で入力ファイルのアスペクト比を維持して、拡大縮小する場合は、scale フィルタの一方のパラメータを -1 にします。この指定により、他方のパラメータに基づいて自動的にサイズが計算され、アスペクト比が保たれます。scale オプションの詳細については、FFmpeg の公式ドキュメントを参照してください。*2

長尺の動画ファイルの生成

PLAY では動画ファイルを処理するシステムを開発することが多く、例えば検証時に長尺のファイルをトランスコードし、再生ができるかという検証をすることがあります。そのため、長尺の動画ファイルが必要になる場合があり、そのような時に便利な FFmpeg のオプションを紹介します。

生成方法としては、動画ファイルを連結し、動画尺が 1 時間になるように動画ファイルを切り取ります。

$ ffmpeg -stream_loop -1 -t 3600 -i input.mp4 -c copy out.mp4

コマンドの詳細

  • -stream_loop -1:このオプションは、入力ファイルのループ回数を指定します。-1 を指定すると、無限にループを繰り返します。今回の場合は、入力ファイルを無限にループさせて、動画を連結させます。*3
  • -t 秒数:このオプションは FFmpeg コマンドラインツールの中で、入力ファイルを読み取る時間の長さを指定するオプションで、秒単位で指定します。3600 と指定した場合は、1 時間( 3,600 秒 = 60 秒 * 60 分)の動画を読み取ります。*4
  • -c copy:このオプションを使用することで、デコード処理とエンコード処理をスキップすることができます。これにより、処理時間が短縮されます。今回、入力ファイルの変換は不要なため、デコード処理やエンコード処理をスキップします。*5

現在の再生時間を動画に表示する

動画に現在の再生時間を表示する方法を紹介します。現在の再生時間を表示するには、FFmpeg の drawtext フィルタを使用します。

動画の中央の下部に現在の再生時間を表示するには、以下のようなコマンドを使用します。

$ ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf: text='%{pts\:hms}': x=(w-tw)/2: y=h-50: fontsize=50: fontcolor=white" output.mp4

コマンドの詳細

  • -vf:ビデオフィルタチェーンを指定するオプションです。
    • drawtext:テキストを動画に描画するためのフィルタです。
    • fontfile=/path/to/font.ttf:使用するフォントファイルのパスを指定します。適切なパスに書き換えてください。
    • text='%{pts\:hms}':表示するテキストの内容です。ここでは変数 %{pts\:hms} を使用して、再生時間を「 hh:mm:ss 」形式で表示しています。
    • x=(w-tw)/2:テキストを描画する X 座標(横方向)を指定します。w は入力ファイルの幅を示し、tw は描画するテキストの幅を示します。ここでは (w-tw)/2 を指定することで、左右の中央に配置しています。
    • y=h-50:テキストを描画する Y 座標(縦方向)を指定します。h は入力ファイルの高さを示し、h-50 と指定することで、入力ファイルの下部から 50 ピクセル上の位置にテキストを描画しています。
    • fontsize=50:フォントのサイズを 50 にします。
    • fontcolor=white:フォントの色を白にします。

上記のコマンドの結果、添付画像のように映像の中央の下部に、タイムコードが表示されます。

タイムコードが埋め込まれた動画

drawtext フィルタではさまざまなカスタマイズが可能です。例えば、文字の影をつけたり、文字の背景色を設定したり、文字の透明度を調整したりできます。詳細なオプションについては、FFmpeg の公式ドキュメントを参照してください。*6

サムネイル画像の生成

次に動画からサムネイル画像を生成する方法を紹介します。

指定した秒数からサムネイルを生成する方法

この方法は、あらかじめサムネイルに切り出す部分が、動画のどの位置か決まっている場合に使用します。下記に記載しているコマンドは、動画の中で先頭から、3 秒目の位置を切り出すように指定しています。出力結果に添付しているように、サムネイルに表示されているタイムスタンプが、指定した通り、00:00:03 になっています。

$ ffmpeg -ss 00:00:03 -i input_video.mp4 -vframes 1 thumbnail.jpg

コマンドの詳細

  • -ss 再生位置:サムネイルの生成位置を動画の時間軸で指定します。この例では、開始から 3 秒目の位置からサムネイルを生成しています。-ss オプションは、入力ファイルのオプションとして( -i の前に)使用する場合と、出力ファイルのオプションとして( -i の後ろに)使用する場合で、FFmpeg の動作が変わります。出力ファイルのオプションとして使用する場合、FFmpeg は入力ファイルをデコードしてからシークするため、入力ファイルの動画尺が長い場合、サムネイル生成の処理時間が長くなります。しかし、入力ファイルのオプションとして使用する場合、FFmpeg は入力ファイルのすべてをデコードせずに、シークするため、サムネイル生成の処理時間が短くなります。*7
  • -vframes 1 :1 フレームだけを抽出するオプションです。*8

出力結果

出力したサムネイル画像

等間隔でサムネイルを生成する方法

サムネイルの生成時に、動画のどの地点をサムネイルにするか決まっていない場合があります。そのような時は、下記のコマンドを使用して、動画ファイルから等間隔でサムネイルを生成します。なお、下記のコマンドでは、10 秒ごとにサムネイルを生成しています。

$ ffmpeg -i input_video.mp4 -vf "fps=1/10,scale=320:-1" thumbnails_%03d.jpg

コマンドの詳細

  • fps=1/10:サムネイルを何秒間に 1 枚生成するかを指定します。fps=1/10 は、10 秒ごとに 1 枚のサムネイルを生成します。
  • scale=320:-1:サムネイルのサイズを指定します。アスペクト比を維持する場合は、高さを -1 と指定します。今回は、幅を 320px と指定し、アスペクト比が 16:9 の場合は、高さが 180px に変換されます。
  • thumbnails_%03d.jpg:生成されるサムネイルのファイル名と拡張子を指定します。%03d は連番の 3 桁の数字を表し、この指定により、生成されるサムネイルの画像のファイル名が、「thumbnails_001.jpg、thumbnails_002.jpg ...」になります。
    10秒間隔で生成されたサムネイル

ウォーターマークの挿入

動画にウォーターマークを挿入することは、コンテンツの所有権を示すために使用されることがあります。多くの場合、半透明なテキストやロゴ画像などを動画の上に表示します。以下では、FFmpeg を使って動画にウォーターマークを挿入する方法を紹介します。

左上に配置する場合

$ ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" output.mp4

左上にウォーターマークを表示
右下に配置する場合

$ ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=W-w-10:H-h-10" output.mp4 

右下にウォーターマークを表示

中央に配置する場合

$ ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=(W-w)/2:(H-h)/2" output.mp4

中央にウォーターマークを表示

コマンドの詳細

  • -i 動画ファイル名:ウォーターマークを挿入したい動画ファイル名を指定します。
  • -i 画像ファイル名:ウォーターマークとして使用する画像ファイル名(ロゴなど)を指定します。
  • overlay=x:y:overlay フィルタは、1つ目の入力ファイル(背景動画)の上に、2つ目の入力ファイル(通常はウォーターマーク画像)を重ねるために使用します。x には、2つ目の入力ファイルの X 座標を、y には2つ目の入力ファイルの Y 座標を指定します。なお、overlay フィルターには、下記の変数を使用することができます。*9
    • W, main_w:1 つ目の入力の幅
    • H, main_h:1 つ目の入力の高さ
    • w, overlay_w:2 つ目の入力の幅
    • h, overlay_h:2 つ目の入力の高さ

終わりに

本記事では、解像度の変換、長尺の動画ファイルの生成、再生時間の表示、サムネイル生成、ウォーターマークの挿入方法など、FFmpeg のさまざまな使い方を取り上げました。

今回紹介した FFmpeg の機能は、ほんの一部であり、FFmpeg にはもっと多くのメディア処理に関する機能があります。本ブログ以外にも、公式ドキュメントや FFmpeg を取り上げた多くの記事があるので、ぜひそちらにも目を通していただき、FFmpeg の可能性を感じていただければと思います。

本記事では、開発時や検証時に必要そうになりそうな FFmpeg の機能をメインに紹介しました。本記事が、皆さんの何かの業務等で役立つ情報になれば幸いです。