- オーディオとビデオをエンコード・デコード・トランスコードし、ストリーミングできるFFmpegフレームワークの構造と使い方を扱う
- ffmpeg、ffplay、ffprobe などのコマンドラインツールと、libavcodec、libavformat、libavfilter などの中核ライブラリの役割を具体的に説明
- AVFormatContext、AVCodecContext、AVPacket、AVFrame を中心としたストリーム解析とデコード手順を段階的に実装
- meson/ninja ビルドシステムを使ってサンプルコードを自動でダウンロード・コンパイルし、サンプルメディアファイルを解析して結果を出力
- FFmpeg の内部動作原理とデコードパイプラインの理解のための実践的な入門資料として活用可能
FFmpeg パッケージ構成
- FFmpeg は、さまざまなオーディオ・ビデオ形式をエンコード、デコード、トランスコードし、ネットワーク経由でストリーミングできるツールとライブラリの集合で構成される
-
FFmpeg ツール
- ffmpeg: コマンドラインベースのマルチメディア形式変換ツール
- ffplay: SDL と FFmpeg ライブラリをベースにしたシンプルなメディアプレーヤー
- ffprobe: マルチメディアストリームを解析するツール
-
FFmpeg ライブラリ
- libavformat: 入出力および muxing/demuxing 機能を提供
- libavcodec: エンコード/デコード 機能を提供
- libavfilter: グラフベースのフィルタによる生メディア処理
- libavdevice: 入力/出力デバイスをサポート
- libavutil: 共通マルチメディアユーティリティを提供
- libswresample: オーディオのリサンプリング、サンプル形式変換、オーディオミキシングをサポート
- libswscale: 色空間変換および画像スケーリング機能
- libpostproc: ビデオ後処理(デブロッキング、ノイズフィルタなど)機能
FFmpeg シンプルプレーヤー
- FFmpeg の基本的な使い方は、マルチメディアストリームを demux してオーディオとビデオのストリームに分離し、それを raw オーディオ/ビデオデータにデコードする流れ
-
主要構造体
- AVFormatContext: ストリームの同期、メタデータ、muxing を管理する上位構造体
- AVStream: 連続するオーディオまたはビデオストリーム
- AVCodec: データのエンコードおよびデコード方式を定義
- AVPacket: ストリーム内のエンコード済みデータ
- AVFrame: デコード済みの生ビデオフレームまたはオーディオサンプル
-
ストリーム解析と demux の流れ
avformat_alloc_context() で AVFormatContext のメモリを確保
avformat_open_input() でマルチメディアファイルを開く
avformat_find_stream_info() でファイル内のストリーム情報を解析
- 各ストリームの time base、フレームレート、開始時刻、長さ、タイプ、FourCC コードを出力
avformat_close_input() でファイルを閉じてメモリを解放
-
コーデック探索と初期化
avcodec_find_decoder() で AVStream の codec ID に合うデコーダを探索
- ビデオストリームでは 解像度(width, height)、オーディオストリームでは チャンネル数とサンプルレート を出力
avcodec_alloc_context3() で AVCodecContext を生成
avcodec_parameters_to_context() でストリームのコーデックパラメータをデコーダコンテキストに適用
avcodec_open2() でデコーダを開く
-
パケット読み取りとデコード
AVPacket と AVFrame 構造体をそれぞれエンコード済みパケットとデコード済みフレーム保存用に確保
av_read_frame() で入力ファイルからパケットを順次読み取る
- パケットの stream_index によってどのストリーム由来かを識別
- 選択したビデオストリーム(
first_video_stream_index)のパケットだけをデコーダに送る
avcodec_send_packet() でパケットをデコーダに渡す
avcodec_receive_frame() でデコード済みフレームを繰り返し受け取る
- 各フレームの 番号、タイプ(I/P/B)、フォーマット、PTS、キーフレームかどうかを出力
av_packet_unref() でパケットメモリを再利用
- すべての処理が終わったら
av_packet_free()、av_frame_free()、avcodec_free_context()、avformat_close_input() でメモリを解放
-
実行と結果例
- サンプルコードは GitHub リポジトリ で提供
- meson と ninja を使ってビルド可能(
pip3 install meson ninja)
meson setup build 実行時に FFmpeg を自動でダウンロードして設定
ninja -C build でビルド後、./build/ffmpeg-101 sample.mp4 で実行
- 実行結果として、ファイル形式、ストリーム情報(ビデオ/オーディオ)、コーデック、解像度、サンプルレート、各パケットの PTS とデコード済みフレーム情報が出力される
-
出力例の要約
- ビデオストリーム: H.264 (avc1)、解像度 206x80、フレームレート 30fps
- オーディオストリーム: AAC (mp4a)、2 チャンネル、44.1kHz
- 各パケットの PTS と フレームタイプ(I/P) が順に表示され、デコード処理がコンソールに出力される
ビルドと実行環境
- 必要なツール: Python、pip、meson、ninja
- インストールコマンド:
pip3 install meson ninja
-
ビルド手順
- サンプルの圧縮ファイルを
ffmpeg-101 フォルダに展開
meson setup build を実行
ninja -C build でビルド
./build/ffmpeg-101 sample.mp4 で実行
- システムに FFmpeg がインストールされていない場合は自動でダウンロードおよび構成される
1件のコメント
Hacker Newsのコメント
FFmpegとlibavの内部動作を深く理解したい人には、Leandro Moreiraのチュートリアルを強く勧める
個人的には、これまで見た中で最も完全で明快な説明
FFmpeg-libav チュートリアルのリンク
もう ffmpeg 101 なのかと驚いた。ffmpeg 8 が出たのは昨日のことのように感じる
別のガイドも共有する
HNの関連ガイドへのリンク
FFmpeg、本当に大好きなツールだ
素晴らしい ffmpeg 入門資料だった。感謝する
ffmpeg はまさにスーパーパワーだ
私は複数の動画断片を1つの再生可能な形に組み立てるとき、いつも使っている