FFmpeg全名是Fast Forward MPEG(Moving Picture Experts Group),為開源的影音多媒體處理框架,可以進行影音的解碼、編碼、編碼轉換、混合、抽取、串流和濾鏡,無論影音格式是從哪個地方出來的,從過去到現在的影音格式它幾乎都能夠支援。FFmpeg也有很不錯的可攜性和可移植性,可以使用在Linux, macOS, Microsoft Windows, BSDs, Solaris等多種不同的作業系統和多種硬體架構上。若想要比對兩個影片的畫質差異程度,也可以使用FFmpeg來達成。



取得FFmpeg

參考這篇文章來取得FFmpeg:

PSNR

PSNR(peak signal-to-noise ratio)即「峰值信噪比」,常用來判斷兩個影像的差異程度。公式如下:

#{{{
PSNR = 10 \times \log_{10}({ { MAX^2 } \over {MSE} })
}}}#

其中的#{{ {MAX} }}#是該分量像素點的最大數值,例如8-bit的yuvj420p,Y、U、V的最大值都是255,所以#{{ {MAX} }}#都會是255。如果是10-bit的yuv420p10le,#{{ {MAX} }}#的值則均為1023。

而MSE為「均方誤差」(Mean Square Error),公式如下:

#{{{
MSE = { { \sum_{n=1}^{ImageSize} (I_{n} - P_{n})^2 } \over { ImageSize } }
}}}#

#{{ I_{n} }}#為第一個影像的第N個像素點的分量值,#{{ P_{n} }}#為第二個影像的第N個像素點的分量值。也就是說,如果兩個影像的差異愈大,其#{{ {MSE} }}#的值就會愈大。

而MSE和PSNR是呈反比關係,因此PSNR愈大,代表兩個影響的差異愈小。兩個相同的影像,PSNR的值為無限大。

在比較兩個解析度相同,且影格(Frame)數也相同的影片的畫質差異程度時,我們可以將它們的影格依時間順序拿來做PSNR的運算,取得平均的PSNR後,即可判斷出這兩個影片的畫質差異如何。PSNR的平均若在45dB以上的話,表示這兩個影片的畫質可以說是十分接近。42dB以上是大多數人都接受的範圍。

若要用FFmpeg來計算兩個影片的PSNR,指令如下:

ffmpeg -i 重製影片的檔案路徑 -i 原始影片的檔案路徑 -lavfi "[0:v]setpts=PTS-STARTPTS[v0];[1:v] setpts=PTS-STARTPTS[v1];[v0][v1]psnr" -f null -

ffmpeg-psnr-ssim

SSIM

SSIM(structural similarity)即「結構相似性」,是針對人類視覺系統所設計的影像差異程度指標。SSIM的用途和PSNR類似,但SSIM的算法更複雜,所以在此就不多提了。

SSIM的值愈大,表示兩個影像的相似程度愈高。兩個相同的影像,SSIM的值為1。

SSIM的平均若在0.990以上的話,表示這兩個影片的畫質可以說是十分接近。0.980以上是大多數人都接受的範圍。

若要用FFmpeg來計算兩個影片的SSIM,指令如下:

ffmpeg -i 重製影片的檔案路徑 -i 原始影片的檔案路徑 -lavfi "[0:v]setpts=PTS-STARTPTS[v0];[1:v] setpts=PTS-STARTPTS[v1];[v0][v1]ssim" -f null -

ffmpeg-psnr-ssim

PSNR和SSIM

由於SSIM是針對人類的視覺系統所設計,因此假設現在我們把某個已經被轉成多種不同畫質的影片檔案的影片,拿來與原始影片檔案進行SSIM和PSNR的計算,並依照SSIM的值和PSNR的值,將這些影片檔案做畫質排序,會發現SSIM所排序出來的結果,會和人類肉眼感受到的結果較為接近。

若要用FFmpeg來同時計算兩個影片的PSNR和SSIM,指令如下:

ffmpeg -i 重製影片的檔案路徑 -i 原始影片的檔案路徑 -lavfi "[0:v]setpts=PTS-STARTPTS[v0];[1:v] setpts=PTS-STARTPTS[v1];[v0][v1]ssim;[0:v]setpts=PTS-STARTPTS[v0];[1:v] setpts=PTS-STARTPTS[v1];[v0][v1]psnr" -f null -

ffmpeg-psnr-ssim

Application provided invalid, non monotonically increasing dts to muxer的解決辦法

在使用FFmpeg來計算兩個影片的PSNR和SSIM時,可能會出現Application provided invalid, non monotonically increasing dts to muxer這樣的如下圖的訊息,而導致PSNR和SSIM的計算結果不準確(會比實際值低很多)。

ffmpeg-psnr-ssim

這通常會發生在兩個影片使用不同編碼器時,例如一個使用libx264來編碼,另一個使用libvpx。解決的辦法很簡單,就是先讓其中一個影片以無損(lossless)的方式先轉成另一個格式,再拿這兩個用相同編碼器編碼出來的影片來計算PSNR和SSIM即可。

libvpx-vp9可以使用-lossless 1參數來做無損編碼;libx264可以使用-crf 0參數來做無損編碼;libx265可以使用-x265-params lossless=1參數來做無損編碼。