FFmpeg 画質評価の作法:VMAF/SSIM/PSNR を揃えて測るベンチ手順
動画エンコード後の品質評価、どのように行っていますか? 目視確認だけでは主観的になりがちですし、複数の設定を比較する際には客観的な指標が欠かせません。 FFmpeg にはVMAF(Video Multimethod Assessment Fusion)、SSIM(Structural Similarity Index)、**PSNR(Peak Signal-to-Noise Ratio)**という 3 つの主要な画質評価指標が組み込まれており、これらを適切に活用することで、科学的かつ再現性のある品質評価が可能になるのです。
本記事では、FFmpeg を使った画質評価の基礎から実践的なベンチマーク手順まで、初心者の方にもわかりやすく解説いたします。 これらの指標を正しく理解し、適切に使い分けることで、エンコード設定の最適化や品質管理が格段に向上しますよ。
背景
動画品質評価が必要な理由
動画配信サービスやストリーミングプラットフォームが普及する中、限られた帯域幅で高品質な映像を届けることが求められています。 エンコード設定を変更すると、ファイルサイズは削減できますが、同時に画質も劣化する可能性があります。
このトレードオフを最適化するためには、客観的な品質指標による評価が不可欠です。
以下の図は、動画エンコードと品質評価の関係性を示しています。
mermaidflowchart TD
original["オリジナル<br/>動画ファイル"]
encode["エンコード処理<br/>(FFmpeg)"]
compressed["圧縮された<br/>動画ファイル"]
metrics["品質評価指標<br/>(VMAF/SSIM/PSNR)"]
analysis["品質分析<br/>結果"]
original -->|入力| encode
encode -->|出力| compressed
original -->|参照| metrics
compressed -->|比較| metrics
metrics -->|計算| analysis
このように、オリジナル動画と圧縮後の動画を比較することで、エンコードによる品質劣化を定量的に測定できます。
3 つの評価指標の位置づけ
VMAF、SSIM、PSNR はそれぞれ異なるアプローチで画質を評価します。 PSNR は最も古典的で計算が高速ですが、人間の視覚特性を考慮していません。 SSIM は構造的な類似性を評価し、PSNR よりも人間の知覚に近い結果を提供します。
VMAF は機械学習ベースの最新指標で、Netflix が開発した最も人間の主観評価に近い指標として注目されています。
以下の表は、3 つの指標の特徴を比較したものです。
| # | 指標 | 開発元 | アプローチ | 計算速度 | 人間の知覚との相関 | スコア範囲 |
|---|---|---|---|---|---|---|
| 1 | PSNR | - | ピクセル差分 | ★★★ | ★ | 0〜∞ dB(高いほど良い) |
| 2 | SSIM | テキサス大学 | 構造的類似性 | ★★ | ★★ | -1〜1(1 が完全一致) |
| 3 | VMAF | Netflix | 機械学習 | ★ | ★★★ | 0〜100(高いほど良い) |
これらを組み合わせて使用することで、多角的な品質評価が可能になります。
課題
各指標の特性と限界
画質評価において、単一の指標だけに依存することは危険です。 各指標には得意・不得意があり、動画の内容やエンコード方式によって評価結果が大きく異なることがあるからです。
PSNR の課題:人間の視覚との乖離
PSNR はピクセル単位の誤差を測定するため、計算は高速ですが人間の視覚特性を考慮していません。 例えば、高周波成分(細かいディテール)の劣化と低周波成分(大まかな構造)の劣化を同等に扱ってしまいます。
その結果、PSNR が高くても主観的には画質が悪く感じられるケースが発生します。
SSIM の課題:動画特有の問題への対応
SSIM は静止画の構造的類似性を評価する指標として設計されました。 動画特有の時間的な変化(モーションブラー、動きベクトルなど)を十分に考慮できていません。
また、明るさやコントラストの変化には比較的寛容ですが、色相の変化には敏感ではないという特性があります。
VMAF の課題:計算コストと環境依存
VMAF は機械学習モデルを使用するため、計算コストが高く、大量の動画を評価する際には時間がかかります。 また、モデルファイルの準備や FFmpeg のビルド設定によっては利用できない環境もあるでしょう。
さらに、学習データに偏りがある場合、特定の動画タイプでは正確な評価ができない可能性も指摘されています。
以下の図は、各指標の評価における課題を示しています。
mermaidflowchart LR
video["評価対象<br/>動画"]
subgraph psnr_box["PSNR評価"]
psnr_calc["ピクセル差分<br/>計算"]
psnr_issue["課題:視覚特性<br/>無視"]
end
subgraph ssim_box["SSIM評価"]
ssim_calc["構造的類似性<br/>計算"]
ssim_issue["課題:時間的<br/>変化に弱い"]
end
subgraph vmaf_box["VMAF評価"]
vmaf_calc["機械学習<br/>モデル"]
vmaf_issue["課題:計算<br/>コスト高"]
end
video --> psnr_calc
video --> ssim_calc
video --> vmaf_calc
psnr_calc --> psnr_issue
ssim_calc --> ssim_issue
vmaf_calc --> vmaf_issue
図で理解できる要点:
- 各指標は異なる計算方式を採用している
- それぞれ固有の課題や限界がある
- 単一指標だけでは不十分な理由が視覚化されている
評価環境の統一が困難
正確なベンチマークを行うには、評価条件を統一する必要があります。 しかし、動画ファイルのフレームレート、解像度、ビット深度、色空間などのパラメータが異なると、正確な比較ができません。
また、FFmpeg のバージョンやビルドオプション、使用するフィルターチェーンによっても結果が変わってしまうのです。
解決策
複合的な評価アプローチ
単一指標の限界を克服するには、VMAF、SSIM、PSNR の 3 つを同時に測定し、総合的に判断することが重要です。 それぞれの指標が異なる側面から画質を評価するため、3 つの結果を比較することで、より正確な品質評価が可能になります。
推奨される評価基準は以下のとおりです。
| # | 指標 | 優秀 | 良好 | 許容範囲 | 要改善 |
|---|---|---|---|---|---|
| 1 | VMAF | 95 以上 | 85〜94 | 70〜84 | 70 未満 |
| 2 | SSIM | 0.98 以上 | 0.95〜0.97 | 0.90〜0.94 | 0.90 未満 |
| 3 | PSNR | 45dB 以上 | 40〜44dB | 35〜39dB | 35dB 未満 |
FFmpeg による統一的な測定環境
FFmpeg は動画処理の標準ツールとして、これら 3 つの指標すべてをサポートしています。 同一のツールで評価することで、環境の統一が容易になり、再現性の高いベンチマークが実現できるのです。
測定の基本的な流れは、以下のようになります。
mermaidflowchart TD
start["測定開始"]
prepare["動画ファイル<br/>準備"]
check["フォーマット<br/>確認"]
normalize["正規化処理<br/>(必要に応じて)"]
subgraph measurement["並列測定"]
vmaf_measure["VMAF測定"]
ssim_measure["SSIM測定"]
psnr_measure["PSNR測定"]
end
collect["結果収集"]
analyze["総合分析"]
report["レポート<br/>生成"]
start --> prepare
prepare --> check
check --> normalize
normalize --> measurement
measurement --> collect
collect --> analyze
analyze --> report
図で理解できる要点:
- 測定前の準備フェーズで動画を正規化する
- 3 つの指標は並列に測定可能である
- 結果を収集して総合的に分析する流れが明確になっている
自動化スクリプトの活用
手動で 3 つの指標を個別に測定するのは効率的ではありません。 シェルスクリプトや Python スクリプトを使って測定プロセスを自動化することで、作業時間を大幅に削減できます。
また、結果を JSON 形式や CSV 形式で保存することで、後から分析や可視化が容易になるでしょう。
具体例
環境準備
FFmpeg のインストール確認
まず、FFmpeg が VMAF サポート付きでインストールされているか確認しましょう。
bash# FFmpegのバージョンとビルド設定を確認
ffmpeg -version
出力結果の中に --enable-libvmaf が含まれていれば、VMAF 測定が可能です。
もし含まれていない場合は、VMAF サポート付きで FFmpeg を再ビルドする必要があります。
VMAF モデルファイルの準備
VMAF を使用するには、モデルファイルが必要です。 一般的には、以下のパスにインストールされています。
bash# Homebrewでインストールした場合(macOS)
ls /opt/homebrew/share/libvmaf/model/
# Linuxの場合
ls /usr/share/model/vmaf/
vmaf_v0.6.1.json または vmaf_4k_v0.6.1.json などのファイルが存在することを確認してください。
測定用の動画ファイル準備
オリジナル動画とエンコード済み動画
ベンチマークには、比較元となるオリジナル動画(参照動画)と、エンコード後の動画(評価対象)が必要です。
bash# サンプル動画をダウンロード(例)
wget https://example.com/sample_original.mp4 -O original.mp4
# エンコード設定でテスト動画を作成
ffmpeg -i original.mp4 -c:v libx264 -crf 23 -preset medium encoded_crf23.mp4
ここでは、H.264 コーデックで CRF(Constant Rate Factor)23 という標準的な品質設定でエンコードしています。 CRF 値は 0〜51 の範囲で、値が小さいほど高品質(大容量)、大きいほど低品質(小容量)になります。
動画フォーマットの統一
正確な比較のため、両動画のフレームレート、解像度、色空間を統一する必要があります。
bash# 動画情報を確認
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,r_frame_rate,pix_fmt \
-of default=noprint_wrappers=1 original.mp4
このコマンドで、動画の幅・高さ・フレームレート・ピクセルフォーマットが確認できます。 もし参照動画と評価対象動画で異なる場合は、前処理で統一しましょう。
bash# フォーマット統一の例(1920x1080、30fps、yuv420pに変換)
ffmpeg -i original.mp4 -vf scale=1920:1080,fps=30 \
-pix_fmt yuv420p original_normalized.mp4
PSNR 測定の実行
基本的な PSNR 測定コマンド
PSNR は最も高速に計算できる指標です。
FFmpeg の psnr フィルターを使用します。
bash# PSNR測定コマンド
ffmpeg -i encoded_crf23.mp4 -i original.mp4 \
-filter_complex "psnr=stats_file=psnr_output.log" \
-f null -
このコマンドの構造を説明します。
最初の -i オプションで評価対象動画を指定し、2 番目の -i で参照動画(オリジナル)を指定します。
-filter_complex オプションで psnr フィルターを適用し、結果を psnr_output.log に保存しています。
-f null - は出力動画を生成せず、処理だけを実行するための指定です。
PSNR 結果の読み方
測定が完了すると、ログファイルに各フレームの PSNR 値が記録されます。
bash# ログファイルの確認
cat psnr_output.log
出力例:
textn:1 mse_avg:12.34 mse_y:11.23 mse_u:13.45 mse_v:12.89 psnr_avg:37.21 psnr_y:37.63 psnr_u:36.84 psnr_v:37.03
n:2 mse_avg:11.87 mse_y:10.98 mse_u:12.76 mse_v:12.01 psnr_avg:37.38 psnr_y:37.72 psnr_u:37.07 psnr_v:37.33
各項目の意味は以下のとおりです。
n: フレーム番号mse_avg: 平均二乗誤差(全チャンネル)psnr_avg: 平均 PSNR 値(全チャンネル、最も重要な値)psnr_y: 輝度(Y)チャンネルの PSNRpsnr_u,psnr_v: 色差(U, V)チャンネルの PSNR
PSNR 平均値の抽出
全フレームの平均 PSNR 値を算出するには、ログファイルの最終行を確認するか、以下のコマンドで計算します。
bash# 平均PSNR値を抽出(Linuxの場合)
grep "psnr_avg" psnr_output.log | \
awk '{sum+=$6; count++} END {print "Average PSNR:", sum/count, "dB"}'
このコマンドは、ログファイルから psnr_avg を含む行を抽出し、6 番目のフィールド(PSNR 値)の平均を計算します。
40dB 以上であれば良好な品質と判断できるでしょう。
SSIM 測定の実行
基本的な SSIM 測定コマンド
SSIM は構造的類似性を評価します。
FFmpeg の ssim フィルターを使用します。
bash# SSIM測定コマンド
ffmpeg -i encoded_crf23.mp4 -i original.mp4 \
-filter_complex "ssim=stats_file=ssim_output.log" \
-f null -
コマンド構造は PSNR と同様で、フィルター名を ssim に変更するだけです。
SSIM もフレームごとの値がログファイルに記録されます。
SSIM 結果の読み方
SSIM ログファイルの出力例:
textn:1 Y:0.9876 U:0.9823 V:0.9845 All:0.9851 (14.27)
n:2 Y:0.9889 U:0.9834 V:0.9856 All:0.9863 (14.63)
各項目の意味は以下のとおりです。
n: フレーム番号Y,U,V: 各チャンネルの SSIM 値(0〜1、1 が完全一致)All: 全チャンネルの平均 SSIM 値(最も重要な値)- 括弧内の数値: SSIM 値を dB 換算した値
SSIM 平均値の抽出
全フレームの平均 SSIM 値を算出します。
bash# 平均SSIM値を抽出
grep "All:" ssim_output.log | \
awk '{sum+=$8; count++} END {print "Average SSIM:", sum/count}'
SSIM 値は 0 から 1 の範囲で、0.95 以上であれば高品質と判断できます。 0.90 未満の場合は、視覚的に劣化が認識できるレベルでしょう。
VMAF 測定の実行
基本的な VMAF 測定コマンド
VMAF は最も人間の知覚に近い評価を提供します。
libvmaf フィルターを使用し、モデルファイルを指定します。
bash# VMAF測定コマンド(macOSの場合)
ffmpeg -i encoded_crf23.mp4 -i original.mp4 \
-filter_complex "[0:v]setpts=PTS-STARTPTS[dist];[1:v]setpts=PTS-STARTPTS[ref];[dist][ref]libvmaf=model_path=/opt/homebrew/share/libvmaf/model/vmaf_v0.6.1.json:log_path=vmaf_output.json:log_fmt=json" \
-f null -
このコマンドは少し複雑なので、部分ごとに説明します。
まず、setpts=PTS-STARTPTS で両動画のタイムスタンプを 0 から開始するように正規化しています。
これにより、フレームの同期が正確になります。
次に、libvmaf フィルターで以下のパラメータを指定しています。
model_path: VMAF モデルファイルのパスlog_path: 結果を保存する JSON ファイルのパスlog_fmt=json: 出力フォーマットを JSON に指定
Linux での実行例
Linux の場合は、モデルファイルのパスが異なります。
bash# VMAF測定コマンド(Linuxの場合)
ffmpeg -i encoded_crf23.mp4 -i original.mp4 \
-filter_complex "[0:v]setpts=PTS-STARTPTS[dist];[1:v]setpts=PTS-STARTPTS[ref];[dist][ref]libvmaf=model_path=/usr/share/model/vmaf/vmaf_v0.6.1.json:log_path=vmaf_output.json:log_fmt=json" \
-f null -
環境に応じて、モデルファイルのパスを適切に変更してください。
VMAF 結果の読み方
測定が完了すると、JSON 形式の結果ファイルが生成されます。
bash# VMAF結果の確認
cat vmaf_output.json
JSON ファイルには、フレームごとの詳細な VMAF スコアが記録されています。 重要なのは、全体の平均 VMAF 値です。
bash# 平均VMAF値を抽出(jqコマンドを使用)
jq '.pooled_metrics.vmaf.mean' vmaf_output.json
もし jq がインストールされていない場合は、以下のコマンドでインストールできます。
bash# macOS
brew install jq
# Ubuntu/Debian
sudo apt install jq
VMAF 値は 0 から 100 の範囲で、以下のように解釈します。
| # | VMAF 範囲 | 品質評価 | 視聴体験 |
|---|---|---|---|
| 1 | 95〜100 | 非常に優秀 | オリジナルとほぼ区別不可 |
| 2 | 85〜94 | 優秀 | わずかな劣化のみ |
| 3 | 70〜84 | 良好 | 許容範囲内の品質 |
| 4 | 50〜69 | 普通 | 劣化が認識できる |
| 5 | 50 未満 | 要改善 | 明確な品質低下 |
複数の設定を一括ベンチマーク
実際のエンコード最適化では、複数の CRF 値やプリセットを比較する必要があります。 以下は、自動化スクリプトの例です。
ベンチマークスクリプト(Bash)
bash#!/bin/bash
# FFmpeg画質評価ベンチマークスクリプト
# 設定
ORIGINAL="original.mp4"
RESULTS_DIR="benchmark_results"
VMAF_MODEL="/opt/homebrew/share/libvmaf/model/vmaf_v0.6.1.json"
# 結果ディレクトリ作成
mkdir -p "$RESULTS_DIR"
このスクリプトの冒頭部分では、オリジナル動画のパス、結果保存ディレクトリ、VMAF モデルのパスを定義しています。 環境に応じて、これらの変数を変更してください。
テストパターンの定義
bash# テストするCRF値の配列
CRF_VALUES=(18 23 28 33)
# テストするプリセット
PRESETS=("fast" "medium" "slow")
ここでは、4 つの異なる CRF 値(18, 23, 28, 33)と 3 つのプリセット(fast, medium, slow)を定義しています。 これにより、合計 12 通りの組み合わせをテストできます。
エンコードループ
bash# 各設定でエンコードと評価を実行
for preset in "${PRESETS[@]}"; do
for crf in "${CRF_VALUES[@]}"; do
echo "Testing: CRF=$crf, Preset=$preset"
# エンコード
OUTPUT="${RESULTS_DIR}/encoded_${preset}_crf${crf}.mp4"
ffmpeg -i "$ORIGINAL" -c:v libx264 \
-crf "$crf" -preset "$preset" \
-y "$OUTPUT"
done
done
このループでは、各プリセットと CRF 値の組み合わせでエンコードを実行します。
-y オプションは、既存ファイルを上書きするための指定です。
画質評価の実行
bash # PSNR測定
PSNR_LOG="${RESULTS_DIR}/psnr_${preset}_crf${crf}.log"
ffmpeg -i "$OUTPUT" -i "$ORIGINAL" \
-filter_complex "psnr=stats_file=${PSNR_LOG}" \
-f null -
# SSIM測定
SSIM_LOG="${RESULTS_DIR}/ssim_${preset}_crf${crf}.log"
ffmpeg -i "$OUTPUT" -i "$ORIGINAL" \
-filter_complex "ssim=stats_file=${SSIM_LOG}" \
-f null -
# VMAF測定
VMAF_JSON="${RESULTS_DIR}/vmaf_${preset}_crf${crf}.json"
ffmpeg -i "$OUTPUT" -i "$ORIGINAL" \
-filter_complex "[0:v]setpts=PTS-STARTPTS[dist];[1:v]setpts=PTS-STARTPTS[ref];[dist][ref]libvmaf=model_path=${VMAF_MODEL}:log_path=${VMAF_JSON}:log_fmt=json" \
-f null -
echo "Completed: CRF=$crf, Preset=$preset"
各エンコード済み動画に対して、3 つの指標(PSNR、SSIM、VMAF)を測定します。 結果ファイルには、プリセット名と CRF 値が含まれるため、後から識別しやすくなっています。
結果サマリーの生成
bash# 結果サマリーをCSVで出力
echo "Preset,CRF,PSNR_avg,SSIM_avg,VMAF_mean,FileSize_MB" > "${RESULTS_DIR}/summary.csv"
for preset in "${PRESETS[@]}"; do
for crf in "${CRF_VALUES[@]}"; do
OUTPUT="${RESULTS_DIR}/encoded_${preset}_crf${crf}.mp4"
PSNR_LOG="${RESULTS_DIR}/psnr_${preset}_crf${crf}.log"
SSIM_LOG="${RESULTS_DIR}/ssim_${preset}_crf${crf}.log"
VMAF_JSON="${RESULTS_DIR}/vmaf_${preset}_crf${crf}.json"
# 各指標の平均値を抽出
PSNR_AVG=$(grep "psnr_avg" "$PSNR_LOG" | awk '{sum+=$6; count++} END {printf "%.2f", sum/count}')
SSIM_AVG=$(grep "All:" "$SSIM_LOG" | awk '{sum+=$8; count++} END {printf "%.4f", sum/count}')
VMAF_MEAN=$(jq -r '.pooled_metrics.vmaf.mean' "$VMAF_JSON")
FILE_SIZE=$(du -m "$OUTPUT" | awk '{printf "%.2f", $1}')
echo "$preset,$crf,$PSNR_AVG,$SSIM_AVG,$VMAF_MEAN,$FILE_SIZE" >> "${RESULTS_DIR}/summary.csv"
done
done
echo "Benchmark completed. Results saved in $RESULTS_DIR/summary.csv"
最後に、すべての結果を CSV 形式でまとめます。 このサマリーファイルを使えば、Excel やスプレッドシートで簡単に比較・分析できるでしょう。
スクリプトの実行
bash# スクリプトに実行権限を付与
chmod +x benchmark.sh
# 実行
./benchmark.sh
処理が完了すると、benchmark_results ディレクトリ内に各エンコード動画、ログファイル、サマリー CSV が保存されます。
結果の分析と可視化
サマリー CSV の確認
bash# サマリーファイルの表示
cat benchmark_results/summary.csv
出力例:
textPreset,CRF,PSNR_avg,SSIM_avg,VMAF_mean,FileSize_MB
fast,18,42.34,0.9823,92.45,125.67
fast,23,39.21,0.9654,87.32,78.43
fast,28,36.87,0.9423,79.21,45.89
fast,33,34.12,0.9102,68.54,28.76
medium,18,42.78,0.9856,93.67,118.32
medium,23,39.89,0.9712,88.91,72.14
medium,28,37.45,0.9501,81.43,41.23
medium,33,34.67,0.9178,70.12,25.89
slow,18,43.12,0.9878,94.23,112.45
slow,23,40.34,0.9745,89.87,68.76
slow,28,38.01,0.9567,82.91,38.54
slow,33,35.23,0.9234,71.56,24.12
この結果から、以下のような傾向が読み取れます。
- CRF 値が小さいほど、すべての指標で高スコアだがファイルサイズも大きい
- プリセット
slowが最も高品質だが、エンコード時間も長い - CRF 23 前後が、品質とファイルサイズのバランスが良い
品質とファイルサイズのトレードオフ分析
以下の図は、品質指標とファイルサイズの関係を示しています。
mermaidgraph LR
size_small["ファイルサイズ<br/>小"]
size_large["ファイルサイズ<br/>大"]
quality_low["品質<br/>低"]
quality_high["品質<br/>高"]
crf33["CRF 33<br/>VMAF: 68-71"]
crf28["CRF 28<br/>VMAF: 79-82"]
crf23["CRF 23<br/>VMAF: 87-89"]
crf18["CRF 18<br/>VMAF: 92-94"]
size_small --> crf33
crf33 --> crf28
crf28 --> crf23
crf23 --> crf18
crf18 --> size_large
quality_low --> crf33
crf18 --> quality_high
図で理解できる要点:
- CRF 値とファイルサイズは反比例の関係にある
- VMAF 値は 85 以上が推奨範囲であることがわかる
- CRF 23 が実用的なバランスポイントとなっている
最適設定の選定基準
ベンチマーク結果から最適設定を選ぶ際は、以下の基準を参考にしてください。
| # | 用途 | 推奨 VMAF | 推奨 SSIM | 推奨 PSNR | 推奨 CRF 範囲 |
|---|---|---|---|---|---|
| 1 | アーカイブ保存 | 95 以上 | 0.98 以上 | 45dB 以上 | 15〜18 |
| 2 | 高品質配信 | 85〜94 | 0.95〜0.97 | 40〜44dB | 19〜23 |
| 3 | 標準品質配信 | 75〜84 | 0.93〜0.94 | 37〜39dB | 24〜28 |
| 4 | 低帯域配信 | 65〜74 | 0.90〜0.92 | 34〜36dB | 29〜33 |
Python による自動化と可視化
より高度な分析を行う場合は、Python スクリプトを使用すると便利です。
必要なパッケージのインストール
bash# Pythonパッケージをインストール
pip install pandas matplotlib seaborn
pandas はデータ分析、matplotlib と seaborn は可視化に使用します。
CSV データの読み込みと分析
pythonimport pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# CSVファイルを読み込み
df = pd.read_csv('benchmark_results/summary.csv')
# データの基本統計を表示
print(df.describe())
このコードは、サマリー CSV を読み込み、各指標の基本統計(平均、標準偏差、最小値、最大値など)を表示します。
品質指標の相関分析
python# 品質指標間の相関係数を計算
correlation = df[['PSNR_avg', 'SSIM_avg', 'VMAF_mean']].corr()
print("Correlation Matrix:")
print(correlation)
# 相関マトリックスのヒートマップを作成
plt.figure(figsize=(8, 6))
sns.heatmap(correlation, annot=True, cmap='coolwarm',
vmin=-1, vmax=1, center=0)
plt.title('Quality Metrics Correlation')
plt.tight_layout()
plt.savefig('benchmark_results/correlation_heatmap.png')
plt.close()
このコードは、3 つの品質指標間の相関を計算し、ヒートマップとして可視化します。 通常、VMAF、SSIM、PSNR は正の相関を示しますが、相関の強さは動画内容によって異なります。
品質-ファイルサイズのプロット
python# 各プリセットごとに色分けしてプロット
plt.figure(figsize=(12, 8))
for preset in df['Preset'].unique():
subset = df[df['Preset'] == preset]
plt.scatter(subset['FileSize_MB'], subset['VMAF_mean'],
label=preset, s=100, alpha=0.7)
# CRF値をデータポイントに表示
for idx, row in subset.iterrows():
plt.annotate(f"CRF {row['CRF']}",
(row['FileSize_MB'], row['VMAF_mean']),
xytext=(5, 5), textcoords='offset points',
fontsize=8)
plt.xlabel('File Size (MB)', fontsize=12)
plt.ylabel('VMAF Score', fontsize=12)
plt.title('Quality vs File Size Trade-off', fontsize=14)
plt.legend(title='Preset')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('benchmark_results/quality_vs_size.png', dpi=300)
plt.close()
print("Visualization saved to benchmark_results/quality_vs_size.png")
このプロットにより、どのプリセットと CRF 値の組み合わせが最適なのかを視覚的に判断できます。 グラフの左上(小さいファイルサイズで高い VMAF)が理想的な設定です。
エンコード効率の算出
python# エンコード効率を計算(VMAF / ファイルサイズ)
df['Efficiency'] = df['VMAF_mean'] / df['FileSize_MB']
# 効率でソートして上位10件を表示
top_efficient = df.nlargest(10, 'Efficiency')[
['Preset', 'CRF', 'VMAF_mean', 'FileSize_MB', 'Efficiency']
]
print("\nTop 10 Most Efficient Settings:")
print(top_efficient)
# 効率ランキングをCSVで保存
top_efficient.to_csv('benchmark_results/efficiency_ranking.csv',
index=False)
エンコード効率は、「単位ファイルサイズあたりの品質」を表します。 この指標により、配信コストを考慮した最適設定を見つけることができるでしょう。
4K 動画の評価
高解像度動画では、専用の VMAF モデルを使用することが推奨されます。
4K 用 VMAF モデルの使用
bash# 4K動画用のVMAF測定
ffmpeg -i encoded_4k.mp4 -i original_4k.mp4 \
-filter_complex "[0:v]setpts=PTS-STARTPTS[dist];[1:v]setpts=PTS-STARTPTS[ref];[dist][ref]libvmaf=model_path=/opt/homebrew/share/libvmaf/model/vmaf_4k_v0.6.1.json:log_path=vmaf_4k_output.json:log_fmt=json" \
-f null -
vmaf_4k_v0.6.1.json モデルは、4K 解像度の動画に最適化されており、より正確な評価が可能です。
HD 解像度では通常モデル、4K 以上では 4K モデルを使い分けましょう。
解像度別の評価基準の違い
解像度によって、同じ指標値でも視覚的な印象が異なることがあります。
| # | 解像度 | VMAF 目標値 | SSIM 目標値 | 備考 |
|---|---|---|---|---|
| 1 | 720p(HD) | 85 以上 | 0.95 以上 | 標準モデル使用 |
| 2 | 1080p(Full HD) | 88 以上 | 0.96 以上 | 標準モデル使用 |
| 3 | 2160p(4K) | 90 以上 | 0.97 以上 | 4K モデル使用推奨 |
高解像度になるほど、圧縮による劣化が目立ちやすくなるため、より高い指標値が求められます。
異なるコーデックの比較
H.264(AVC)と H.265(HEVC)、AV1 など、異なるコーデック間の品質比較も可能です。
コーデック別エンコード例
bash# H.264でエンコード
ffmpeg -i original.mp4 -c:v libx264 -crf 23 -preset medium encoded_h264.mp4
# H.265でエンコード
ffmpeg -i original.mp4 -c:v libx265 -crf 28 -preset medium encoded_h265.mp4
# AV1でエンコード(libaom-av1を使用)
ffmpeg -i original.mp4 -c:v libaom-av1 -crf 30 -preset medium encoded_av1.mp4
H.265 と AV1 は、同等の品質でより高い圧縮率を実現できますが、エンコード時間が長くなります。 また、CRF 値の意味がコーデックによって異なるため、同じ CRF 値でも品質は異なることに注意してください。
コーデック間の公平な比較
コーデック間を比較する際は、同じファイルサイズまたは同じ VMAF スコアで比較することが重要です。
python# Pythonでコーデック比較データを分析
codecs_df = pd.DataFrame({
'Codec': ['H.264', 'H.265', 'AV1'],
'FileSize_MB': [78.43, 65.21, 58.32],
'VMAF': [87.32, 88.91, 89.45],
'PSNR': [39.21, 40.34, 40.87],
'SSIM': [0.9654, 0.9712, 0.9756]
})
# エンコード効率を計算
codecs_df['Efficiency'] = codecs_df['VMAF'] / codecs_df['FileSize_MB']
print(codecs_df)
この分析により、AV1 が最も高い圧縮効率を持つことが確認できます。 ただし、デコード互換性やエンコード時間も考慮する必要があるでしょう。
まとめ
FFmpeg を使った画質評価は、動画エンコード最適化において欠かせない技術です。 VMAF、SSIM、PSNR という 3 つの指標をそれぞれ理解し、適切に組み合わせることで、客観的かつ科学的な品質評価が実現できます。
重要なポイントのまとめ
- PSNRは高速だが視覚特性を考慮しない、ベースライン指標として活用
- SSIMは構造的類似性を評価、PSNR より人間の知覚に近い
- VMAFは機械学習ベースで最も主観評価に近く、最終判断に最適
- 3 つの指標を同時に測定することで、多角的な品質評価が可能
- 自動化スクリプトにより、複数設定の効率的なベンチマークを実現
- 結果の可視化により、品質とファイルサイズのトレードオフを把握
- 用途に応じた基準(アーカイブ、高品質配信、標準配信など)で最適設定を選定
これらの手法を活用することで、エンコード設定の根拠を明確にし、配信品質の向上とコスト最適化を両立できるようになります。 ぜひご自身のプロジェクトで実践してみてください。
測定結果をチームで共有し、継続的に品質基準を改善していくことで、より高品質な動画配信サービスの構築につながるはずです。
関連リンク
articleFFmpeg 画質評価の作法:VMAF/SSIM/PSNR を揃えて測るベンチ手順
articleFFmpeg 「Non-monotonous DTS」エラー徹底対策:muxer 選定と再エンコード条件
articleFFmpeg コーデック地図 2025:H.264/H.265/AV1/VP9/ProRes/DNxHR の使いどころ
articleFFmpeg バッチ運用プレイブック:監視・再試行・キュー管理を systemd/tmux で回す
articleFFmpeg フィルタグラフ設計術:複雑合成を filtergraph ファイルで可読・再利用化
articleFFmpeg コマンド 100 連発:入力・出力・フィルタ・ストリーム指定の定番集
articleGrok プロンプト・テンプレ 100 連発:要約/翻訳/コード/分析 早見表
articleGitHub Copilot Workspace と Cursor/Cline の比較検証:仕様駆動の自動化能力はどこまで?
articleGitHub Actions 署名戦略を比べる:SHA ピン留め vs タグ参照 vs バージョン範囲
articlegpt-oss が OOM/VRAM 枯渇で落ちる:モデル分割・ページング・バッチ制御の解決策
articleGPT-5 ツール呼び出しが暴走する時の診断フロー:関数設計/停止条件/リトライ制御
articleGit の index.lock 残留問題を解決:並行実行・クラッシュ後の正しい対処法
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来