#直播總結(jié)
##1.概述
關(guān)于直播的技術(shù)文章不少,成體系的不多着逐。我們將用這篇文章倘潜,更系統(tǒng)化地介紹當(dāng)下大熱的視頻直播各環(huán)節(jié)的關(guān)鍵技術(shù),幫助視頻直播創(chuàng)業(yè)者們更全面械拍、深入地了解視頻直播技術(shù)突勇,更好地技術(shù)選型。
###1.1 一個(gè)完整的直播APP原理
`直播原理` : 把主播錄制的視頻坷虑,推流送到服務(wù)器甲馋,服務(wù)器經(jīng)過處理(鑒黃等),通過CDN分發(fā)給觀眾看。
`直播環(huán)節(jié)` : 推流端(采集迄损、美顏定躏、編碼、推流)芹敌,服務(wù)端處理(轉(zhuǎn)碼痊远、錄制、截圖党窜、鑒黃)拗引、播放器(拉流、解碼幌衣、渲染)矾削、互動(dòng)系統(tǒng)(聊天室、禮物系統(tǒng)豁护、贊)
###1.2 一個(gè)完整直播APP實(shí)現(xiàn)流程
`1.采集哼凯、2.濾鏡處理、3.編碼楚里、4.推流断部、5.CDN分發(fā)、6.拉流班缎、7.解碼蝴光、8.播放、9.聊天互動(dòng)`
![](直播app流程.png)
###1.3 一個(gè)完整直播APP架構(gòu)
`1.采集端达址、服務(wù)端蔑祟、播放端`
![](liveApp.png)
###1.4 一個(gè)完整直播APP技術(shù)點(diǎn)
![](直播app技術(shù)點(diǎn).jpeg)
下面我們會(huì)選擇一部分技術(shù)進(jìn)行講解。
`提示`:[總結(jié)不好 圖看不清 請點(diǎn)這里](http://www.reibang.com/p/bd42bacbe4cc)
##2. 視頻采集
###2.1 基本知識(shí)介紹
`AVFundation` : 音視頻數(shù)據(jù)采集需要用AVFundation框架
`AVCaptureDevice` : 硬件設(shè)備沉唠,包括麥克風(fēng)疆虚、攝像頭、通過該對象可以設(shè)置物理設(shè)備的一些屬性。例如相機(jī)焦距径簿,白平衡等
`AVCaptureDeviceInput` : 硬件輸入對象罢屈,可以根據(jù)AVCaptureDevice創(chuàng)建對應(yīng)的AVCaptureDeviceInput對象,用于管理硬件輸入數(shù)據(jù)
`AVCaptureOutput` : 硬件輸出對象篇亭,用于接收各類輸出數(shù)據(jù)缠捌,通常使用對應(yīng)的子類AVCaptureAudioDataOutput(聲音數(shù)據(jù)輸出對象), AVCaptureVideoDataOutput(視頻輸出對象)
`AVCaptureConnection` : 當(dāng)把一個(gè)輸入和輸出添加到AVCaptureSession后。AVCaptureSession就會(huì)在輸出译蒂、輸出設(shè)備之間建立連接鄙币,而且通過AVCaptureOutput可以獲得這個(gè)對象
`AVCaptureVideoPreviewLayer` : 相機(jī)拍攝預(yù)覽圖層,能實(shí)時(shí)查看相機(jī)效果蹂随。創(chuàng)建該對象需要指定對應(yīng)的AVCaptureSession對象,因?yàn)锳VCaptureSession包含輸出數(shù)據(jù)因惭,有視頻數(shù)據(jù)才能顯示岳锁。
`AVCaptureSession` : 協(xié)調(diào)輸入與輸出之間傳遞數(shù)據(jù)
###2.2 捕獲音視頻步驟
包含關(guān)系:
![](AVCaptureSession.png)
步驟:
>1.? 創(chuàng)建AVCaptureDevice(video或者audio)
>2.? 根據(jù)AVCaptureDevice創(chuàng)建AVCaptureDeviceInput。
>3.? 創(chuàng)建AVCaptureSession
>4.? 把創(chuàng)建的AVCaptureDeviceInput加入AVCaptureSession
>5.? 添加視頻預(yù)覽圖層AVCaptureVideoPreviewLayer
>6.? 創(chuàng)建AVCaptureAudioDataOutput蹦魔,并加入AVCaptureSession
>7.? 啟動(dòng)會(huì)話
官方步驟(可以忽略):
> 1. 創(chuàng)建AVCaptureSession對象
> 2. 獲取AVCaptureDevice錄像設(shè)備(攝像頭)激率,錄音設(shè)備(麥克風(fēng))。只用于配置
> 3. 根據(jù)音頻/視頻硬件設(shè)備(AVCaptureDevice)創(chuàng)建音頻/視頻硬件輸入數(shù)據(jù)對象(AVCaptureDeviceInput)勿决,專門管理數(shù)據(jù)輸入乒躺。
> 4. 創(chuàng)建視頻輸出數(shù)據(jù)管理對象(AVCaptureVideoDataOutput),并且設(shè)置樣品緩存代理(setSampleBufferDelegate)就可以通過它拿到采集到的視頻數(shù)據(jù)
> 5. 創(chuàng)建音頻輸出數(shù)據(jù)管理對象(AVCaptureAudioDataOutput)低缩,并且設(shè)置樣品緩存代理(setSampleBufferDelegate)就可以通過它拿到采集到的音頻數(shù)據(jù)
> 6. 將數(shù)據(jù)輸入對象AVCaptureDeviceInput嘉冒、數(shù)據(jù)輸出對象AVCaptureOutput添加到媒體會(huì)話管理對象AVCaptureSession中,就會(huì)自動(dòng)讓音頻輸入與輸出和視頻輸入與輸出產(chǎn)生連接.
> 7. 創(chuàng)建視頻預(yù)覽圖層AVCaptureVideoPreviewLayer并指定媒體會(huì)話,添加圖層到顯示容器layer中
> 8. 啟動(dòng)AVCaptureSession咆繁,只有開啟讳推,才會(huì)開始輸入到輸出數(shù)據(jù)流傳輸
其中`AVCaptureAudioDataOutput`、`AVCaptureVideoDataOutput`包含兩個(gè)代理方法玩般,可以一直監(jiān)聽捕獲屬性银觅。
```
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
if (self.videoConnection == connection)
{
NSLog(@"采集到視頻");
}
else if(self.audioConnection == connection)
{
NSLog(@"采集到音頻");
}
}
// 丟失幀會(huì)調(diào)用這里
- (void)captureOutput:(AVCaptureOutput *)captureOutput didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection NS_AVAILABLE(10_7, 6_0)
{
NSLog(@"丟失幀");
}
```
不清楚可以看 : [官方文檔](https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html)
###2.3 捕捉圖片
`AVCaptureStillImageOutput`可以將捕獲到的Video轉(zhuǎn)換為圖片。
> 1. 創(chuàng)建device
> 2. 根據(jù)device創(chuàng)建deviceInput
> 3. 添加deviceInput進(jìn)session
> 4. 添加預(yù)覽圖層
> 5. 添加deviceOutput進(jìn)session
> 6. 調(diào)用AVCaptureConnection生成圖片
###2.4 捕捉視頻
`AVCaptureMovieFileOutput` 可以將捕捉到的視頻輸出到磁盤坏为【柯浚可以設(shè)置錄制最長時(shí)限或錄制到特定大小,還可以配置成保留最小可用磁盤空間匀伏。
> 1. 創(chuàng)建device
> 2. 根據(jù)device創(chuàng)建deviceInput
> 3. 添加deviceInput進(jìn)session
> 4. 添加預(yù)覽圖層
> 5. 添加deviceOutput進(jìn)session
> 6. 調(diào)用AVCaptureMovieFileOutput把視頻寫入文件
`AVCaptureMovieFileOutput`包含有幾個(gè)代理方法洒忧。分別是`視頻開始錄制`,`視頻暫停`,`視頻恢復(fù)`, `視頻將要錄制完成`, `視頻錄制完成`。
#2.5 采集音頻視頻按幀輸出流程解析
> 1.找到物理設(shè)備攝像頭_inputCamera帘撰、麥克風(fēng)_microphone跑慕,創(chuàng)建攝像頭輸入videoInput和麥克風(fēng)輸入audioInput;
>
> 2.設(shè)置videoInput和audioInput為_captureSession的輸入,同時(shí)設(shè)置videoOutput和audioOutput為_captureSession的輸出核行,并且設(shè)置videoOutput和audioOutput的輸出delegate牢硅;
>
> 3._captureSession調(diào)用startRunning,開始捕獲信號芝雪;
>
> 4.音頻數(shù)據(jù)到達(dá)减余,把數(shù)據(jù)轉(zhuǎn)發(fā)給之前設(shè)置的audioEncodingTarget,并通過調(diào)用assetWriterAudioInput的appendSampleBuffer方法寫入音頻數(shù)據(jù)惩系;
>
> 5.視頻數(shù)據(jù)到達(dá)位岔,視頻數(shù)據(jù)傳入響應(yīng)鏈抒抬,經(jīng)過處理后通過assetWriterPixelBufferInput的appendSampleBuffer方法寫入視頻數(shù)據(jù);
>
> 6.選擇保存后晤柄,文件通過ALAssertLibrary寫入手機(jī)照片庫。
流程圖:
![](捕獲流程.png)
###2.6 Demo在這里
代碼 : [捕獲音視頻Demo](https://github.com/tiantianlan/LiveExplanation/tree/master/%E6%8D%95%E8%8E%B7%E9%9F%B3%E8%A7%86%E5%B1%8F)
##3. GPUImage
`前面好像沒看懂芥颈,可以看這里嗎惠勒?`
可以纠屋,GPUImage對AVFundation進(jìn)行了一層封裝,就算你不會(huì)前面的也沒關(guān)系献丑。
###3.1 基本概念
`GPU` 手機(jī)或者電腦用于處理圖像渲染的硬件
`OpenGL ES` 一套圖形與硬件接口,用于把處理好的圖片顯示到屏幕上。
`GPUImage` 是一個(gè)基于OpenGL ES 2.0圖像和視頻處理的開源iOS框架黔龟,提供各種各樣的圖像處理濾鏡,并且支持照相機(jī)和攝像機(jī)的實(shí)時(shí)濾鏡,內(nèi)置120多種濾鏡效果倒得,并且能夠自定義圖像濾鏡潮梯。
`GPUImage` 是一個(gè)基于OpenGL ES 2.0圖像和視頻處理的開源iOS框架耙旦,提供各種各樣的圖像處理濾鏡,并且支持照相機(jī)和攝像機(jī)的實(shí)時(shí)濾鏡萝究,內(nèi)置120多種濾鏡效果免都,并且能夠自定義圖像濾鏡。
`濾鏡處理的原理` 就是把靜態(tài)圖片或者視頻的每一幀進(jìn)行圖形變換再顯示出來帆竹。它的本質(zhì)就是像素點(diǎn)的坐標(biāo)和顏色變化
###3.1 利用GPUImage處理直播過程中美顏流程
`采集視頻 => 獲取每一幀圖片 => 濾鏡處理 => GPUImageView展示`
![](美顏流程.png)
###3.2 處理畫面原理
GPUImage采用鏈?zhǔn)椒绞絹硖幚懋嬅?通過addTarget:方法為鏈條添加每個(gè)環(huán)節(jié)的對象绕娘,處理完一個(gè)target,就會(huì)把上一個(gè)環(huán)節(jié)處理好的圖像數(shù)據(jù)傳遞下一個(gè)target去處理,稱為GPUImage處理鏈栽连。
一般的target可以分為兩類:
`中間環(huán)節(jié)`的target险领,一般是指各種filter侨舆,是GPUImageFilter或者是子類
`最終環(huán)節(jié)`的target,GPUImageView 用于顯示到屏幕上或者GPUImageMovieWriter寫成視頻文件绢陌。
主要分為三個(gè)環(huán)節(jié):
`source(視頻挨下,圖片源) => filter(濾鏡) => final target(處理后的視頻、圖片)`
###3.3 美顏原理
`磨皮(GPUImageBilateralFilter)`:本質(zhì)就是讓像素點(diǎn)模糊下面,可以使用高斯模糊复颈,但是可能導(dǎo)致邊緣會(huì)不清晰,用雙邊濾波(Bilateral Filter) 沥割,有針對性的模糊像素點(diǎn)耗啦,能保證邊緣不被模糊。
`美白(GPUImageBrightnessFilter)`:本質(zhì)就是提高亮度机杜。
###3.4 GPUImage源對象
GPUImage的數(shù)據(jù)源只能是4類:
`GPUImageVideoCamera` ios攝像頭的實(shí)時(shí)美顏帜讲。GPUImageVideoCamera是GPUImageOutput的子類,提供來自攝像頭的圖像數(shù)據(jù)作為源數(shù)據(jù)椒拗,一般是響應(yīng)鏈的源頭似将。
`GPUImageStillCamera` 相機(jī)拍照
`GPUImagePicture` 處理靜止圖像
`GPUImageMovie` 電影
###3.5 用法
>1. 創(chuàng)建過濾器
>2. 創(chuàng)建源對象
>3. 把過濾器添加到源對象
>4. 生成target
靜態(tài)圖片處理:
```
UIImage *inputImage = [UIImage imageNamed:@"105"];
// 創(chuàng)建過濾器
GPUImageBrightnessFilter *filter = [[GPUImageBrightnessFilter alloc] init];
filter.brightness = 0.5;
[filter forceProcessingAtSize:inputImage.size];
[filter useNextFrameForImageCapture]; // 告訴系統(tǒng)從后來捕獲過濾器
// 處理靜止的圖像
GPUImagePicture *stillPic = [[GPUImagePicture alloc] initWithImage:inputImage];
[stillPic addTarget:filter]; //添加過濾器
[stillPic processImage]; // 執(zhí)行渲染
UIImage *newImage = [filter imageFromCurrentFramebuffer];
UIImageView *imageView = [[UIImageView alloc] initWithImage:newImage];
[imageView sizeToFit];
[self.view addSubview:imageView];
imageView.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, CGRectGetHeight(self.view.frame)/2);
```
實(shí)時(shí)美顏處理:
```
// 創(chuàng)建視頻源
GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPresetHigh cameraPosition:AVCaptureDevicePositionBack];
// 設(shè)置方向
videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
// 創(chuàng)建預(yù)覽View
GPUImageView *videoPreview = [[GPUImageView alloc] initWithFrame:self.view.bounds];
[self.view insertSubview:videoPreview atIndex:0];
// 添加預(yù)覽圖層到源
GPUImageBeautifyFilter *fiter = [[GPUImageBeautifyFilter alloc] init];
[_videoCamera addTarget:fiter];
[fiter addTarget:self.videoPreview];
// 開始采集視頻
[videoCamera startCameraCapture];
```
到這里,僅僅是屏幕顯示的內(nèi)容有濾鏡效果蚀苛,而作為直播應(yīng)用在验,還需要輸出帶有美顏效果的視頻流。
我們需要使用`GPUImageMovieWriter`類堵未,才能處理視頻流腋舌。
核心思路:
通過GPUImageVideoCamera采集視頻和音頻信息,音頻信息直接發(fā)送給`GPUImageMovieWriter`渗蟹,視頻信息傳入響應(yīng)鏈作為源頭块饺,渲染后的視頻再寫入`GPUImageMovieWriter`,同時(shí)通過`GPUImageView`顯示在屏幕上雌芽。只需要`addTarget`就可以添加`GPUImageMovieWriter`;
![](GPUImageMovieWriter.png)
###3.6 實(shí)例代碼在這里
[美顏的使用](https://github.com/tiantianlan/LiveExplanation/tree/master/GPUImage)
##4. 音視頻編碼授艰,解碼
這一章太難了,以后再寫世落。
### VideoToolBox
### AudioToolBox
##5. 流媒體服務(wù)器
國內(nèi)外有很多好用的流媒體服務(wù)區(qū)淮腾。這里為了方便搭建我們采用`nginx+RTMP`搭建流媒體服務(wù)器。
###5.1 MAC環(huán)境搭建
[MACOS上搭建nginx+rtmp環(huán)境](https://github.com/tiantianlan/LiveExplanation/blob/master/MACOS%E4%B8%8A%E6%90%AD%E5%BB%BAnginx%2Brtmp%E7%8E%AF%E5%A2%83.md)
###5.2 Centos環(huán)境搭建
[Centos下搭建的nginx + RTMP環(huán)境](https://github.com/tiantianlan/LiveExplanation/blob/master/Centos%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.md)
###5.3 服務(wù)端常用技術(shù)
`CDN` 直播數(shù)據(jù)上傳到服務(wù)器后屉佳,觀看直播的人比較多来破,服務(wù)器是承受不了的,會(huì)將數(shù)據(jù)分發(fā)到CDN忘古,觀眾直接去CDN獲取數(shù)據(jù)徘禁。減少服務(wù)器的負(fù)載。
`負(fù)載均衡` 由多臺(tái)服務(wù)器組成一個(gè)服務(wù)器集群髓堪,每次請求的時(shí)候送朱,會(huì)根據(jù)服務(wù)器負(fù)載選擇處理請求的服務(wù)器娘荡。
##6. 推流
###6.1 推流協(xié)議的選擇
[HLS和RTMP](https://github.com/tiantianlan/LiveExplanation/blob/master/%E7%9B%B4%E6%92%AD%E5%8D%8F%E8%AE%AE%E7%9A%84%E9%80%89%E6%8B%A9.md)
###6.2 推流原理
在iOS設(shè)備上進(jìn)行各推流的話,是通過AVCaptureSession這么一個(gè)捕捉會(huì)話驶沼,指定兩個(gè)AVCaptureDevice 也就是iOS的攝像頭和麥克風(fēng)炮沐,獲取個(gè)原始視頻和音頻,然后需要進(jìn)行個(gè)H.264的視頻編碼和AAC的音頻編碼回怜,再將編碼后的數(shù)據(jù)整合成一個(gè)音視頻包大年,通過rmtp推送到nginx服務(wù)器
###6.3 librtmp
這個(gè)參考資料很少。不過大部分都采用的這個(gè)玉雾。
因?yàn)樯婕疤郈/C++這里不討論翔试。
參考:[https://my.oschina.net/jerikc/blog/501948](https://my.oschina.net/jerikc/blog/501948)
##7. 音視頻播放
###7.1 播放框架的選擇
iOS的播放框架主要有以下三種:
>1. AVPlayer 可以播放本地、遠(yuǎn)程視頻复旬,可以自定義UI進(jìn)行控制
>2. AVPlayerViewController 自帶播放控制UI垦缅,不能自定義UI
>3. MPMoviePlayerController,MPMoviePlayerViewController (iOS9后棄用)
如果只是簡單的播放視頻驹碍,選擇`AVPlayerViewController`壁涎,如果想自定義播放器,選擇`AVPlayer`志秃。
###7.2 AVPlayer
AVPlayer是一個(gè)用來播放基于時(shí)間的流媒體控制對象怔球。支持播放從本地、分布下載或通過HTTP Live Streaming協(xié)議得到的流媒體浮还。
AVPlayer只管理一個(gè)單獨(dú)資源的播放竟坛,不過框架還提供了AVPlayer的一個(gè)子類AVQueuePlayer,可以用來管理一個(gè)資源隊(duì)列碑定。當(dāng)你需要在一個(gè)序列中播放多個(gè)條目或者為音頻、視頻資源設(shè)置播放循環(huán)時(shí)可以使用該子類又官。
AVPlayer視頻播放使用步驟:
>1. 創(chuàng)建視頻資源地址URL延刘,可以是網(wǎng)絡(luò)URL
>2. 通過URL創(chuàng)建視頻內(nèi)容對象`AVPlayerItem`,一個(gè)視頻對應(yīng)一個(gè)`AVPlayerItem`
>3. 創(chuàng)建`AVPlayer`視頻播放對象,需要一個(gè)`AVPlayerItem`進(jìn)行初始化
>4. 創(chuàng)建`AVPlayerLayer`播放圖層對象六敬,添加到現(xiàn)實(shí)視圖上去
>5. 添加KVO監(jiān)聽碘赖。 監(jiān)聽到AVPlayerItemStatusReadyToPlay的時(shí)候調(diào)用play方法
[AVPlayer的使用](https://github.com/tiantianlan/LiveExplanation/tree/master/AVPlayer)
###7.3 AVPlayerViewController
`AVPlayerViewController`屬于`AV Kit`,它是`UIViewController的子類`,用于展示并控制AVPlayer實(shí)例的播放外构。
`AVPlayerViewController `類使用步驟
>1. 創(chuàng)建URL
>2. 創(chuàng)建AVPlayerViewController普泡,并根據(jù)URL設(shè)置player屬性
>3. 調(diào)用play方法
[AVPlayerViewController的使用](https://github.com/tiantianlan/LiveExplanation/tree/master/AVKit)
Xcode8模擬器可能有問題,打開播放不了审编。
###8.開源框架
前面所講都有第三方框架支持撼班。采集、美顏垒酬、推流有`LFLiveKit`, 拉流播放有`IJKMediaFramework`砰嘁。
[`LFLiveKit`](https://github.com/LaiFengiOS/LFLiveKit) : LFLiveKit是iOS版開源RTMP流SDK件炉。他支持后臺(tái)錄制、美顏功能矮湘、支持h264斟冕、AAC硬編碼,動(dòng)態(tài)改變速率缅阳,RTMP傳輸?shù)?/p>
[`IJKMediaFramework`](https://github.com/Bilibili/ijkplayer) : ijkplayer是B站開源的一款視頻直播框架磕蛇,它是基于ffmpeg。 如果從github下載是需要編譯十办。參考地址:[http://www.reibang.com/p/1f06b27b3ac0](http://www.reibang.com/p/1f06b27b3ac0)
個(gè)人實(shí)驗(yàn)只需要配置Nginx+RTMP服務(wù)
這里我采用這兩個(gè)第三方框架寫了一個(gè)直播秀撇,包含在線觀看直播,和直播推流,支持在線美顏橘洞,前后攝像頭切換等你需要:
>1. 搭建`Nginx+RTMP環(huán)境`:[MAC](https://github.com/tiantianlan/LiveExplanation/blob/master/MACOS%E4%B8%8A%E6%90%AD%E5%BB%BAnginx%2Brtmp%E7%8E%AF%E5%A2%83.md) 或者? [Centos](https://github.com/tiantianlan/LiveExplanation/blob/master/Centos%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.md)
>2. 下載項(xiàng)目真機(jī)運(yùn)行捌袜。[https://github.com/tiantianlan/miaoboDemo](https://github.com/tiantianlan/miaoboDemo)
登陸界面
![](miaobo1.png)
主頁
![](miaobo2.png)
直播頁面
![](miaobo3.png)
參考文章:
>1. [知乎 如何搭建一個(gè)完整的直播系統(tǒng)](https://www.zhihu.com/question/42162310)
>2. [袁崢技術(shù)博客](http://www.reibang.com/users/b09c3959ab3b/latest_articles)
>3. [GPUImage 基于GPU加速的圖形和視頻處理庫](http://www.ios122.com/2015/08/gpuimage/)
>
>4. [iOS中為直播APP集成美顏功能](http://news.h5.com.cn/ios/49696.html)
>
>5. [iOS視頻直播~推流、拉流原理](http://www.reibang.com/p/e516a5b31480)
>
>6. [關(guān)于視頻直播技術(shù)炸枣,你想要知道的都在這里了](http://www.reibang.com/p/ddb640ac4fec)
>
>7. [macOS上搭建Nginx+rtmp服務(wù)器](https://www.xsd.me/mac_nginx_rtmp_server.html)