GPUImage
可以實(shí)現(xiàn)的功能(基于GPU)
- 視頻合成
- 視頻加水印
- 修改圖片
- 使用GPUImage拍照
- 錄制視頻(CMSampleBuffer)

蘋果自帶的圖片處理框架(基于CPU)
- ImageIO
- CoreImage
視頻
- 未經(jīng)過編碼的視頻,幀數(shù)越大,視頻文件體積越大,一個(gè)像素根據(jù)RGB等計(jì)算大小,一秒之內(nèi)需要30幀才能保證肉眼看起來很流暢(1秒16幀基本看不出卡頓)
文件大小一般會(huì)在1080 * 720 * 30 * 90 - 通過編碼,讓視頻文件體積減小,一般從以下方面做處理:
- 空間冗余
- 時(shí)間冗余
- 指定編碼標(biāo)準(zhǔn)的組織:
- ITU(國(guó)際電傳視訊聯(lián)盟)
- H.26X系列(H261,H263,H264/MPEG-4(
最流行))
- H.26X系列(H261,H263,H264/MPEG-4(
- ISO(國(guó)際標(biāo)準(zhǔn)化組織)
- MPEG系列(MPEG-1、MPEG-2、MPEG-4)
- ITU(國(guó)際電傳視訊聯(lián)盟)
- 其它:AMV、VP6、VP7、VP8、VP9、WMV
視頻編碼流程

H264中的三種幀(每一個(gè)畫面基于三種幀進(jìn)行編碼)
I、B、P幀

編輯方式
- 編碼方式有兩種:
- 硬編碼:使用非CPU進(jìn)行編碼(如GPU、專用的DSP、FPGA、ASIC芯片等)
- 軟編碼:使用CPU進(jìn)行編碼,軟編碼通常使用:FFmpeg+x264
- FFmpeg:是一套開源的、用于對(duì)音頻進(jìn)行編碼、解碼、轉(zhuǎn)化計(jì)算機(jī)程序
- x264:是一種免費(fèi)、開源、具有優(yōu)秀算法的H.264/MPEG-4 AVC視頻壓縮編碼方式
- 對(duì)比:
- 硬編碼:性能高,對(duì)CPU沒有壓力,對(duì)其他硬件要求高(如GPU等)
- 軟編碼:實(shí)現(xiàn)直接、簡(jiǎn)單、參數(shù)調(diào)整方便,升級(jí)易,但CPU負(fù)載重,性能不如硬編碼
- iOS中編碼方式:
- iOS8之前,蘋果未開放硬編碼接口,只能采用FFmpeg+264--->軟編碼
- iOS8之后,蘋果開放硬編碼接口,封裝ViewToolBox和AudioToolBox兩個(gè)框架,分別針對(duì)音頻和視頻進(jìn)行硬編碼
視頻推流
協(xié)議
- HLS
蘋果公司推出?;趆ttp的拉流協(xié)議。原理:將完整視頻切片(例如,將MP4文件切換成m3u8和ts切片),客戶端依次下載切片進(jìn)行播放。- 先切片,后傳輸,因此傳輸會(huì)延遲,
不適合用做直播。 - 可以通過FFmpeg實(shí)現(xiàn)切片。
- 命令: ffmpeg -i xxx.mp4 -c:v libx264 -c:a copy -f hls xxx.m3u8
- m3u8索引頭解析
- 先切片,后傳輸,因此傳輸會(huì)延遲,
EXTM3U -------------------------------- m3u文件頭,必須放在第一行
EXT-X-MEDIA-SEQUENCE -------- 第一個(gè)TS分片序號(hào)
EXT-X-TARGETDURATION -------- 每個(gè)分片TS最大時(shí)長(zhǎng)
EXT-X-ALLOW-CACHE ------------- 是否允許cache
EXT-X-ENDLIST ----------------------- m3u8文件結(jié)束符
EXTINF ----------------------------------- extra,info,分片ts信息(如時(shí)長(zhǎng)、帶寬等)
- RTMP
Adobe公司推出?;赥CP的推流協(xié)議。是目前的主流協(xié)議。本質(zhì)是流協(xié)議。主要優(yōu)勢(shì):- 實(shí)時(shí)性高。在3s內(nèi),經(jīng)過多層CDN界面分發(fā),實(shí)時(shí)性也在三秒左右。
- 支持加密。支持RTMPE和RTMPS協(xié)議。
- 穩(wěn)定性高。
使用:
RTMP會(huì)對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行格式化,稱為RTMP message。
為了更好的實(shí)現(xiàn)多路復(fù)用、分包、信息公平性,發(fā)送端會(huì)把message劃分為帶有messageID的chunk,每個(gè)chunk可能是一個(gè)單獨(dú)的message,也可能是message的一部分,接收端會(huì)根據(jù)message中data的長(zhǎng)度、messageID、message的長(zhǎng)度,把chunk還原成完整的message,實(shí)現(xiàn)信息的收發(fā)。
本地推流
- Nginx安裝
// 克隆到本地
brew tap homebrew/nginx
// unlink
brew unlink nginx
// 安裝
brew install nginx-full --with-rtmp-module
// 啟動(dòng)
nginx
macOS系統(tǒng),安裝配置文件路徑是:/usr/local/etc/nginx/nginx.conf
- 配置nginx支持hls:
在默認(rèn)配置:
location / {
root html;
index index.html index.htm;
}
平級(jí)添加:
location /hls {
#Serve HLS config
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /usr/local/var/www;
add_header Cache-Control no-cache;
}
- 配置nginx支持RTMP:
在最外層,和http平級(jí)添加:
rtmp {
server {
listen 1935;
application rtmplive {
live on;
max_connections 1024;
}
application hls {
live on;
hls on;
hls_path /usr/local/var/www/hls;
hls_fragment 1s;
}
}
}
- 配置完成,需要重啟nginx生效。
nginx -s reload
遇到過的報(bào)錯(cuò):
- rtmp安裝不正確,看上方安裝步驟。
nginx: [emerg] unknown directive "rtmp" in /usr/local/etc/nginx/nginx.conf:134
- 端口被占用報(bào)錯(cuò):
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
解決方案:
// 根據(jù)端口號(hào)查看進(jìn)程號(hào)
sudo lsof -i :8080
// 殺死進(jìn)程
kill -9 進(jìn)程號(hào)
// 啟動(dòng)
nginx
iOS實(shí)現(xiàn)直播
使用第三方庫(kù)
OC使用LFLiveKit
swift使用HaishinKit