🎬

FFmpeg — 25年間メディア世界を支えてきたスイスアーミーナイフ

アーキテクチャ、コーデック抽象化、フィルターチェーン、ハードウェアアクセラレーションまで — FFmpeg内部構造の解剖

FFmpegとは何か

FFmpegはCLIツールであり、ライブラリの集合体だ。「FF」はFast Forward、「mpeg」は動画規格グループ名に由来する。2000年にFabrice Bellardが作り、以降Michael Niedermayerをはじめ数百人の貢献者が開発を続けている。

一言でまとめると:ほぼすべてのメディアフォーマットを入力し、ほぼすべてのメディアフォーマットで出力できる。

ffmpeg -i input.mov -c:v libx264 -c:a aac output.mp4

この1行でMOVファイルをH.264ビデオ+AACオーディオのMP4に変換する。

コアコンポーネント

FFmpegプロジェクトは複数のバイナリとライブラリで構成される。

バイナリ:

  • ffmpeg — メディア変換・エンコードのメインCLI

  • ffprobe — メディアファイルのメタデータ・ストリーム情報照会

  • ffplay — SDLベースの簡易メディアプレーヤー

ライブラリ(libav*):

  • libavcodec — コーデック実装(H.264、HEVC、VP9、AV1、AAC、Opus等)

  • libavformat — コンテナフォーマット処理(MP4、MKV、WebM、FLV、HLS等)

  • libavfilter — フィルターグラフ(スケーリング、クロップ、オーバーレイ、色補正等)

  • libavutil — 共通ユーティリティ(数学、ピクセルフォーマット、エラーコード等)

  • libswscale — ピクセルフォーマット変換+スケーリング

  • libswresample — オーディオリサンプリング+フォーマット変換

  • libavdevice — キャプチャデバイスI/O(カメラ、マイク、画面キャプチャ)

処理パイプライン

FFmpegのデータフロー:

入力 → デマックス → デコード → フィルタリング → エンコード → マックス → 出力

  1. Demuxing(libavformat)— コンテナから個別ストリーム(ビデオ、オーディオ、字幕)を分離。圧縮パケット単位で抽出
  2. Decoding(libavcodec)— 圧縮パケットをrawフレームにデコード。ビデオはYUV/RGBピクセルデータ、オーディオはPCMサンプルに変換
  3. Filtering(libavfilter)— rawフレームにフィルターチェーン適用。スケーリング、クロップ、色補正、テキストオーバーレイ、ノイズ除去等
  4. Encoding(libavcodec)— 処理済みフレームを再圧縮。ターゲットコーデック・ビットレート・品質設定に従いエンコード
  5. Muxing(libavformat)— エンコード済みストリームをコンテナに格納し出力ファイルに書き込み

ストリームコピーモード(-c copy)ではデコード/エンコードをスキップし、パケットをそのままリマックスする。品質劣化なしにコンテナだけ変えたい時に使う。

コーデック抽象化構造

libavcodecの核心はAVCodec構造体だ。すべてのコーデック(H.264、HEVC、VP9、AV1、...)が同一インターフェースを実装する。

typedef struct AVCodec {
    const char *name;
    enum AVMediaType type;
    enum AVCodecID id;
    int (*init)(AVCodecContext *);
    int (*encode2)(AVCodecContext *, AVPacket *, const AVFrame *, int *);
    int (*decode)(AVCodecContext *, AVFrame *, int *, AVPacket *);
    int (*close)(AVCodecContext *);
} AVCodec;

同じコーデックID(例:H.264)に複数の実装が存在できる:

  • libx264 — ソフトウェアエンコーダ(CPU)

  • h264_nvenc — NVIDIA GPUハードウェアエンコーダ

  • h264_qsv — Intel Quick Sync

  • h264_vaapi — VA-API(Linux)

  • h264_videotoolbox — macOSハードウェアエンコーダ

ユーザーは-c:v libx264のようにエンコーダ名を変えるだけ。パイプラインの残りは同一に動作する。

フィルターグラフ

libavfilterは有向グラフ構造でフィルターを接続する。

ffmpeg -i input.mp4 -vf "scale=1280:720,fps=30,eq=brightness=0.1" output.mp4

3つのフィルターがチェーン接続:
1. scale — 解像度を1280x720に調整
2. fps — フレームレートを30fpsに変換
3. eq — 明るさを0.1上げる

複雑なフィルターグラフは複数の入出力を持てる:

ffmpeg -i main.mp4 -i logo.png \
  -filter_complex "[0:v][1:v]overlay=10:10[out]" \
  -map "[out]" output.mp4

メイン映像にロゴをオーバーレイする構造。

ハードウェアアクセラレーション

FFmpegはhwaccel APIでハードウェアアクセラレーションを抽象化する。

  • NVIDIA — NVDEC(デコード)+ NVENC(エンコード)+ CUDAフィルター

  • Intel — QSV(Quick Sync Video)

  • AMD — AMF(Advanced Media Framework)

  • VA-API — Linux汎用ハードウェアアクセラレーション

  • VideoToolbox — macOS/iOS

  • Vulkan — クロスプラットフォームGPUコンピューティング

GPUデコード→GPUフィルター→GPUエンコードのパイプラインを構成すれば、フレームがGPUメモリから出ないためCPU-GPU間データ転送オーバーヘッドがなくなる。

誰がFFmpegを使っているか

事実上、メディアを扱うほぼすべてのサービスとツール。

  • YouTube — アップロード映像のトランスコーディング

  • Netflix — コンテンツエンコーディングパイプライン

  • Meta — 1日数百億回実行(VOD+ライブストリーミング)

  • VLC — 再生エンジンの中核

  • OBS Studio — ストリーミング/録画

  • HandBrake — デスクトップトランスコーディング

  • Plex/Jellyfin — メディアサーバートランスコーディング

FFmpegなしに現代のメディアインフラは回らない。25年以上にわたりCで書かれた300万行以上のコードベースがこのすべてを支えている。

動作フロー

1

Demuxing — コンテナからビデオ・オーディオ・字幕ストリームを分離

2

Decoding — 圧縮パケットをrawフレーム(YUV/PCM)にデコード

3

Filtering — フィルターグラフでスケーリング・クロップ・色補正等を適用

4

Encoding — 処理済みフレームをターゲットコーデックで再圧縮

5

Muxing — エンコード済みストリームをコンテナ(MP4/MKV/WebM)に格納し出力

ユースケース

メディアトランスコーディング — フォーマット・コーデック・解像度・ビットレート変換 ライブストリーミング — RTMP/HLS/DASH入出力+リアルタイムエンコード メディア分析 — ffprobeでコーデック・解像度・フレームレート・ビットレート照会