在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ 在 iOS 上捕獲視頻
與四軸無(wú)人機(jī)的通訊
在沙盒中編寫(xiě)腳本
結(jié)構(gòu)體和值類(lèi)型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測(cè)試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動(dòng)開(kāi)發(fā)
Collection View 動(dòng)畫(huà)
截圖測(cè)試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個(gè)完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動(dòng)布局工具箱
動(dòng)畫(huà)
為 iOS 7 重新設(shè)計(jì) App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實(shí)例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類(lèi)
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動(dòng)畫(huà)解釋
響應(yīng)式 Android 應(yīng)用
初識(shí) TextKit
客戶(hù)端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項(xiàng)目介紹
Swift 的強(qiáng)大之處
測(cè)試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機(jī)制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計(jì)優(yōu)雅的移動(dòng)游戲
繪制像素到屏幕上
相機(jī)與照片
音頻 API 一覽
交互式動(dòng)畫(huà)
常見(jiàn)的后臺(tái)實(shí)踐
糟糕的測(cè)試
避免濫用單例
數(shù)據(jù)模型和模型對(duì)象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場(chǎng)
照片框架
響應(yīng)式視圖
Square Register 中的擴(kuò)張
DTrace
基礎(chǔ)集合類(lèi)
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點(diǎn)互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計(jì)的藝術(shù)
導(dǎo)航應(yīng)用
線程安全類(lèi)的設(shè)計(jì)
置換測(cè)試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無(wú)人機(jī)項(xiàng)目
Mach-O 可執(zhí)行文件
UI 測(cè)試
值對(duì)象
活動(dòng)追蹤
依賴(lài)注入
Swift
項(xiàng)目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測(cè)試 View Controllers
訪談
收據(jù)驗(yàn)證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場(chǎng)
游戲
調(diào)試核對(duì)清單
View Controller 容器
學(xué)無(wú)止境
XCTest 測(cè)試實(shí)戰(zhàn)
iOS 7
Layer 中自定義屬性的動(dòng)畫(huà)
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲(chǔ)
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺(jué)
Artsy
照片擴(kuò)展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫(kù)支持
Fetch 請(qǐng)求
導(dǎo)入大數(shù)據(jù)集
iOS 開(kāi)發(fā)者的 Android 第一課
iOS 上的相機(jī)捕捉
語(yǔ)言標(biāo)簽
同步案例學(xué)習(xí)
依賴(lài)注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識(shí)別
玩轉(zhuǎn)字符串
相機(jī)工作原理
Build 過(guò)程

在 iOS 上捕獲視頻

隨著每一代 iPhone 處理能力和相機(jī)硬件配置的提高,使用它來(lái)捕獲視頻也變得更加有意思。它們小巧,輕便,低調(diào),而且與專(zhuān)業(yè)攝像機(jī)之間的差距已經(jīng)變得非常小,小到在某些情況下,iPhone 可以真正替代它們。

這篇文章討論了關(guān)于如何配置視頻捕獲管線 (pipeline) 和最大限度地利用硬件性能的一些不同選擇。 這里有個(gè)使用了不同管線的樣例 app,可以在 GitHub 查看。

UIImagePickerController

目前,將視頻捕獲集成到你的應(yīng)用中的最簡(jiǎn)單的方法是使用 UIImagePickerController。這是一個(gè)封裝了完整視頻捕獲管線和相機(jī) UI 的 view controller。

在實(shí)例化相機(jī)之前,首先要檢查設(shè)備是否支持相機(jī)錄制:

if ([UIImagePickerController
       isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
    NSArray *availableMediaTypes = [UIImagePickerController
      availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
    if ([availableMediaTypes containsObject:(NSString *)kUTTypeMovie]) {
        // 支持視頻錄制
    }
}

然后創(chuàng)建一個(gè) UIImagePickerController 對(duì)象,設(shè)置好代理便于進(jìn)一步處理錄制好的視頻 (比如存到相冊(cè)) 以及對(duì)于用戶(hù)關(guān)閉相機(jī)作出響應(yīng):

UIImagePickerController *camera = [UIImagePickerController new];
camera.sourceType = UIImagePickerControllerSourceTypeCamera;
camera.mediaTypes = @[(NSString *)kUTTypeMovie];
camera.delegate = self;

這是你實(shí)現(xiàn)一個(gè)功能完善的攝像機(jī)所需要寫(xiě)的所有代碼。

相機(jī)配置

UIImagePickerController 提供了額外的配置選項(xiàng)。

通過(guò)設(shè)置 cameraDevice 屬性可以選擇一個(gè)特定的相機(jī)。這是一個(gè) UIImagePickerControllerCameraDevice 枚舉,默認(rèn)情況下是 UIImagePickerControllerCameraDeviceRear,你也可以把它設(shè)置為 UIImagePickerControllerCameraDeviceFront。每次都應(yīng)事先確認(rèn)你想要設(shè)置的相機(jī)是可用的:

UIImagePickerController *camera = …
if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]) {
    [camera setCameraDevice:UIImagePickerControllerCameraDeviceFront];
}

videoQuality 屬性用于控制錄制視頻的質(zhì)量。它允許你設(shè)置一個(gè)特定的編碼預(yù)設(shè),從而改變視頻的比特率和分辨率。以下是六種預(yù)設(shè):

enum {
   UIImagePickerControllerQualityTypeHigh             = 0,
   UIImagePickerControllerQualityTypeMedium           = 1,  // default  value
   UIImagePickerControllerQualityTypeLow              = 2,
   UIImagePickerControllerQualityType640x480          = 3,
   UIImagePickerControllerQualityTypeIFrame1280x720   = 4,
   UIImagePickerControllerQualityTypeIFrame960x540    = 5
};
typedef NSUInteger  UIImagePickerControllerQualityType;

前三種為相對(duì)預(yù)設(shè) (low, medium, high)。這些預(yù)設(shè)的編碼配置會(huì)因設(shè)備不同而不同。如果選擇 high,那么你選定的相機(jī)會(huì)提供給你該設(shè)備所能支持的最高畫(huà)質(zhì)。后面三種是特定分辨率的預(yù)設(shè) (640x480 VGA, 960x540 iFrame, 和 1280x720 iFrame)。

自定義 UI

就像上面提到的,UIImagePickerController 自帶一套相機(jī) UI,可以直接使用。然而,你也可以自定義相機(jī)的控件,通過(guò)隱藏默認(rèn)控件,然后創(chuàng)建帶有控件的自定義視圖,并覆蓋在相機(jī)預(yù)覽圖層上面:

UIView *cameraOverlay = …
picker.showsCameraControls = NO;
picker.cameraOverlayView = cameraOverlay;

然后你需要將你覆蓋層上的控件關(guān)聯(lián)上 UIImagePickerController 的控制方法 (比如,startVideoCapturestopVideoCapture)。

AVFoundation

如果你想要更多關(guān)于處理捕獲視頻的方法,而這些方法是 UIImagePickerController 所不能提供的,那么你需要使用 AVFoundation。

AVFoundation 中關(guān)于視頻捕獲的主要的類(lèi)是 AVCaptureSession。它負(fù)責(zé)調(diào)配影音輸入與輸出之間的數(shù)據(jù)流:

http://wiki.jikexueyuan.com/project/objc/images/23-1.svg" alt="" />

使用一個(gè) capture session,你需要先實(shí)例化,添加輸入與輸出,接著啟動(dòng)從輸入到輸出之間的數(shù)據(jù)流:

AVCaptureSession *captureSession = [AVCaptureSession new];
AVCaptureDeviceInput *cameraDeviceInput = …
AVCaptureDeviceInput *micDeviceInput = …
AVCaptureMovieFileOutput *movieFileOutput = …
if ([captureSession canAddInput:cameraDeviceInput]) {
    [captureSession addInput:cameraDeviceInput];
}
if ([captureSession canAddInput:micDeviceInput]) {
    [captureSession addInput:micDeviceInput];
}
if ([captureSession canAddOutput:movieFileOutput]) {
    [captureSession addOutput:movieFileOutput];
}

[captureSession startRunning];

(為了簡(jiǎn)單起見(jiàn),調(diào)度隊(duì)列 (dispatch queue) 的相關(guān)代碼已經(jīng)從上面那段代碼中省略了。所有對(duì) capture session 的調(diào)用都是阻塞的,因此建議將它們分配到后臺(tái)串行隊(duì)列中。)

capture session 可以通過(guò)一個(gè) sessionPreset 來(lái)進(jìn)一步配置,這可以用來(lái)指定輸出質(zhì)量的等級(jí)。有 11 種不同的預(yù)設(shè)模式:

NSString *const  AVCaptureSessionPresetPhoto;
NSString *const  AVCaptureSessionPresetHigh;
NSString *const  AVCaptureSessionPresetMedium;
NSString *const  AVCaptureSessionPresetLow;
NSString *const  AVCaptureSessionPreset352x288;
NSString *const  AVCaptureSessionPreset640x480;
NSString *const  AVCaptureSessionPreset1280x720;
NSString *const  AVCaptureSessionPreset1920x1080;
NSString *const  AVCaptureSessionPresetiFrame960x540;
NSString *const  AVCaptureSessionPresetiFrame1280x720;
NSString *const  AVCaptureSessionPresetInputPriority;

第一個(gè)代表高像素圖片輸出。 接下來(lái)的九個(gè)和之前我們?cè)谠O(shè)置 UIImagePickerControllervideoQuality 時(shí)看到過(guò)的 UIImagePickerControllerQualityType 選項(xiàng)非常相似,不同的是,這里有一些額外可用于 capture session 的預(yù)設(shè)。 最后一個(gè) (AVCaptureSessionPresetInputPriority) 代表 capture session 不去控制音頻與視頻輸出設(shè)置。而是通過(guò)已連接的捕獲設(shè)備的 activeFormat 來(lái)反過(guò)來(lái)控制 capture session 的輸出質(zhì)量等級(jí)。在下一節(jié),我們將會(huì)看到更多關(guān)于設(shè)備和設(shè)備格式的細(xì)節(jié)。

輸入

AVCaptureSession 的輸入其實(shí)就是一個(gè)或多個(gè)的 AVCaptureDevice 對(duì)象,這些對(duì)象通過(guò) AVCaptureDeviceInput 連接上 capture session。

我們可以使用 [AVCaptureDevice devices] 來(lái)尋找可用的捕獲設(shè)備。以 iPhone 6 為例:

(
    “<AVCaptureFigVideoDevice: 0x136514db0 [Back Camera][com.apple.avfoundation.avcapturedevice.built-in_video:0]>”,
    “<AVCaptureFigVideoDevice: 0x13660be80 [Front Camera][com.apple.avfoundation.avcapturedevice.built-in_video:1]>”,
    “<AVCaptureFigAudioDevice: 0x174265e80 [iPhone Microphone][com.apple.avfoundation.avcapturedevice.built-in_audio:0]>”
)

視頻輸入

配置相機(jī)輸入,需要實(shí)例化一個(gè) AVCaptureDeviceInput 對(duì)象,參數(shù)是你期望的相機(jī)設(shè)備,然后把它添加到 capture session:

AVCaptureSession *captureSession = …
AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
AVCaptureDeviceInput *cameraDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice: error:&error];
if ([captureSession canAddInput:input]) {
    [captureSession addInput:cameraDeviceInput];
}

如果上面提到的 capture session 預(yù)設(shè)列表里能滿(mǎn)足你的需求,那你就不需要做更多的事情了。如果不夠,比如你想要高的幀率,你將需要配置具體的設(shè)備格式。一個(gè)視頻捕獲設(shè)備有許多設(shè)備格式,每個(gè)都帶有特定的屬性和功能。下面是對(duì)于 iPhone6 的后置攝像頭的一些例子 (一共有 22 種可用格式):

格式 分辨率 FPS HRSI FOV VIS 最大放大比例 Upscales AF ISO SS HDR
420v 1280x720 5 - 240 1280x720 54.626 YES 49.12 1.09 1 29.0 - 928 0.000003-0.200000 NO
420f 1280x720 5 - 240 1280x720 54.626 YES 49.12 1.09 1 29.0 - 928 0.000003-0.200000 NO
420v 1920x1080 2 - 30 3264x1836 58.040 YES 95.62 1.55 2 29.0 - 464 0.000013-0.500000 YES
420f 1920x1080 2 - 30 3264x1836 58.040 YES 95.62 1.55 2 29.0 - 464 0.000013-0.500000 YES
420v 1920x1080 2 - 60 3264x1836 58.040 YES 95.62 1.55 2 29.0 - 464 0.000008-0.500000 YES
420f 1920x1080 2 - 60 3264x1836 58.040 YES 95.62 1.55 2 29.0 - 464 0.000008-0.500000 YES
  • 格式 = 像素格式
  • FPS = 支持幀數(shù)范圍
  • HRSI = 高像素靜態(tài)圖片尺寸
  • FOV = 視角
  • VIS = 該格式支持視頻防抖
  • Upscales = 加入數(shù)字 upscaling 時(shí)的放大比例
  • AF = 自動(dòng)對(duì)焦系統(tǒng)(1 是反差對(duì)焦,2 是相位對(duì)焦)
  • ISO = 支持感光度范圍
  • SS = 支持曝光時(shí)間范圍
  • HDR = 支持高動(dòng)態(tài)范圍圖像

通過(guò)上面的那些格式,你會(huì)發(fā)現(xiàn)如果要錄制 240 幀每秒的視頻的話,可以根據(jù)想要的像素格式選用第一個(gè)或第二個(gè)格式。另外若是要捕獲 1920x1080 的分辨率的視頻的話,是不支持 240 幀每秒的。

配置一個(gè)具體設(shè)備格式,你首先需要調(diào)用 lockForConfiguration: 來(lái)獲取設(shè)備的配置屬性的獨(dú)占訪問(wèn)權(quán)限。接著你簡(jiǎn)單地使用 setActiveFormat: 來(lái)設(shè)置設(shè)備的捕獲格式。這將會(huì)自動(dòng)把 capture session 的預(yù)設(shè)設(shè)置為 AVCaptureSessionPresetInputPriority

一旦你設(shè)置了預(yù)想的設(shè)備格式,你就可以在這種設(shè)備格式的約束參數(shù)范圍內(nèi)進(jìn)行進(jìn)一步的配置了。

對(duì)于視頻捕獲的對(duì)焦,曝光和白平衡的設(shè)置,與圖像捕獲時(shí)一樣,具體可參考第 21 期“iOS 上的相機(jī)捕捉”。除了那些,這里還有一些視頻特有的配置選項(xiàng)。

你可以用捕獲設(shè)備的 activeVideoMinFrameDurationactiveVideoMaxFrameDuration 屬性設(shè)置幀速率,一幀的時(shí)長(zhǎng)是幀速率的倒數(shù)。設(shè)置幀速率之前,要先確認(rèn)它是否在設(shè)備格式所支持的范圍內(nèi),然后鎖住捕獲設(shè)備來(lái)進(jìn)行配置。為了確保幀速率恒定,可以將最小與最大的幀時(shí)長(zhǎng)設(shè)置成一樣的值:

NSError *error;
CMTime frameDuration = CMTimeMake(1, 60);
NSArray *supportedFrameRateRanges = [device.activeFormat videoSupportedFrameRateRanges];
BOOL frameRateSupported = NO;
for (AVFrameRateRange *range in supportedFrameRateRanges) {
    if (CMTIME_COMPARE_INLINE(frameDuration, >=, range.minFrameDuration) &&
        CMTIME_COMPARE_INLINE(frameDuration, <=, range.maxFrameDuration)) {
        frameRateSupported = YES;
    }
}

if (frameRateSupported && [device lockForConfiguration:&error]) {
    [device setActiveVideoMaxFrameDuration:frameDuration];
    [device setActiveVideoMinFrameDuration:frameDuration];
    [device unlockForConfiguration];
}

視頻防抖 是在 iOS 6 和 iPhone 4S 發(fā)布時(shí)引入的功能。到了 iPhone 6,增加了更強(qiáng)勁和流暢的防抖模式,被稱(chēng)為影院級(jí)的視頻防抖動(dòng)。相關(guān)的 API 也有所改動(dòng) (目前為止并沒(méi)有在文檔中反映出來(lái),不過(guò)可以查看頭文件)。防抖并不是在捕獲設(shè)備上配置的,而是在 AVCaptureConnection 上設(shè)置。由于不是所有的設(shè)備格式都支持全部的防抖模式,所以在實(shí)際應(yīng)用中應(yīng)事先確認(rèn)具體的防抖模式是否支持:

AVCaptureDevice *device = ...;
AVCaptureConnection *connection = ...;

AVCaptureVideoStabilizationMode stabilizationMode = AVCaptureVideoStabilizationModeCinematic;
if ([device.activeFormat isVideoStabilizationModeSupported:stabilizationMode]) {
    [connection setPreferredVideoStabilizationMode:stabilizationMode];
}

iPhone 6 的另一個(gè)新特性就是視頻 HDR (高動(dòng)態(tài)范圍圖像),它是“高動(dòng)態(tài)范圍的視頻流,與傳統(tǒng)的將不同曝光度的靜態(tài)圖像合成成一張高動(dòng)態(tài)范圍圖像的方法完全不同”,它是內(nèi)建在傳感器中的。有兩種方法可以配置視頻 HDR:直接將 capture device 的 videoHDREnabled 設(shè)置為啟用或禁用,或者使用 automaticallyAdjustsVideoHDREnabled 屬性來(lái)留給系統(tǒng)處理。

技術(shù)參考:iPhone 6 和 iPhone Plus 的新 AV Foundation 相機(jī)特性

音頻輸入

之前展示的捕獲設(shè)備列表里面只有一個(gè)音頻設(shè)備,你可能覺(jué)得奇怪,畢竟 iPhone 6 有 3 個(gè)麥克風(fēng)。然而因?yàn)橛袝r(shí)會(huì)放在一起使用,便于優(yōu)化性能,因此可能被當(dāng)做一個(gè)設(shè)備來(lái)使用。例如在 iPhone 5 及以上的手機(jī)錄制視頻時(shí),會(huì)同時(shí)使用前置和后置麥克風(fēng),用于定向降噪。

Technical Q&A: AVAudioSession - Microphone Selection

大多數(shù)情況下,設(shè)置成默認(rèn)的麥克風(fēng)配置即可。后置麥克風(fēng)會(huì)自動(dòng)搭配后置攝像頭使用 (前置麥克風(fēng)則用于降噪),前置麥克風(fēng)和前置攝像頭也是一樣。

然而想要訪問(wèn)和配置單獨(dú)的麥克風(fēng)也是可行的。例如,當(dāng)用戶(hù)正在使用后置攝像頭捕獲場(chǎng)景的時(shí)候,使用前置麥克風(fēng)來(lái)錄制解說(shuō)也應(yīng)是可能的。這就要依賴(lài)于 AVAudioSession。 為了變更要訪問(wèn)的音頻,audio session 首先需要設(shè)置為支持這樣做的類(lèi)別。然后我們需要遍歷 audio session 的輸入端口和端口數(shù)據(jù)來(lái)源,來(lái)找到我們想要的麥克風(fēng):

// 配置 audio session
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setActive:YES error:nil];

// 尋找期望的輸入端口
NSArray* inputs = [audioSession availableInputs];
AVAudioSessionPortDescription *builtInMic = nil;
for (AVAudioSessionPortDescription* port in inputs) {
    if ([port.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {
        builtInMic = port;
        break;
    }
}

// 尋找期望的麥克風(fēng)
for (AVAudioSessionDataSourceDescription* source in builtInMic.dataSources) {
    if ([source.orientation isEqual:AVAudioSessionOrientationFront]) {
        [builtInMic setPreferredDataSource:source error:nil];
        [audioSession setPreferredInput:builtInMic error:&error];
        break;
    }
}

除了設(shè)置非默認(rèn)的麥克風(fēng)配置,你也可以使用 AVAudioSession 來(lái)配置其他音頻設(shè)置,比如音頻增益和采樣率等。

訪問(wèn)權(quán)限

有件事你需要記住,訪問(wèn)相機(jī)和麥克風(fēng)需要先獲得用戶(hù)授權(quán)。當(dāng)你給視頻或音頻創(chuàng)建第一個(gè) AVCaptureDeviceInput 對(duì)象時(shí),iOS 會(huì)自動(dòng)彈出一次對(duì)話框,請(qǐng)求用戶(hù)授權(quán),但你最好還是自己實(shí)現(xiàn)下。之后你就可以在還沒(méi)有被授權(quán)的時(shí)候,使用相同的代碼來(lái)提示用戶(hù)進(jìn)行授權(quán)。當(dāng)用戶(hù)未授權(quán)時(shí),對(duì)于錄制視頻或音頻的嘗試,得到的將是黑色畫(huà)面和無(wú)聲。

輸出

輸入配置完了,現(xiàn)在把我們的注意力轉(zhuǎn)向 capture session 的輸出。

AVCaptureMovieFileOutput

將視頻寫(xiě)入文件,最簡(jiǎn)單的選擇就是使用 AVCaptureMovieFileOutput 對(duì)象。把它作為輸出添加到 capture session 中,就可以將視頻和音頻寫(xiě)入 QuickTime 文件,這只需很少的配置。

AVCaptureMovieFileOutput *movieFileOutput = [AVCaptureMovieFileOutput new];
if([captureSession canAddOutput:movieFileOutput]){
    [captureSession addOutput:movieFileOutput];
}

// 開(kāi)始錄制
NSURL *outputURL = …
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];

當(dāng)實(shí)際的錄制開(kāi)始或停止時(shí),想要接收回調(diào)的話就必須要一個(gè)錄制代理。當(dāng)錄制停止時(shí),輸出通常還在寫(xiě)入數(shù)據(jù),等它完成之后會(huì)調(diào)用代理方法。

AVCaptureMovieFileOutput 有一些其他的配置選項(xiàng),比如在某段時(shí)間后,在達(dá)到某個(gè)指定的文件尺寸時(shí),或者當(dāng)設(shè)備的最小磁盤(pán)剩余空間達(dá)到某個(gè)閾值時(shí)停止錄制。如果你還需要更多設(shè)置,比如自定義視頻音頻的壓縮率,或者你想要在寫(xiě)入文件之前,處理視頻音頻的樣本,那么你需要一些更復(fù)雜的操作。

AVCaptureDataOutputAVAssetWriter

如果你想要對(duì)影音輸出有更多的操作,你可以使用 AVCaptureVideoDataOutputAVCaptureAudioDataOutput 而不是我們上節(jié)討論的 AVCaptureMovieFileOutput。

這些輸出將會(huì)各自捕獲視頻和音頻的樣本緩存,接著發(fā)送到它們的代理。代理要么對(duì)采樣緩沖進(jìn)行處理 (比如給視頻加濾鏡),要么保持原樣傳送。使用 AVAssetWriter 對(duì)象可以將樣本緩存寫(xiě)入文件:

http://wiki.jikexueyuan.com/project/objc/images/23-2.svg" alt="" />

配置一個(gè) asset writer 需要定義一個(gè)輸出 URL 和文件格式,并添加一個(gè)或多個(gè)輸入來(lái)接收采樣的緩沖。我們還需要將輸入的 expectsMediaInRealTime 屬性設(shè)置為 YES,因?yàn)樗鼈冃枰獜?capture session 實(shí)時(shí)獲得數(shù)據(jù)。

NSURL *url = …;
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeMPEG4 error:nil];
AVAssetWriterInput *videoInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:nil];
videoInput.expectsMediaDataInRealTime = YES;
AVAssetWriterInput *audioInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:nil];
audioInput.expectsMediaDataInRealTime = YES;
if ([assetWriter canAddInput:videoInput]) {
    [assetWriter addInput:videoInput];
}
if ([assetWriter canAddInput:audioInput]) {
    [assetWriter addInput:audioInput];
}

(這里推薦將 asset writer 派送到后臺(tái)串行隊(duì)列中調(diào)用。)

在上面的示例代碼中,我們將 asset writer 的 outputSettings 設(shè)置為 nil。這就意味著附加上來(lái)的樣本不會(huì)再被重新編碼。如果你確實(shí)想要重新編碼這些樣本,那么需要提供一個(gè)包含具體輸出參數(shù)的字典。關(guān)于音頻輸出設(shè)置的鍵值被定義在這里, 關(guān)于視頻輸出設(shè)置的鍵值定義在這里。

為了更簡(jiǎn)單點(diǎn),AVCaptureVideoDataOutputAVCaptureAudioDataOutput 分別帶有 recommendedVideoSettingsForAssetWriterWithOutputFileType:recommendedAudioSettingsForAssetWriterWithOutputFileType: 方法,可以生成與 asset writer 兼容的帶有全部鍵值對(duì)的字典。所以你可以通過(guò)在這個(gè)字典里調(diào)整你想要重寫(xiě)的屬性,來(lái)簡(jiǎn)單地定義你自己的輸出設(shè)置。比如,增加視頻比特率來(lái)提高視頻質(zhì)量等。

或者,你也可以使用 AVOutputSettingsAssistant 來(lái)配置輸出設(shè)置的字典,但是從我的經(jīng)驗(yàn)來(lái)看,使用上面的方法會(huì)更好,它們會(huì)提供更實(shí)用的輸出設(shè)置,比如視頻比特率。另外,AVOutputSettingsAssistant 似乎存在一些缺點(diǎn),例如,當(dāng)你改變希望的視頻的幀速率時(shí),視頻的比特率并不會(huì)改變。

實(shí)時(shí)預(yù)覽

當(dāng)使用 AVFoundation 來(lái)做圖像捕獲時(shí),我們必須提供一套自定義的用戶(hù)界面。其中一個(gè)關(guān)鍵的相機(jī)交互組件是實(shí)時(shí)預(yù)覽圖。最簡(jiǎn)單的實(shí)現(xiàn)方式是通過(guò)把 AVCaptureVideoPreviewLayer 對(duì)象作為一個(gè) sublayer 加到相機(jī)圖層上去:

AVCaptureSession *captureSession = ...;
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
UIView *cameraView = ...;
previewLayer.frame = cameraView.bounds;
[cameraView.layer addSublayer:previewLayer];

如果你想要更進(jìn)一步操作,比如,在實(shí)時(shí)預(yù)覽圖加濾鏡,你需要將 AVCaptureVideoDataOutput 對(duì)象加到 capture session,并且使用 OpenGL 展示畫(huà)面,具體可查看該文“iOS 上的相機(jī)捕捉”

總結(jié)

有許多不同的方法可以給 iOS 上的視頻捕獲配置管線,從最直接的 UIImagePickerController,到精密配合的 AVCaptureSessionAVAssetWriter 。如何抉擇取決于你的項(xiàng)目要求,比如期望的視頻質(zhì)量和壓縮率,或者是你想要展示給用戶(hù)的相機(jī)控件。