瀏覽器中的音視頻知識(shí)總結(jié)
本文適合使用音視頻入門的小伙伴進(jìn)行閱讀。
歡迎關(guān)注前端早茶,與廣東靚仔攜手共同進(jìn)階~
作者:廣東靚仔
一、前言
廣東靚仔最近前陣子看到字節(jié)開源了西瓜播放器,感覺還不錯(cuò)。
https://github.com/bytedance/xgplayer
二、視頻是什么
視頻,其實(shí)就是一系列連續(xù)播放的圖片,如果1s鐘播放24張圖片,那么人眼看到的就不再是一張張獨(dú)立的圖片,而是動(dòng)起來的畫面。其中一張圖片稱為一幀,1s播放的圖片數(shù)稱為幀率。常見的幀率有24幀/s,30幀/s,32幀/s。
視頻是由圖片構(gòu)成的,圖片是由像素構(gòu)成的,假設(shè)尺寸為 1024*768。每個(gè)像素由RGB構(gòu)成,每個(gè)8位,共24位。
這里補(bǔ)充一點(diǎn)2進(jìn)制的知識(shí)
1位10進(jìn)制數(shù),能夠表示0-9,共10種可能
類比一下,1位2進(jìn)制,能夠表示0,1,共表示2種可能性。
一位2進(jìn)制稱為1比特,即1 bit。
byte 字節(jié)是計(jì)算機(jī)計(jì)量的基本單位,1 byte= 8bit
1位16進(jìn)制能夠表示0-15,共16種可能性,如果換算成2進(jìn)制,2^4=16,需要4位二進(jìn)制才能表示1位16進(jìn)制數(shù)。
1byte=8bit=2個(gè)16進(jìn)制數(shù)
像素用16進(jìn)制表示為 #ffffff,需要6個(gè)16進(jìn)制,也就是3byte假設(shè)幀率是30,那么每秒鐘的視頻的尺寸如下:
30幀x1024x768x24=566231040Bits=70778880Bytes
一分鐘視頻的尺寸就是 4246732800Bytes已經(jīng)是4個(gè)G了。
1Byte=8bit
1MB=1024Byte(2^10)
1GB=1024MB(2^20Byte)可以看到,這個(gè)數(shù)據(jù)量是很大的,不好進(jìn)行網(wǎng)絡(luò)傳輸以及存儲(chǔ),所以需要對(duì)視頻進(jìn)行壓縮,也就是編碼。
三、編碼過程
之所以能夠?qū)σ曨l的中圖片進(jìn)行壓縮,是因?yàn)橐曨l和圖片具有以下特點(diǎn):
空間冗余:圖像的相鄰像素之間有較強(qiáng)的相關(guān)性,一張圖片相鄰像素往往是漸變的,不是突變的,沒必要每個(gè)像素都完整地保存,可以隔幾個(gè)保存一個(gè),中間的用算法計(jì)算出來。
時(shí)間冗余:視頻序列的相鄰圖像之間內(nèi)容相似。一個(gè)視頻中連續(xù)出現(xiàn)的圖片也不是突變的,可以根據(jù)已有的圖片進(jìn)行預(yù)測(cè)和推斷。
視覺冗余:人的視覺系統(tǒng)對(duì)某些細(xì)節(jié)不敏感,因此不會(huì)每一個(gè)細(xì)節(jié)都注意到,可以允許丟失一些數(shù)據(jù)。
編碼冗余:不同像素值出現(xiàn)的概率不同,概率高的用的字節(jié)少,概率低的用的字節(jié)多,類似霍夫曼編碼(Huffman Coding)的思路。
編碼的流程如下:

四、總結(jié)并補(bǔ)充一些概念
分辨率
屏幕是由一個(gè)個(gè)像素點(diǎn)組成的,我們常見的1080p,是指屏幕豎直方向有1080個(gè)像素,共有1920列,一共207萬像素。2K,2560x1440,共369萬像素。
放一個(gè)百度百科的解釋
顯示分辨率(屏幕分辨率)是屏幕圖像的精密度,是指顯示器所能顯示的像素有多少。
由于屏幕上的點(diǎn)、線和面都是由像素組成的,顯示器可顯示的像素越多,畫面就越精細(xì),
同樣的屏幕區(qū)域內(nèi)能顯示的信息也越多,所以分辨率是個(gè)非常重要的性能指標(biāo)之一。
可以把整個(gè)圖像想象成是一個(gè)大型的棋盤,而分辨率的表示方式就是所有經(jīng)線和緯線交叉點(diǎn)的數(shù)目。
顯示分辨率一定的情況下,顯示屏越小圖像越清晰,反之,顯示屏大小固定時(shí),
顯示分辨率越高圖像越清晰。
分辨率對(duì)視頻體積有一定影響,但是不是分辨率越大,視頻越清晰,還要看碼率。
幀率FPS
每秒顯示的幀數(shù),就是1s播放的圖片數(shù)量(Frames per Second)。
百度百科解釋:
由于人類眼睛的特殊生理結(jié)構(gòu),如果所看畫面之幀率高于24的時(shí)候,就會(huì)認(rèn)為是連貫的,
此現(xiàn)象稱之為視覺暫留。這也就是為什么電影膠片是一格一格拍攝出來,然后快速播放的。
而對(duì)游戲,一般來說,第一人稱射擊游戲比較注重FPS的高低,如果FPS<30的話,
游戲會(huì)顯得不連貫。所以有一句有趣的話:“FPS(指FPS游戲)重在FPS(指幀率)。
每秒的幀數(shù)(fps)或者說幀率表示圖形處理器處理場(chǎng)時(shí)每秒鐘能夠更新的次數(shù)。
高的幀率可以得到更流暢、更逼真的動(dòng)畫。一般來說30fps就是可以接受的,
但是將性能提升至60fps則可以明顯提升交互感和逼真感,
但是一般來說超過75fps一般就不容易察覺到有明顯的流暢度提升了。
如果幀率超過屏幕刷新率只會(huì)浪費(fèi)圖形處理的能力,因?yàn)楸O(jiān)視器不能以這么快的速度更新,
這樣超過刷新率的幀率就浪費(fèi)掉了。
碼率(比特率)
碼率,也叫比特率,幀率是1S播放多少幀,類比一下,比特率就是1s的視頻有多少bit。
這個(gè)參數(shù)決定了視頻是否清晰。
一個(gè)1080P的視頻,大小可以為1G,也可以為4G,視頻越大,說明1S存放的數(shù)據(jù)越多,比特率越高,壓縮比越小,視頻越清晰。
1080P,長(zhǎng)度為100分鐘,大小為1GB的視頻的比特率是多少?
總時(shí)間為
100分鐘=100X60S=6000s
總數(shù)據(jù)量為
1GB=1024MB= 1024X1024KB=1024X1024X1024Byte=1024X1024X1024X8bit=8589934592bit
幀率為 (數(shù)據(jù)量/時(shí)間)
8589934592/6000 = 1.4Mbit/s幀率和分辨率都可以影響視頻體積,但是幀率是主要因素,在工作中如果看到一個(gè)很短的視頻非常大,很大可能性是因?yàn)閹屎艽?,為了便于網(wǎng)絡(luò)傳輸,需要降低幀率。一般來說主流視頻平臺(tái)的幀率在1Mbit/s左右。
音頻是什么
音頻這里的概念有點(diǎn)多,我也不太會(huì),如果一次有看不懂的地方,請(qǐng)發(fā)在評(píng)論區(qū)。我改。
聲音是由物體振動(dòng)產(chǎn)生的,振動(dòng)的快慢(頻率)決定了聲音的音調(diào)(男高音,男低音),振動(dòng)的幅度決定了聲音的大小(音量|響度),振動(dòng)的物體的特性決定了聲音的音色。音調(diào)、音量和音色稱為聲音的三要素。
聲音可以用模擬信號(hào)來表示的,模擬信號(hào)的概念如下:
模擬信號(hào)是指用連續(xù)變化的物理量表示的信息,其信號(hào)的幅度,或頻率,
或相位隨時(shí)間作連續(xù)變化,或在一段連續(xù)的時(shí)間間隔內(nèi),
其代表信息的特征量可以在任意瞬間呈現(xiàn)為任意數(shù)值的信號(hào)。

橫軸是時(shí)間

PCM數(shù)據(jù),Pulse Code Modulation,包含以下內(nèi)容:采樣大小
一個(gè)采樣用多少bit存放,常用的16bit,采樣大小越大
采樣率
1s采樣多少次
聲道數(shù)
左聲道、右聲道,雙聲道
音頻的比特率(1s種音頻的大?。┯?jì)算方式為
音頻碼率=采樣大小*采樣率*聲道
44100 * 16 * 2 = 1378.125 kbps如果是1分鐘,需要的大小為
1378.125 * 60 / 8 / 1024 = 10.09 MB
六、音頻編碼

封裝格式

操作音視頻必備工具-FFMPEG
FFMPE是音視頻處理最常用的開源軟件,本文主要介紹它的命令行工具。
首先,安裝FFMPEG:
分MAC、WINDOW、LINUX
七、一些概念
支持的封裝格式
查看ffmpeg支持的封裝格式(container)
ffmpeg -formats
以上輸入會(huì)很多,可以使用grep過濾,例如我們想查看是否支持FLV格式,可以使用以下命令:
ffmpeg -codecs | grep FLV
支持的編碼格式
H.262
H.264
H.265
MPEG-4
常見的音頻編碼格式如下:
MP3
AAC
查看ffmpeg支持的編碼格式,視頻編碼和音頻編碼都在內(nèi)
ffmpeg -codecs
編碼器
libx264:最流行的開源 H.264 編碼器
NVENC:基于 NVIDIA GPU 的 H.264 編碼器
libx265:開源的 HEVC 編碼器
libvpx:谷歌的 VP8 和 VP9 編碼器
libaom:AV1 編碼器
音頻編碼器
libfdk-aac
aac
以下命令查看已安裝的編碼器
ffmpeg -encoders
ffprobe查看視頻信息
ffprobe是ffmpeg提供的一個(gè)命令行工具,用來查看視頻元數(shù)據(jù)以及音視頻碼流的編碼信息等,使用很簡(jiǎn)單
ffprobe 1.mp4
輸出如下:

ffmpeg命令行使用格式
ffmpeg {1} {2} -i {3} {4} {5}
五個(gè)部分的參數(shù)依次如下:
全局參數(shù)
輸入文件參數(shù)
輸入文件,必需
輸出文件參數(shù)
輸出文件,必需
舉個(gè)簡(jiǎn)單的栗子:
ffmpeg -i 1.mp4 output.webm
上面的代碼是把封裝格式為mp4的文件轉(zhuǎn)成封裝格式為webm格式的文件,只輸入了輸入文件和輸出文件。
以上代碼沒有指定視頻碼流的編碼格式的音頻碼流的編碼格式,ffmpeg會(huì)自動(dòng)選擇編碼格式具體選擇的是什么編碼格式,可以等轉(zhuǎn)換完成之后自己使用ffprobe查看一下。ffprobe output.webm
如果只想轉(zhuǎn)換封裝格式,編碼格式不變,可以在輸出文件參數(shù)那里添加-c copy
ffmpeg -i 1.mp4 -c copy output.avi
常見參數(shù)
-c:指定編碼器-c copy:直接復(fù)制,不經(jīng)過重新編碼(這樣比較快)-c:v:指定視頻編碼器-c:a:指定音頻編碼器-i:指定輸入文件-an:去除音頻流-vn:去除視頻流-preset:指定輸出的視頻質(zhì)量,會(huì)影響文件的生成速度,有以下幾個(gè)可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。-y:不經(jīng)過確認(rèn),輸出時(shí)直接覆蓋同名文件。
常見用法
查看視頻信息
使用ffprobe查看視頻信息
參數(shù)格式:ffprobe [options] [input_file]
# 最簡(jiǎn)單用法
ffprobe 1.mp4
# 不顯示歡迎信息,只顯示流相關(guān)信息
ffprobe -hide_banner 1.mp4
# 以json形式顯示每個(gè)流信息
ffprobe -print_format json -show_streams 1.mp4
# 顯示容器格式相關(guān)信息
ffprobe -show_format 1.mp4參數(shù)說明:
hide_banner 不顯示歡迎信息和配置信息,只顯示視頻元數(shù)據(jù)
show_format 顯示容器格式相關(guān)信息
轉(zhuǎn)換編碼格式
ffmpeg -i input.mp4 output.mpeg
指定視頻碼流編碼格式。
轉(zhuǎn)化為H.264編碼,一般使用編碼器libx264
# 轉(zhuǎn)化為 H.264格式
ffmpeg -i 1.mp4 -c:v libx264 output.mp4
# 轉(zhuǎn)化為 H.265格式
ffmpeg -i 1.mp4 -c:v libx265 output-265.mp4
參數(shù)說明:
-c:v 指定視頻編碼器
-c:a 指定音頻編碼器
轉(zhuǎn)換容器格式
mp4轉(zhuǎn)為avi
ffmpeg -i input.mp4 -c copy output.avi
上面例子中,只是轉(zhuǎn)一下容器,內(nèi)部的編碼格式不變,所以使用-c copy指定直接拷貝,不經(jīng)過轉(zhuǎn)碼,這樣比較快
# 不使用 -c copy參數(shù),ffmpeg會(huì)自己判斷輸入文件的編碼
ffmpeg -i input.mp4 output.webm
轉(zhuǎn)換時(shí)可以手動(dòng)指定編碼格式
# 轉(zhuǎn)換時(shí)可以手動(dòng)指定編碼格式
ffmpeg \\
-y \\ # 全局參數(shù)
-c:a libfdk_aac -c:v libx264 \\ # 輸入文件參數(shù)
-i input.mp4 \\ # 輸入文件
-c:v libvpx-vp9 -c:a libvorbis \\ # 輸出文件參數(shù)
output.webm # 輸出文件
調(diào)整碼率(比特率)
調(diào)整碼率指的是,改變編碼的比特率,一般用來將視頻文件的體積變小。
比特率計(jì)算:視頻多少比特(bit)/視頻時(shí)長(zhǎng)(s)
例如一個(gè)視頻是2.6M 換算成比特 2.6x1024x1024x8=21810380.8 bit
視頻是22s
比特率:21810380.8/22=991 Kb/s
設(shè)置碼率:
# 設(shè)置輸出的碼率為1.5M,ps:最后的輸出視頻碼率會(huì)有一些小的偏差
ffmpeg -i input.mp4 -b 1.5M output.mp4
# 默認(rèn)情況下,ffmpeg使用可變比特率(VBR)進(jìn)行設(shè)置,靜態(tài)的畫面使用較少的碼率,動(dòng)態(tài)的畫面使用較多的碼率
參數(shù)說明
-b 指定視頻流和音頻流總體的比特率
可以使用-b:v -b:a 分別指定視頻流和音頻流的比特率
也可以手動(dòng)指定 最小比特率,最大比特率,以及緩沖區(qū)的大?。?/p>ffmpeg -i input.mp4 -minrate 964k -maxrate 3856k -bufsize 2000k output.mp4
# -b -minrate -maxrate 需要指定固定的值,maxrate需要指令一個(gè)bufsize(緩沖區(qū)大小)
ffmpeg -i input.mp4 -b 0.5M -minrate 0.5M -maxrate 0.5M -bufsize 1M output.mp4
改變分辨率
# 將分辨率調(diào)整為640*480
ffmpeg -i input.mp4 -vf scale=640:480 output.mp4
# 按照原比率進(jìn)行調(diào)整
ffmpeg -i input.mp4 -vf scale=480:-1 output.mp4
參數(shù)說明
vf 濾鏡
vf scale 調(diào)整分辨率
分離視頻(去除視頻中的音頻)
ffmpeg -i input.mp4 -c:v copy -an output.mp4
參數(shù)說明
an 去除音頻流
分離音頻
ffmpeg -i input.mp4 -vn -c:a copy output.aac
參數(shù)說明
vn 表示去掉視頻
c:a copy表示不改變音頻編碼
添加音軌
將外部音頻加入視頻,比如添加背景音樂或者旁白
# 如果視頻原來有聲音,不會(huì)添加成功,所以需要先去除視頻中原來的音頻
# 輸入有兩個(gè)文件,ffmpeg會(huì)將它們合成為一個(gè)文件
ffmpeg -i input.aac -i input.mp4 output.mp4
截圖
從指定時(shí)間開始,連續(xù)對(duì)1秒鐘的視頻進(jìn)行截圖
# 從00:00:05s開始,連續(xù)對(duì)1秒鐘的視頻進(jìn)行截圖
ffmpeg -y -i input.mp4 -ss 00:00:05 -t 00:00:01 output_%3d.jpg
如果只需要截取一幀
# 從00:00:10s開始截取一幀
ffmpeg -ss 00:00:10 -i input -vframes 1 -q:v 2 output.jpg
參數(shù)說明
vframes 1 指定只截取一幀
q:v 2表示輸出圖片的質(zhì)量 一般是1至5之間
分割一個(gè)mp4文件到多個(gè)小的mp4文件
可以指定開始時(shí)間和持續(xù)時(shí)間,也可以指定結(jié)束時(shí)間
ffmpeg -ss <start> -i <input> -t <duration> -c copy <output>
ffmpeg -ss <start> -i <input> -to <end> -c copy <output>
示例:
# 將視頻從0s分割到5s的位置
ffmpeg -ss 00:00:00 -i 1.mp4 -c copy -t 5 aqgy-1.mp4
# 示例:將一個(gè)1分30s的視頻分成4段
ffmpeg -ss 00:00:00 -i 1.mp4 -c copy -t 00:00:22 aqgy-1.mp4
ffmpeg -ss 00:00:22 -i 1.mp4 -c copy -t 00:00:22 aqgy-2.mp4
ffmpeg -ss 00:00:44 -i 1.mp4 -c copy -t 00:00:22 aqgy-3.mp4
ffmpeg -ss 00:01:06 -i 1.mp4 -c copy -t 00:00:22 aqgy-4.mp4八、視頻播放器的原理
先說一下播放器是如何播放視頻的,這里的播放器可以是本地的播放器,也可以是瀏覽器中的播放器。
大概流程如下:

瀏覽器中音視頻知識(shí)
為什么有些視頻播放不了
音視頻解碼階段,因?yàn)闉g覽器支持的解碼器有限,所有有些編碼的視頻碼流瀏覽器無法解碼,流程中斷,所以也就無法播放。h264,音頻編碼為aac的MP4文件在各大瀏覽器都能播放,因?yàn)閔264編碼格式雖然有版權(quán),但是可以免費(fèi)使用。音視頻標(biāo)簽
<video controls poster="1.jpg" src="1.mp4" loop muted></video>
<audio controls src="1.mp3"></audio>
src指定資源地址,poster為視頻指定一張封面圖,controls表示瀏覽器應(yīng)該顯示UI控件(每個(gè)瀏覽器樣式不同)
常用屬性
下面是video和audio的通用屬性

常用事件
video和audio通用事件

常用方法
play() 控制視頻開始播放
pause() 控制視頻暫停播放
有了上述的屬性、事件及方法,我們就可以做很多事了,比如自定義播放器,使用播放器本地預(yù)覽視頻等。
瀏覽器中實(shí)現(xiàn)視頻播放器的基本思路
整體思路如下:
監(jiān)聽
loadedmetadata事件,獲取視頻時(shí)長(zhǎng)(duration),真實(shí)寬高(videoWidth,videoHeight)點(diǎn)擊播放/暫停時(shí),調(diào)用視頻元素的play/pause方法
播放時(shí),監(jiān)聽
timeupdate,獲取當(dāng)前播放時(shí)間(currentTime),計(jì)算出進(jìn)度條的進(jìn)度拖動(dòng)進(jìn)度條,設(shè)置視頻當(dāng)前播放時(shí)間,與步驟3相反
視頻初始加載時(shí),顯示loading。即組件初次渲染時(shí),loading屬性默認(rèn)為true,即顯示加載效果,當(dāng)視頻元數(shù)據(jù)加載時(shí),取消loading
視頻卡頓時(shí),顯示loading。該功能的實(shí)現(xiàn)是監(jiān)聽的
waiting事件,不卡頓時(shí),取消loading,監(jiān)聽的是canplay事件
九、總結(jié)
關(guān)注我,一起攜手進(jìn)階
歡迎關(guān)注前端早茶,與廣東靚仔攜手共同進(jìn)階~
