前言
最近剛做完一個直播類的項目,在視頻這塊也有一定研究,下面總結下。
過程
首先視頻項目一般要求定制化,用UIImagePickerController不符合需求,所以基本上都是用AVFoundation自定義相機,在網上一搜,還是查到比較多參考博文的,其中簡書上的這篇iOS-AVFoundation自定義相機詳解比較詳細(內含Demo),十分值得參考。
另外蘋果官方也提供了一個Demo蘋果官方Demo-RosyWriter,后來我對比過兩個Demo發現,其實簡書那篇的Demo也是參考蘋果官方的再深入研究,所以在開發過程中以這兩個Demo參考基本夠用了。
AVFoundation 中視頻相關類:
會話
AVCaptureSession
輸入
AVCaptureDeviceInput
輸出
AVCaptureConnection
AVCaptureConnection
AVCaptureVideoDataOutput
AVCaptureStillImageOutput
AVCaptureMovieFileOutput
文件寫入
AVAssetWriter
AVAssetWriterInput
自定義AVFoundation主要為以下5個步驟:
1.創建session(捕捉會話)
2.創建device input(捕捉設備輸入)
3.預覽view
4.創建capture output(捕捉的輸出)
5.拍照、錄視頻(元數據轉成圖片或文件)
詳細代碼就不說了,下面主要說下我做的過程中遇到的一下問題:
1.實時視頻流AVCaptureVideoDataOutput和系統視頻錄制功能AVCaptureMovieFileOutput沖突,不能同時使用。AVCaptureMovieFileOutput是把音頻和視頻合成并輸出一個完整的音視頻文件,代碼比較簡單,但定制化功能少;而AVCaptureVideoDataOutput需要配合AVCaptureAudioDataOutput使用,分別輸出音頻和視頻兩條軌道的數據,并用AVAssetWriter寫入,代碼比較復雜,但定制功能多,推薦使用。
2.關于碼率
以上蘋果和簡書上的demo都是通過分辨率計算碼率,代碼如下:
//計算像素
int numPixels = dimensions.width * dimensions.height;
int bitsPerSecond;
NSLog( @"No video settings provided, using default settings" );
// Assume that lower-than-SD resolutions are intended for streaming, and use a lower bitrate
if ( numPixels < ( 640 * 480 ) ) {
bitsPerPixel = 4.05; // This bitrate approximately matches the quality produced by AVCaptureSessionPresetMedium or Low.
}
else {
bitsPerPixel = 10.1; // This bitrate approximately matches the quality produced by AVCaptureSessionPresetHigh.
}
//碼率
bitsPerSecond = numPixels * bitsPerPixel;
NSDictionary *compressionProperties = @{ AVVideoAverageBitRateKey : @(bitsPerSecond),
AVVideoExpectedSourceFrameRateKey : @(30),
AVVideoMaxKeyFrameIntervalKey : @(30) };
如想自定義碼率可在以上代碼處設置,另外奉上開發過程中找到的一篇關于碼率的文章視頻質量,分辨率以及碼率之間的關系。
另外,關于視頻的壓縮,我還特意和微信的對比過,在網上搜到這篇文章Compress in iOS,我是參照以上這篇文章,把分辨率設為960*540,再調整碼率,使視頻文件大小與微信相仿。
3.關于切換攝像頭
用上面說到的Demo,切換攝像頭時,你會發現屏幕會黑一下,體驗效果很不好,改良如下:
//切換攝像頭之前,先停止session
[_captureSession stopRunning];
//給攝像頭的切換添加翻轉動畫
CATransition *animation = [CATransition animation];
animation.duration = .5f;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = @"oglFlip";
animation.subtype = kCATransitionFromLeft;//動畫翻轉方向
[self.previewLayer addAnimation:animation forKey:nil];
//接下來開始切換攝像頭
......
由于我也是在別人的Demo基礎上改的代碼,所以我自己就不貼上代碼,稍微研究下簡書和蘋果上的Demo,再結合自己的需求,相信很快就能做出來了。
結束
學習之路,與君共勉。