ffmpeg實戰-音影片基礎概念
轉發自白狼棧:查看原文
關於音影片,相信大家都看過電影(影片),聽過音樂(音頻),至少應該都知道mp4是影片文件,mp3是音頻文件。
對於一個音影片文件,都有哪些屬性呢?以影片為例,我們可以通過 ffmpeg -i 命令查看媒體文件的資訊。
» ffmpeg -i r1ori.mp4 ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers built with Apple LLVM version 10.0.0 (clang-1000.10.44.4) configuration: --prefix=/usr/local/Cellar/ffmpeg/4.1 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags='-I/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/include/darwin' --host-ldflags= --enable-ffplay --enable-gpl --enable-libmp3lame --enable-libopus --enable-libsnappy --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-chromaprint --enable-frei0r --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfdk-aac --enable-libfontconfig --enable-libfreetype --enable-libgme --enable-libgsm --enable-libmodplug --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-librsvg --enable-librtmp --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtesseract --enable-libtwolame --enable-libvidstab --enable-libwavpack --enable-libwebp --enable-libzmq --enable-opencl --enable-openssl --enable-videotoolbox --enable-libopenjpeg --disable-decoder=jpeg2000 --extra-cflags=-I/usr/local/Cellar/openjpeg/2.3.0/include/openjpeg-2.3 --enable-nonfree libavutil 56\. 22.100 / 56\. 22.100 libavcodec 58\. 35.100 / 58\. 35.100 libavformat 58\. 20.100 / 58\. 20.100 libavdevice 58\. 5.100 / 58\. 5.100 libavfilter 7\. 40.101 / 7\. 40.101 libavresample 4\. 0\. 0 / 4\. 0\. 0 libswscale 5\. 3.100 / 5\. 3.100 libswresample 3\. 3.100 / 3\. 3.100 libpostproc 55\. 3.100 / 55\. 3.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'r1ori.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.20.100 Duration: 00:00:58.53, start: 0.000000, bitrate: 1870 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 544x960, 1732 kb/s, 29.83 fps, 29.83 tbr, 11456 tbn, 59.67 tbc (default) Metadata: handler_name : VideoHandler Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 129 kb/s (default) Metadata: handler_name : SoundHandler
除了影片的元資訊,還包括了更多我們當初編譯的配置,你可以選擇 -hide_banner 參數來隱藏這些資訊,完整的命令如下
»ffmpeg -i r1ori.mp4 -hide_banner Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'r1ori.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.20.100 Duration: 00:00:58.53, start: 0.000000, bitrate: 1870 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 544x960, 1732 kb/s, 29.83 fps, 29.83 tbr, 11456 tbn, 59.67 tbc (default) Metadata: handler_name : VideoHandler Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 129 kb/s (default) Metadata: handler_name : SoundHandler At least one output file must be specified
我們主要看幾個數據
- Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘r1ori.mp4’: # Input #0 表示我們通過ffmpeg -i 參數輸入的第一個文件,下標從0開始,也就是說我們可以輸入多個文件,實際上ffmpeg還支援輸出多個文件
- Metadata 表示影片元資訊
- Duration 這行包含了影片的播放時長是58.53秒,開始播放時間是0,整個文件的比特率是1870kbit/s
- Stream #0:0(und): Video: h264,這行表示該文件的第一個流是影片流,編碼格式是H264格式(封裝格式為AVC1),每一幀的數據表示為yuv420p,解析度為544×960,影片流的比特率是1732kbit/s,幀率為每秒鐘29.83幀。
- Stream #0:1(und): Audio: aac,這行表示該文件的第二個流是音頻流,編碼格式為ACC(封裝格式為MP4A),並且採用的Profile是LC規格,取樣率是44.1KHz,聲道是立體聲(stereo),碼率是129kbit/s
開始出現了一些陌生的名詞,我們依次介紹下。
容器
像上面這個影片文件一樣,把不同的數據流(影片流、音頻流,有的還有字幕流等)封裝在一個文件中,我們稱之為容器。像我們熟悉的mp4、avi、rmvb等等都是多媒體容器格式,一般情況下,多媒體文件的後綴就是它的容器格式。
我們可以把容器理解為一個瓶子、罐子之類的東西。
編碼和解碼(codec)
編碼:將影片、音頻用某種格式或規範記錄下來並存儲,稱為編碼(codec)。編碼可以理解成是對容器內的東西的加工處理。
常見的影片編碼格式有 h264、h265等,常見的音頻編碼格式有 mp3、aac等。
解碼:就是將影片、音頻壓縮的編碼數據,解碼成為非壓縮的影片、音頻原始數據。比如我們要對一段音頻增加回聲,就需要先對音頻文件先解碼再編碼。
軟解:即軟體解碼,通過軟體讓CPU對影片文件進行解碼操作。
硬解:即硬體解碼,為了減輕CPU的壓力,採用GPU來處理原來全部讓CPU處理的部分影片數據。
軟解需要對大量的影片資訊進行處理,所以軟解非常吃CPU,一條FFmpeg的命令都有可能把CPU干趴下了。
相比而言,硬解的效率非常高,但是硬解的缺點也顯而易見,它不能像軟解那樣,對字幕、畫質等的處理效果都不是很好。如果我沒記錯的話,七牛雲平台(一個相對專業的音影片平台)現在還不支援硬解。
ffmpeg是最常見的軟解碼開源庫,它實際是通過比如 H264、H265、MPEG-4等編解碼演算法進行軟解。
在現如今的音影片領域,ffmpeg 幾乎支援所有音影片的編解碼,非常強大。
轉碼:即編碼轉換,是將影片從一種格式轉換為另一種格式。比如將一個flv文件轉換為mp4文件。
ffmpeg -i input.flv output.mp4
比特率
比特率又稱碼率,表示編碼器每秒輸出的位元組數,單位是 Kbps,b 為 比特(bit) 這個就是電腦文件大小的計量單位,1KB=8Kb,區分大小寫,s 為 秒(second) p 為 每(per) 。
比如
在相同的壓縮演算法下(後面我們會介紹若干不同的壓縮演算法),碼率越高,影片的品質也就越高。
對於壓縮文件,按照上面的理解,碼率的粗略計算方式=文件大小/時長。
比如 r1ori.mp4 的大小是 13.7兆,時長約59秒,那麼它的碼率大約等於 (13.7 x 1024 x 8) / 59 = 1900 kb/s
公式:1MB=8Mb=1024KB=8192Kb
因為還有一些參數的影響,所以這個碼率我們也只能得到一個大約的數值。
固定碼率和可變碼率
早些年的時候,音頻編碼的時候選擇的都是固定碼率(Constant Bitrate, CBR),後面出現了可變碼率(Variable Bitrate, VBR),固定碼率指的是編碼器輸出的碼率固定,這樣就很難均衡「平靜的畫面」和「劇烈的畫面」,相對而言,可變碼率就可以很好的控制編碼器,在細節比較多,畫面相對劇烈的時候使用更多的比特位,對於相對平靜的畫面,使用更低的比特位。如此一來,在輸出品質一定的情況下,VBR更具優勢,存儲的話我們也會優先選擇可變碼率。
幀和幀率
幀指的是一個畫面。
幀率(frames per second, fps),即每秒輸出多少幀,你也可以理解畫面每秒輸出多少次。
大家在玩遊戲的時候一定深有體驗,遊戲卡頓的時候,畫面都是幀與幀之間跳動的,非常的不順暢。
幀率影響畫面的流暢度,幀率越高,畫面也就越流暢。
由於視覺暫留現象(即當物體在快速運動時, 人眼所看到的影像消失後,人眼仍能繼續保留其影像1/24秒左右的影像)的存在,所以對於一般的電影影片,要求最低幀率是24,也就是每幀曝光1/24 = 0.042秒。
解析度
解析度大家應該都不陌生,比如某影片網站常見的藍光1080P,超清720P,高清540P。
解析度可以理解為影片畫面的大小,即影片的寬度和高度。720P指的就是高度是720像素。
了解過碼率和幀率我們發現,不能絕對的說解析度越高影片越清晰,更重要的是如何平衡好碼率、幀率以及解析度三者的關係。
總的來說,我們更願意接受影片體積越小,清晰度越高的影片,一來是存儲方便,二來是看起來爽。
有損和無損
首先我們說一下什麼是音影片的原始數據?原始數據指的是通過音影片設備採集的、沒有經過任何加工的數據。音頻的原始數據是pcm格式,影片的原始數據是yuv格式。
有損和無損,即有沒有損失,這裡針對的是多媒體數據壓縮的一種說法。有損壓縮又稱之為破壞性壓縮,當然並不是說壓縮之後無法解壓的那種破壞。比如我們常見的mp3、mp4文件都是有損壓縮。
以音頻編碼為例,音頻裡面的聲音來源於自然界,我們通過技術方案捕獲到聲音,然後根據一定的演算法進行存儲。
在現階段,我們存儲下來的聲音不能完全還原為自然界的聲音,任何音頻編碼都是有損的。
有同學可能要提出疑問了,我看有文章介紹,音頻的原始數據不是pcm格式的嗎?
其實pcm編碼也只是無限接近於無損,它能夠達到訊號的最高保真,因此,pcm編碼才被約定為無損壓縮。
好好的音頻,我想聽最真實的從自然界採集的聲音,為什麼要壓縮呢?
原始數據太大,不方便存儲
即使存儲下來了,也不方便傳輸,需要極大的頻寬
現在影片的壓縮比很高,比如現如今大家耳熟能詳的4k 8k,看起來完全能滿足需要
復用器和解復用器
對於容器而言,注意這裡針對的是容器,我們經常會有兩種頻繁的操作。
取出容器內的音影片數據,我們稱之為解封裝,由demuxer解封裝器(又稱之為解復用器)完成。
把處理好的音影片數據裝進容器內稱之為封裝,由muxer封裝器(又稱之為復用器)完成。
我們會在這邊文章下面持續更新音影片相關的概念,如果你覺得有什麼概念不好理解,可以給我留言,我會再收集並作補充。