第一部分: 視頻采集----AVCaptureSession
1.1 視頻采集的流程
AVCaptureSession通過把設(shè)備的麥克風(fēng)/攝像頭(AVCaptureDevice)實(shí)例化成數(shù)據(jù)流輸入對(duì)象(AVCaptureDeviceInput)后,再通過建立連接(AVCaptionConnection)將錄制數(shù)據(jù)通過數(shù)據(jù)流輸出對(duì)象(AVCaptureOutput)導(dǎo)出,而錄制的時(shí)候咱們可以同步預(yù)覽當(dāng)前的錄制界面(AVCaptureVideoPreviewLayer).
1.2 視頻采集中的主要對(duì)象
1. AVCaptureSession: 是設(shè)備音頻/視頻整個(gè)錄制期間的管理者;
2. AVCaptureDevice: 設(shè)備管理者: 操作閃光燈,手電筒,聚焦模式等;
3. AVCaptureDeviceInput: 是錄制期間輸入流數(shù)據(jù)的管理對(duì)象;
4. AVCaptionConnection: 是將 輸入流/輸出流 連接起來的連接對(duì)象,視頻/音頻穩(wěn)定,預(yù)覽與錄制方向一致都在這里設(shè)置,還有audioChannels聲道;
5. AVCaptureOutput: 是 輸出流數(shù)據(jù) 的管理對(duì)象,通過頭文件可以看到有很多子類,而我們通常也使用其子類;
6. AVCaptureVideoPreviewLayer: 是一個(gè)CALyer,可以讓我們預(yù)覽拍攝過程中的圖像.
本文最終實(shí)現(xiàn)目標(biāo)---音視頻采集/壓縮:
1.3 設(shè)備授權(quán)
錄制視頻需真機(jī), 因此必須首先獲得授權(quán);用以下代碼來判斷, 返回結(jié)果為枚舉值
;
//此處獲取攝像頭授權(quán), 是一個(gè)枚舉值
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]
枚舉值---AVAuthorizationStatus為:
typedef NS_ENUM(NSInteger, AVAuthorizationStatus) {
//未進(jìn)行授權(quán)選擇
AVAuthorizationStatusNotDetermined = 0,
//未授權(quán)拓劝,且用戶無法更新慰照,如家長控制情況下
AVAuthorizationStatusRestricted,
//用戶拒絕App使用
AVAuthorizationStatusDenied,
//已授權(quán)捍岳,可使用
AVAuthorizationStatusAuthorized
} NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
1.4 AVCaptureSession對(duì)象創(chuàng)建
- (void)initAVCapture{
_captureSession = [[AVCaptureSession alloc] init];
//設(shè)置錄像的分辨率
if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) {
[_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh];
}
/****************************/
[_captureSession beginConfiguration];
/*-----------------------------*/
//攝像頭<枚舉值:前后>
_videoDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:AVCaptureDevicePositionBack];
//視頻的輸入輸出
[self videoIO];
//音頻的輸入<錄制視頻時(shí)不需要輸出>
[self audioIO];
//錄制的同時(shí)播放
[self previewLayer];
/*-----------------------------*/
[_captureSession commitConfiguration];
//開啟會(huì)話-->注意,不等于開始錄制
[_captureSession startRunning];
}
注釋:
**1. [_captureSession beginConfiguration/commitConfiguration];
**參考蘋果官方文檔中所述:
After calling beginConfiguration, you can for example add or remove outputs, alter
the sessionPreset, or configure individual capture input or output properties. No changes
are actually made until you invoke commitConfiguration(), at which time they are applied together.
1.5 視頻的輸入和輸出--AVCaptureDeviceInput/AVCaptureMovieFileOutput
//視頻的輸入和輸出
- (void)videoIO{{
/*---------------input-------------------------*/
NSError *videoError;
// 視頻輸入對(duì)象
// 根據(jù)輸入設(shè)備初始化輸入對(duì)象袁辈,用戶獲取輸入數(shù)據(jù)
_videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:_videoDevice error:&videoError];
if (videoError) {
NSLog(@"---- 取得攝像頭設(shè)備時(shí)出錯(cuò) ------ %@",videoError);
return;
}
// 將視頻輸入對(duì)象添加到會(huì)話 (AVCaptureSession) 中
if ([_captureSession canAddInput:_videoInput]) {
[_captureSession addInput:_videoInput];
}
/*---------------output------------------------*/
// 拍攝視頻輸出對(duì)象
// 初始化輸出設(shè)備對(duì)象挨措,用戶獲取輸出數(shù)據(jù)
_movieOutput = [[AVCaptureMovieFileOutput alloc] init];
if ([_captureSession canAddOutput:_movieOutput]) {
[_captureSession addOutput:_movieOutput];
AVCaptureConnection *captureConnection = [_movieOutput connectionWithMediaType:AVMediaTypeVideo];
// 視頻穩(wěn)定設(shè)置
if ([captureConnection isVideoStabilizationSupported]) {
captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
}
captureConnection.videoScaleAndCropFactor = captureConnection.videoMaxScaleAndCropFactor;
}
}
1.6 音頻的輸入---AVCaptureDeviceInput
#pragma mark 音頻的輸入輸出
- (void)audioIO{
/*-------------input---------*/
NSError *audioError;
// 添加一個(gè)音頻輸入設(shè)備
_audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
// 音頻輸入對(duì)象
_audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:_audioDevice error:&audioError];
if (audioError) {
NSLog(@"取得錄音設(shè)備時(shí)出錯(cuò) ------ %@",audioError);
return;
}
// 將音頻輸入對(duì)象添加到會(huì)話 (AVCaptureSession) 中
if ([_captureSession canAddInput:_audioInput]) {
[_captureSession addInput:_audioInput];
}
}
1.7 展示的錄制視頻
- (void)previewLayer{
[self.view layoutIfNeeded];
// 通過會(huì)話 (AVCaptureSession) 創(chuàng)建預(yù)覽層
_captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
_captureVideoPreviewLayer.frame = self.view.layer.bounds;
//有時(shí)候需要拍攝完整屏幕大小的時(shí)候可以修改這個(gè)
// _captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
// 如果預(yù)覽圖層和視頻方向不一致,可以修改這個(gè)
_captureVideoPreviewLayer.connection.videoOrientation = [_movieOutput connectionWithMediaType:AVMediaTypeVideo].videoOrientation;
_captureVideoPreviewLayer.position = CGPointMake(self.videoView.frame.size.width*0.5,self.videoView.frame.size.height*0.5);
// 顯示在視圖表面的圖層
CALayer *layer = self.videoView.layer;
layer.masksToBounds = true;
[self.view layoutIfNeeded];
[layer addSublayer:_captureVideoPreviewLayer];
}
第二部分
- 視頻壓縮
1.1需要引入系統(tǒng)框架--AssetsLibrary.framework與AVKit.framework
# 壓縮視頻
- (IBAction)compressVideo:(id)sender{
NSLog(@"開始?jí)嚎s,壓縮前大小 %f MB",[self fileSize:self.videoUrl]);
self.saveBtn.enabled = NO;
AVURLAsset *avAsset = [[AVURLAsset alloc] initWithURL:self.videoUrl options:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality]) {
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:AVAssetExportPreset640x480];
exportSession.outputURL = [self compressedURL];
//優(yōu)化網(wǎng)絡(luò)
exportSession.shouldOptimizeForNetworkUse = true;
//轉(zhuǎn)換后的格式
exportSession.outputFileType = AVFileTypeMPEG4;
//異步導(dǎo)出
[exportSession exportAsynchronouslyWithCompletionHandler:^{
// 如果導(dǎo)出的狀態(tài)為完成
if ([exportSession status] == AVAssetExportSessionStatusCompleted) {
NSLog(@"壓縮完畢,壓縮后大小 %f MB",[self fileSize:[self compressedURL]]);
[self saveVideo:[self compressedURL]];
}else{
NSLog(@"當(dāng)前壓縮進(jìn)度:%f",exportSession.progress);
}
self.saveBtn.enabled = YES;
}];
}
}
壓縮是使用的AVURLAsset的流程圖如下:
2.保存暫時(shí)使用的是ALAssetsLibrary;
ALAssetsLibrary提供了我們對(duì)iOS設(shè)備中的相片汗洒、視頻的訪問议纯。
//ALAssetsLibrary提供了我們對(duì)iOS設(shè)備中的相片、視頻的訪問仲翎。
- (void)saveVideo:(NSURL *)outputFileURL
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"保存視頻失敗:%@",error);
} else {
NSLog(@"保存視頻到相冊成功");
}
}];
}
注釋
PhotoKit是蘋果推出的用于替代ALAssetsLibrary的框架痹扇。
PhotoKit為使用照片和視頻資源提供了新的API。PhotoKit還包含一個(gè)線程安全架構(gòu)用以獲取溯香、緩存縮略圖和全尺寸圖片鲫构,請求資產(chǎn)更改,遵守其他應(yīng)用所做的變化玫坛,以及對(duì)資產(chǎn)內(nèi)容進(jìn)行可恢復(fù)的編輯结笨。
iOS直播---音/視頻解碼(四)
iOS直播---音/視頻編碼(三)
更多精彩內(nèi)容請關(guān)注“IT實(shí)戰(zhàn)聯(lián)盟”哦~~~
參考
1.蘋果官方文檔AVCaptureSession_Class
2. iOS 自定義相機(jī), UIImagePickerController && AVCaptureSession (附微信小視頻模仿demo)
3. AVFoundation編程指南1-使用 Assets
4. AVFoundation編程指南2-用AVPlayer播放視頻
5. iOS --- 使用PhotoKit代替ALAssetsLibrary來管理相冊資源