通過 拍攝照片Demo 的學習,我們學會了AVCaptureSession的基本使用。現在,同樣使用AVCaptureSession類,隻需要做微小的修改就可以完成視訊拍攝。
初始化�預覽畫面
聲明屬性
首先,我們要聲明拍攝所必須的屬性:
@property (nonatomic, strong) AVCaptureSession *captureSession;
@property (nonatomic, strong) AVCaptureDevice *videoDevice;
@property (nonatomic, strong) AVCaptureDevice *audioDevice;
@property (nonatomic, strong) AVCaptureDeviceInput *videoInput;
@property (nonatomic, strong) AVCaptureDeviceInput *audioInput;
@property (nonatomic, strong) AVCaptureMovieFileOutput *movieFileOutput;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
因為視訊會包含音頻資訊,是以比拍攝圖檔多出了音頻裝置(audioDevice)和音頻輸入(audioInput)。而我們的輸出類由AVCaptureStillImageOutput變成了AVCaptureMovieFileOutput,他們同樣都是AVCaptureOutput的子類。
捕捉會話初始化
在拍攝視訊前,需要初始化捕捉會話(AVCaptureSession):
- (void)setupCaptureSession {
// 1.擷取視訊裝置
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices) {
if (device.position == AVCaptureDevicePositionBack) {
self.videoDevice = device;
break;
}
}
// 2.擷取音頻裝置
self.audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
// 3.建立視訊輸入
NSError *error = nil;
self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:self.videoDevice error:&error];
if (error) {
return;
}
// 4.建立音頻輸入
self.audioInput = [AVCaptureDeviceInput deviceInputWithDevice:self.audioDevice error:&error];
if (error) {
return;
}
// 5.建立視訊輸出
self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
// 6.建立會話
self.captureSession = [[AVCaptureSession alloc] init];
self.captureSession.sessionPreset = AVCaptureSessionPreset1280x720;
if ([self.captureSession canAddInput:self.videoInput]) {
[self.captureSession addInput:self.videoInput];
}
if ([self.captureSession canAddInput:self.audioInput]) {
[self.captureSession addInput:self.audioInput];
}
if ([self.captureSession canAddOutput:self.movieFileOutput]) {
[self.captureSession addOutput:self.movieFileOutput];
}
// 7.預覽畫面
self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
[self.previewView.layer addSublayer:self.previewLayer];
}
看到這個方法應該很熟悉了吧,和拍攝照片的初始化話幾乎沒有差別。需要注意的是第6步sessionPreset設為了AVCaptureSessionPreset1280x720,也就是輸出720p的視訊。通過查詢文檔,還有很多不同分辨率可供選擇。
還記得開始和結束會話的兩個方法嗎?�startRunning和stopRunning,真是太好記了:
- (void)startSession {
if(![self.captureSession isRunning]) {
[self.captureSession startRunning];
}
}
- (void)stopSession {
if([self.captureSession isRunning]) {
[self.captureSession stopRunning];
}
}
最後,在viewDidLoad中調用上文的兩個方法:
[self setupCaptureSession];
[self startSession];
真機運作,就可以看到拍攝預覽畫面了。
拍攝視訊
完成了初始化工作, 拍攝視訊部分,我們隻需要調用startRecordingToOutputFileURL:recordingDelegate:方法就可以實作了。其中,參數url是為視訊指定的輸出路徑。
下面我們要為錄制按鈕建立兩個Action,touch down時開始拍攝視訊,touch up時結束拍攝。
touch down時,調用startRecord方法:
- (void)startRecord {
[self.movieFileOutput startRecordingToOutputFileURL:[NSURL fileURLWithPath:[self videoPath]] recordingDelegate:self];
}
touch up時,調用stopRecord方法:
- (void)stopRecord {
if ([self.movieFileOutput isRecording]) {
[self.movieFileOutput stopRecording];
}
}
我們注意到,開始拍攝時,調用了videoPath方法為視訊生成一個輸出位址。這個方法使用目前時間戳作為唯一的視訊檔案名:
- (NSString *)videoPath {
NSString *basePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *moviePath = [basePath stringByAppendingPathComponent:
[NSString stringWithFormat:@"%f.mp4",[NSDate date].timeIntervalSince1970]];
return moviePath;
}
最後我們,還要實作AVCaptureFileOutputRecordingDelegate代理。拍攝完成後,系統會觸發captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error:方法。我們可以通過outputFileURL參數通路拍攝好的視訊檔案。
增強攝像功能
拍攝視訊和照片的一些進階功能原理是一緻的,這裡我隻将上個Demo中�一塊代碼拷貝了過來,不用做任何修改就可實作攝像頭切換。其他的進階設定可以查閱文檔�自行探索。
Demo位址:
https://github.com/WorthyZhang/WZMediaDemo