🎞️

ffmpegで画像を動画にオーバーレイすると色がくすむ問題の対処法

2024/01/31に公開

単純にoverlayフィルターを使うと色がくすむ

ffmpegのフィルターを使って、画像を動画にオーバーレイする(重ねる)ことができる。

ffmpeg -i input.mp4 -i yellow_FFFF00.png \
-filter_complex "[0:v][1:v]overlay" /tmp/output.mp4

しかし、上の単純なフィルターだと画像は重なるが色が微妙にくすんでしまう。例えば、#FFFF00の画像が#FFF000の色になってオーバーレイされる。

入力画像の色空間を変換する

この問題に対処するには、色空間を変換するフィルターを追加する必要がある。

ffmpeg -i input.mp4 -i yellow_FFFF00.png \
-filter_complex "[1:v]colorspace=all=bt709:iall=bt601-6-625:fast=1[p1];[0:v][p1]overlay" \
/tmp/output.mp4

これでオーバーレイされる画像の色は#FFFF00(もしくはその1bit誤差)となる。

動画に色空間メタデータを追加する

さらにプレイヤーに正しい色空間を使わせるヒントとして以下のオプションでメタデータを追加するとよりよい。

ffmpeg -i input.mp4 -i yellow_FFFF00.png \
-filter_complex "[1:v]colorspace=all=bt709:iall=bt601-6-625:fast=1[p1];[0:v][p1]overlay" \
-color_range 1 -colorspace 1 -color_primaries 1 \ 
/tmp/output.mp4

上の1はbt709色空間を意味する。

透過レイヤーがある場合

上記フィルターで色空間を変換すると透過レイヤーが失われるのでsplitして透過レイヤーを最後にalphamergeする必要がある。

ffmpeg -i input.mp4 -i yellow_FFFF00.png \
-filter_complex "[1:v]split=2[p_color][p_alpha];[p_color]colorspace=all=bt709:iall=bt601-6-625:fast=1[p_color];[p_alpha]format=yuva420p,extractplanes=a[p_alpha];[p_color][p_alpha]alphamerge[p1];[0:v][p1]overlay" \
-color_range 1 -colorspace 1 -color_primaries 1 \ 
/tmp/output.mp4

参考

主に参考にしたのは以下のブログ。
https://medium.com/invideo-io/talking-about-colorspaces-and-ffmpeg-f6d0b037cc2f

以下のブログによればまだ改善の余地はあるらしくcolorspace=all=bt709:iprimaries=bt709:itrc=srgb:ispace=bt709を推している。

https://www.canva.dev/blog/engineering/a-journey-through-colour-space-with-ffmpeg/

Discussion