iOS 視頻錄制

  • 使用原生相機(jī) UIImagePickerController 來(lái)錄制

一刻诊、準(zhǔn)備
1.添加依賴庫(kù)AVFoundation.framework

2.導(dǎo)入頭文件
<AVFoundation/AVFoundation.h>#import <MobileCoreServices/MobileCoreServices.h>

3.添加成員變量:

{
    //視頻錄制
    UIImagePickerController *_picker;
    //拍攝視頻資源控制符
    NSURL *_movieUrl;
    //保存到本地資源控制符
    NSURL *_locoaUrl;
    //視頻播放
    AVPlayer *player;
}

4.設(shè)置權(quán)限

麥克風(fēng)權(quán)限:Privacy - Microphone Usage Description 是否允許此App使用你的麥克風(fēng)
相機(jī)權(quán)限: Privacy - Camera Usage Description 是否允許此App使用你的相機(jī)?
相冊(cè)權(quán)限: Privacy - Photo Library Usage Description 是否允許此App訪問(wèn)你的媒體資料庫(kù)洛勉?
通訊錄權(quán)限
Privacy - Contacts Usage Description 是否允許此App訪問(wèn)你的通訊錄邻邮?

藍(lán)牙權(quán)限:Privacy - Bluetooth Peripheral Usage Description 是否許允此App使用藍(lán)牙?
語(yǔ)音轉(zhuǎn)文字權(quán)限:Privacy - Speech Recognition Usage Description 是否允許此App使用語(yǔ)音識(shí)別?
日歷權(quán)限:Privacy - Calendars Usage Description 是否允許此App使用日歷征绎?
定位權(quán)限:Privacy - Location When In Use Usage Description 我們需要通過(guò)您的地理位置信息獲取您周邊的相關(guān)數(shù)據(jù)
后臺(tái)定位權(quán)限: Privacy - Location Always Usage Description 我們需要通過(guò)您的地理位置信息獲取您周邊的相關(guān)數(shù)據(jù)定位的需要這么寫,防止上架被拒磨取。

二人柿、代碼:

/**
** 
****點(diǎn)擊按鈕開始錄制
** @param sender <#sender description#> */
- (IBAction)startPicker:(id)sender {
//初始化 UIImagePickerController
    _picker = [[UIImagePickerController alloc]init];    
    _picker.delegate = self;
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
//來(lái)源為攝像頭
        _picker.sourceType = UIImagePickerControllerSourceTypeCamera;
// 重點(diǎn) 是設(shè)置媒體類型為視頻 電影 類型為數(shù)組
        _picker.mediaTypes = @[(NSString*)kUTTypeMovie];
//設(shè)置為錄制模式
        _picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
//下面為默認(rèn)設(shè)置
//錄制時(shí)間
        _picker.videoMaximumDuration = 10;
//質(zhì)量
        _picker.videoQuality = UIImagePickerControllerQualityTypeIFrame960x540;
//顯示攝像頭控制面板 設(shè)置為NO 使用cameraOverlayView 自定義界面
        _picker.showsCameraControls = YES;
// picker.cameraOverlayView 攝像頭上覆蓋的視圖,可用通過(guò)這個(gè)視頻來(lái)自定義拍照或錄像界面
//攝像頭  前置/后置
        _picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
//閃光燈模式 自動(dòng)
        _picker.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
    }
    [self presentViewController:_picker animated:YES completion:nil];    
}

#pragma mark UIImagePickerControllerDelegate  代理方法(在代理方法中處理視頻)
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
       [picker dismissViewControllerAnimated:YES completion:nil];
       NSString *mediaType =  [info objectForKey:UIImagePickerControllerMediaType];
       if ([mediaType isEqualToString:@"public.image"]) {
        //如果媒體類型為圖片
        //相機(jī):裁剪后的圖片//
        UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
        //原始圖片
        UIImage *image2 = [info objectForKey:UIImagePickerControllerOriginalImage];
           }else if (
              [mediaType isEqualToString:@"public.movie"]){//如果媒體類型為視頻
               _movieUrl = [info objectForKey:UIImagePickerControllerMediaURL];
//獲取視頻資源定位
               //將視頻保存到本地
            NSData *fileData = [NSData dataWithContentsOfURL:_movieUrl];
            NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
            path = [path stringByAppendingPathComponent:@"save.mp4"];
            NSFileManager *fileManager = [NSFileManager defaultManager];
            BOOL isSuccess = [fileManager createFileAtPath:path contents:fileData attributes:nil];
               if (isSuccess) {
            NSLog(@"保存到本地成功");
            //保存本地資源定位
            _locoaUrl = [NSURL URLWithString:path];
        } else {
            NSLog(@"保存到本地失敗");
        }    }
    NSLog(@"拍照忙厌,相片完成”);

        //將視頻保存到相冊(cè)
    UISaveVideoAtPathToSavedPhotosAlbum([_movieUrl path], self, @selector(video:didFinishSavingWithError:contextInfo:), nil);}

/* 實(shí)現(xiàn)錄制過(guò)程中點(diǎn)擊取消退出 @param picker <#picker description#> */
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
    [picker dismissViewControllerAnimated:YES completion:nil];
}

/** 視頻格式轉(zhuǎn)換(帶轉(zhuǎn)換功能額)
** @param sender <#sender description#> */
- (IBAction)formatConverter:(id)sender{
//轉(zhuǎn)換時(shí)文件不能已存在凫岖,否則出錯(cuò)
       AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:_movieUrl options:nil];
       NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
       //判斷是否包含該質(zhì)量的視頻
    if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality]) {
        AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:AVAssetExportPresetMediumQuality];
        //用時(shí)間給文件全名,以免重復(fù)逢净,在測(cè)試的時(shí)候其實(shí)可以判斷文件是否存在若存在哥放,則刪除,重新生成文件即可
        NSDateFormatter *formater = [[NSDateFormatter alloc] init];
        [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
        NSString *resultPath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
        exportSession.outputURL = [NSURL fileURLWithPath:resultPath];
        exportSession.outputFileType = AVFileTypeMPEG4;
        [exportSession exportAsynchronouslyWithCompletionHandler:^(void)         {
             switch (exportSession.status) {
                 case AVAssetExportSessionStatusUnknown:
                     NSLog(@"AVAssetExportSessionStatusUnknown");
                     break;
                 case AVAssetExportSessionStatusWaiting:
                     NSLog(@"AVAssetExportSessionStatusWaiting");
                     break;
                 case AVAssetExportSessionStatusExporting:
                     NSLog(@"AVAssetExportSessionStatusExporting");
                     break;
                 case AVAssetExportSessionStatusCompleted:
                     NSLog(@"AVAssetExportSessionStatusCompleted");
                 {
                     NSURL *fileUrl = [NSURL URLWithString:resultPath];
                     NSLog(@"轉(zhuǎn)換結(jié)束");
                     [self fileSizeAtPath:fileUrl];                     _endUrl = fileUrl;
                 }
                     break;
                 case AVAssetExportSessionStatusFailed:
                     NSLog(@"AVAssetExportSessionStatusFailed");
                     break;
             }
         }];
    }
}

三爹土、其他:

/** **計(jì)算文件大小** @param filePathUrl <#filePathUrl description#> @return 返回單位為Byte */
- (unsigned long long)fileSizeAtPath:(NSURL *)filePathUrl{
       NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isExist = [fileManager fileExistsAtPath:[filePathUrl path]];
    if (isExist){
        unsigned long long fileSize = [[fileManager attributesOfItemAtPath:[filePathUrl path] error:nil] fileSize];
        NSLog(@"%@大小: %f M",[filePathUrl path],fileSize/1024.0/1024.0);
        return fileSize;
    } else {
        NSLog(@"file is not exist");
        return 0;
    }
}

/** **點(diǎn)擊播放本地視頻** @param sender <#sender description#> */
- (IBAction)playLocalMove:(id)sender {
       NSURL *movieUrl = [NSURL fileURLWithPath:[_locoaUrl path]];
    //直接調(diào)用_localUrl無(wú)法播放甥雕,不知道為什么
    player = [AVPlayer playerWithURL:movieUrl];
       //3、創(chuàng)建視頻顯示的圖層
    AVPlayerLayer *showVodioLayer = [AVPlayerLayer playerLayerWithPlayer:player];
    showVodioLayer.frame = self.view.frame;
    [self.view.layer addSublayer:showVodioLayer];
    //4着饥、播放視頻
    [player play];
}

/** **獲取相冊(cè)內(nèi)視頻的時(shí)長(zhǎng)** @param URL <#URL description#> @return <#return value description#> */
-(CGFloat)getVideoLength:(NSURL*)URL{
    NSDictionary*opts=[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]                                                 forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
       AVURLAsset *urlAs = [AVURLAsset URLAssetWithURL:URL options:opts];
       CGFloat second= urlAs.duration.value/urlAs.duration.timescale;
       return second;
}

//**視頻保存后的回調(diào)**
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
       if (error) {
        NSLog(@"保存視頻過(guò)程中發(fā)生錯(cuò)誤犀农,錯(cuò)誤信息:%@",error.localizedDescription);
    }else{
        NSLog(@"視頻保存成功.");
    }
}

視頻質(zhì)量與大小的關(guān)系(以10s為例)

// UIImagePickerControllerQualityTypeHigh = 0, 高,18M
// UIImagePickerControllerQualityTypeMedium = 1 , 中等宰掉,0.95M
// UIImagePickerControllerQualityTypeLow = 2, 低呵哨,0.19M
// UIImagePickerControllerQualityType640x480 , 3.745M
// UIImagePickerControllerQualityTypeIFrame1280x720赁濒, 50M
// UIImagePickerControllerQualityTypeIFrame960x540, 35M

四孟害、UIImagePickerController常用屬性拒炎、方法

1.+(BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType;
// 檢查指定源是否在設(shè)備上可用。
// 檢查照片源是否可用
[UIImagePickerControlle isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]

2.allowsEditing
默認(rèn)NO,是否允許編輯允許編輯.

[imagePicker setAllowsEditing:YES]; 

3. videoMaximumDuration
設(shè)置UIImagePicker的最大視頻持續(xù)時(shí)間.默認(rèn)10分鐘

4. availableMediaTypesForSourceType:
//指定源可用的媒體種類
//獲得相機(jī)模式下支持的媒體類型

NSArray* availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];

5. sourceType
設(shè)置UIImagePicker照片源類型挨务,默認(rèn)有3種击你。
照片源類型 UIImagePickerControllerSourceTypeCamera
照相機(jī) UIImagePickerControllerSourceTypePhotoLibrary
照片庫(kù)(通過(guò)同步存放的,用戶不能刪除) UIImagePickerControllerSourceTypeSavedPhotosAlbum
保存的照片(通過(guò)拍照或者截屏保存的谎柄,用戶可以刪除)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末丁侄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子朝巫,更是在濱河造成了極大的恐慌鸿摇,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,294評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劈猿,死亡現(xiàn)場(chǎng)離奇詭異拙吉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)揪荣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門筷黔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人仗颈,你說(shuō)我怎么就攤上這事佛舱。” “怎么了挨决?”我有些...
    開封第一講書人閱讀 157,790評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵名眉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我凰棉,道長(zhǎng),這世上最難降的妖魔是什么陌粹? 我笑而不...
    開封第一講書人閱讀 56,595評(píng)論 1 284
  • 正文 為了忘掉前任撒犀,我火速辦了婚禮,結(jié)果婚禮上掏秩,老公的妹妹穿的比我還像新娘或舞。我一直安慰自己,他們只是感情好蒙幻,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,718評(píng)論 6 386
  • 文/花漫 我一把揭開白布映凳。 她就那樣靜靜地躺著,像睡著了一般邮破。 火紅的嫁衣襯著肌膚如雪诈豌。 梳的紋絲不亂的頭發(fā)上仆救,一...
    開封第一講書人閱讀 49,906評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音矫渔,去河邊找鬼彤蔽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛庙洼,可吹牛的內(nèi)容都是我干的顿痪。 我是一名探鬼主播,決...
    沈念sama閱讀 39,053評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼油够,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蚁袭!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起石咬,我...
    開封第一講書人閱讀 37,797評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤揩悄,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后碌补,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虏束,經(jīng)...
    沈念sama閱讀 44,250評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,570評(píng)論 2 327
  • 正文 我和宋清朗相戀三年厦章,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了镇匀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,711評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡袜啃,死狀恐怖汗侵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情群发,我是刑警寧澤晰韵,帶...
    沈念sama閱讀 34,388評(píng)論 4 332
  • 正文 年R本政府宣布,位于F島的核電站熟妓,受9級(jí)特大地震影響雪猪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜起愈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,018評(píng)論 3 316
  • 文/蒙蒙 一只恨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抬虽,春花似錦官觅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至笛辟,卻和暖如春功氨,著一層夾襖步出監(jiān)牢的瞬間序苏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工疑故, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杠览,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,461評(píng)論 2 360
  • 正文 我出身青樓纵势,卻偏偏與公主長(zhǎng)得像踱阿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钦铁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,595評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 兩種方式 使用高度封裝的類UIImagePickerController 使用AVFoundation框架 方式一...
    丨n水瓶座菜蟲灬閱讀 2,942評(píng)論 0 10
  • 我們?cè)陧?xiàng)目中有時(shí)會(huì)碰到視頻相關(guān)的需求软舌,一般的可以分為幾種情況: 1. 簡(jiǎn)單的視頻開發(fā),對(duì)界面無(wú)要求牛曹,可直接使用系統(tǒng)...
    純情_小火雞閱讀 20,895評(píng)論 2 103
  • 最近開發(fā)中遇到一個(gè)需求佛点,就是想微信那樣錄制一個(gè)小視頻,然后在錄制視頻的圖層上播放黎比,然后發(fā)布到朋友圈超营,無(wú)聲播放,但有...
    攻克乃還_閱讀 1,310評(píng)論 1 3
  • #import "MovieViewController.h"#import #import typedef ...
    Ashoka_APP閱讀 1,652評(píng)論 2 1
  • 因?yàn)橐Y(jié)局swift3.0中引用snapKit的問(wèn)題,看到一篇介紹Xcode8,swift3變化的文章,覺得很詳細(xì)...
    uniapp閱讀 4,405評(píng)論 0 12