什么是視頻錄制
視頻錄制其實(shí)就是一個類似于拍電影的過程浅悉,通過手機(jī)的攝像頭和麥克風(fēng),錄入聲音和畫面冗酿,然后經(jīng)過一個加工廠加工埠对,然后導(dǎo)出,就變成了我們口中定義的視頻裁替。接下來项玛,我會帶大家看一下,iOS中的視頻錄制到底是怎么做的弱判,讓大家能初步地寫出一個錄制視頻的小demo襟沮。當(dāng)然,還會教大家怎么進(jìn)行視頻圖像的捕獲還有壓縮昌腰。
iOS如何進(jìn)行視頻錄制
- 視頻錄制需要導(dǎo)入一個框架--
AVFoundation
框架
#import <AVFoundation/AVFoundation.h>
- 根據(jù)前言的分析,所以我們需要設(shè)置四個屬性來進(jìn)行視頻錄制的相關(guān)配置
//輸入聲音
@property (nonatomic, strong) AVCaptureDeviceInput *inputAudio;
//輸入畫面
@property (nonatomic, strong) AVCaptureDeviceInput *inputVideo;
//會話屬性
@property (nonatomic, strong) AVCaptureSession *session;
//導(dǎo)出
@property (nonatomic, strong) AVCaptureMovieFileOutput *output;
- 我們就做一個簡單點(diǎn)的demo开伏,在touchesBegan方法中進(jìn)行視頻錄制相關(guān)操作
// 3.創(chuàng)建對象,并且實(shí)例化
// 3.1創(chuàng)建一個設(shè)備
// 聲音
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
self.inputAudio = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
// 3.2畫面
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
self.inputVideo = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil];
// 3.3會話
self.session = [[AVCaptureSession alloc] init];
// 3.4 導(dǎo)出
self.output = [[AVCaptureMovieFileOutput alloc] init];
- 添加到加工廠(輸入&輸出)
if ([self.session canAddInput:self.inputAudio]) {
[self.session addInput:self.inputAudio];
}
if ([self.session canAddInput:self.inputVideo]) {
[self.session addInput:self.inputVideo];
}
if ([self.session canAddOutput:self.output]) {
[self.session addOutput:self.output];
}
// 添加一個預(yù)覽的圖層
AVCaptureVideoPreviewLayer *prelayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
prelayer.frame = self.view.bounds;
// [self.view.layer addSublayer:prelayer];
[self.view.layer insertSublayer:prelayer atIndex:0];
- 開啟加工廠
[self.session startRunning];
- 添加視頻錄制開關(guān)按鈕
// 視頻錄制的開關(guān)
- (IBAction)startOrClose:(id)sender {
if ([self.output isRecording]) {
// 正在錄制
[self.output stopRecording];
} else {
// 沒有錄制
// 獲取沙盒路徑,用于存儲
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:@"錄制的視頻.mov"];
// 開始錄制
[self.output startRecordingToOutputFileURL:[NSURL fileURLWithPath:path] recordingDelegate:self];
}
}
- 監(jiān)聽視頻錄制的進(jìn)度
#pragma mark - AVCaptureFileOutputRecordingDelegate
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error;
{
NSLog(@"完成錄制");
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections
{
NSLog(@"開始錄制");
}
為什么需要做視頻截圖
視頻截圖就是截取視頻播放中的某一幀(關(guān)鍵幀)畫面。
有時候當(dāng)我們觀看視頻的時候遭商,或者觀看直播的時候固灵,看到一些好玩,有趣的畫面需要和朋友進(jìn)行分享的時候劫流,就要用到視頻截圖這個功能了巫玻。
下面,我們一起來看一下如何進(jìn)行視頻截圖祠汇。
如何進(jìn)行視頻截圖
- 導(dǎo)入框架
#import <AVFoundation/AVFoundation.h>
- 核心代碼
創(chuàng)建視頻資源對象
// 1.1獲取資源的url
NSURL *url = [[NSBundle mainBundle] URLForResource:@"movie.mp4" withExtension:nil];
// 1.2對url進(jìn)行封裝
AVAsset *asset = [AVAsset assetWithURL:url];
// 1.創(chuàng)建一個視頻截取的截取器
AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
// <#int64_t value#>: 截取的時間
// <#int32_t timescale#>: 每秒播放多少幀
CMTime time = CMTimeMake(23, 1);
NSValue *value = [NSValue valueWithCMTime:time];
[generator generateCGImagesAsynchronouslyForTimes:@[value] completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) {
// UI的更新一定要在主線程進(jìn)行,要不然不能夠時時獲得更新
dispatch_sync(dispatch_get_main_queue(), ^{
self.picImageView.image = [UIImage imageWithCGImage:image];
});
}];
為什么要進(jìn)行視頻壓縮
通常錄制出來的原視頻都會很大仍秤,如果不壓縮就進(jìn)行上傳,一個是浪費(fèi)用戶的流量可很,二個會造成上傳時間過長诗力,影響用戶體驗。
如何進(jìn)行視頻壓縮
獲取視頻的位置-------相冊
創(chuàng)建相冊控制器對象,訪問相冊
// 創(chuàng)建訪問相冊的控制器對象
UIImagePickerController *picker = [[UIImagePickerController alloc]
init];
- 訪問相冊之前,需要判斷是否存在相冊
// 0. 判斷是否有相冊
if (![UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{NSLog(@" ");
return;}
- 彈出控制器
[self presentViewController:picker animated:YES completion:nil];
- 訪問相冊可以通過不同的方式,改變的方法為:
設(shè)置他的資源類型
/**
UIImagePickerControllerSourceTypePhotoLibrary, //照片庫 UIImagePickerControllerSourceTypeCamera, //照相機(jī)
UIImagePickerControllerSourceTypeSavedPhotosAlbum //相冊
*/
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
- 可以看到,相冊中沒有視頻,這是因為需要設(shè)置 媒體類型才能看到
// 設(shè)置媒體類型
picker.mediaTypes = [UIImagePickerControlleravailableMediaTypesForSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
- 看到視頻后,我們需要拿到該視頻,才能進(jìn)行壓縮操作,所以需要設(shè)置代理
picker.delegate = self;
并且遵守協(xié)議
@interface ViewController () <UINavigationControllerDelegate,UIImagePickerControllerDelegate>
實(shí)現(xiàn)方法:
// MARK: - delegate方法
// 選擇照片或者是視頻時 調(diào)用
// info: 相關(guān)參數(shù)
- (void)imagePickerController:(UIImagePickerController *)pickerdidFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;
// 選擇 取消時 調(diào)用
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
- 打印代理方法中的info這個參數(shù),可以看到里面包含該視頻的地址, 接收該地址
NSLog(@"%@",info);
NSURL *url = info[UIImagePickerControllerMediaURL];
- 視頻壓縮的原理: 把視頻用低質(zhì)量導(dǎo)出
- 創(chuàng)建視頻資源對象
// asset :資源
AVAsset *asset = [AVAsset assetWithURL:url];
- 創(chuàng)建視頻導(dǎo)出會話
/**
AVAssetExportPresetLowQuality //低質(zhì)量
AVAssetExportPresetMediumQuality//中質(zhì)量
AVAssetExportPresetHighestQuality//高質(zhì)量
*/
// 創(chuàng)建視頻導(dǎo)出會話
// presetName : 視頻導(dǎo)出質(zhì)量
AVAssetExportSession *session = [AVAssetExportSessionexportSessionWithAsset:asset presetName:AVAssetExportPresetLowQuality];
- 導(dǎo)出視頻:
// 導(dǎo)出
[session exportAsynchronouslyWithCompletionHandler:^{NSLog(@" ");
}];
- 導(dǎo)出視頻之前,需要我們確定導(dǎo)出到哪里
獲取沙盒路徑//
NSString *filePath =[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.mp4"];
// session.outputURL = [NSURL fileURLWithPath:filePath];
- 演示視頻導(dǎo)出, 報錯, 查看原因,發(fā)現(xiàn)視頻導(dǎo)出錯的原因是沒有設(shè)置視頻導(dǎo)出的類型根據(jù)屬性介紹,可以看到需要查看session.supportedFileTypes屬性,打印該屬性
// NSLog(@"%@",session.supportedFileTypes);
/**
"com.apple.quicktime-movie", quicktime-movie 類型
"public.mpeg-4" mp4 類型
*/
// 視頻導(dǎo)出的文件類型
session.outputFileType = @"public.mpeg-4";