当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS AVCaptureSession实现视频录制功能

iOS AVCaptureSession实现视频录制功能

2019年07月24日  | 移动技术网移动技术  | 我要评论

本文实例为大家分享了avcapturesession实现视频录制功能的具体代码,供大家参考,具体内容如下

#import "recordingvideoviewcontroller.h" 
#import <avfoundation/avfoundation.h> 
#import <assetslibrary/assetslibrary.h> 
 
@interface recordingvideoviewcontroller ()<avcapturefileoutputrecordingdelegate> 
 
//会话 负责输入和输出设备之间的数据传递 
@property (strong,nonatomic) avcapturesession  *capturesession; 
//设备输入 负责从avcapturedevice获得输入数据 
@property (strong,nonatomic) avcapturedeviceinput  *videocapturedeviceinput; 
@property (strong,nonatomic) avcapturedeviceinput  *audiocapturedeviceinput; 
//视频输出流 
@property (strong,nonatomic) avcapturemoviefileoutput  *capturemoviefileoutput; 
//相机拍摄预览图层 
@property (strong,nonatomic) avcapturevideopreviewlayer  *capturevideopreviewlayer; 
 
//自定义ui控件容器 
@property (strong,nonatomic) uiview  *viewcontainer; 
//聚焦图标 
@property (strong,nonatomic) uiimageview  *focuscursor; 
//录制时长 
@property (strong,nonatomic) uilabel  *timelabel; 
//切换前后摄像头 
@property (strong,nonatomic) uibutton  *switchcamerabtn; 
//改变焦距 
@property (strong,nonatomic) uibutton  *scalebtn; 
//计时器 
@property (strong,nonatomic) nstimer  *timer; 
 
 
@end 
 
@implementation recordingvideoviewcontroller { 
 @private 
  nsinteger _num; 
  cgfloat _kcamerascale; 
} 
 
 
- (uiview *)viewcontainer { 
  if (!_viewcontainer) { 
    _viewcontainer = [[uiview alloc] initwithframe:[uiscreen mainscreen].bounds]; 
     
    uibutton *takebutton = [uibutton buttonwithtype:uibuttontypecustom]; 
    takebutton.backgroundcolor = [uicolor redcolor]; 
    [takebutton settitle:@"start" forstate:uicontrolstatenormal]; 
    [takebutton addtarget:self action:@selector(takebuttonclick:) forcontrolevents:uicontroleventtouchupinside]; 
     
   
    _timelabel = [[uilabel alloc] init]; 
    _timelabel.textcolor = [uicolor redcolor]; 
    _timelabel.textalignment = nstextalignmentcenter; 
    _timelabel.font = [uifont boldsystemfontofsize:20]; 
    _timelabel.text = @"00:00"; 
     
     
    _switchcamerabtn = [uibutton buttonwithtype:uibuttontypecustom]; 
    [_switchcamerabtn settitle:@"switch" forstate:uicontrolstatenormal]; 
    _switchcamerabtn.backgroundcolor = [uicolor redcolor]; 
    [_switchcamerabtn addtarget:self action:@selector(switchcamerabtnclick) forcontrolevents:uicontroleventtouchupinside]; 
     
    _scalebtn = [uibutton buttonwithtype:uibuttontypecustom]; 
    [_scalebtn settitle:@"1x" forstate:uicontrolstatenormal]; 
    _scalebtn.backgroundcolor = [uicolor redcolor]; 
    [_scalebtn addtarget:self action:@selector(scalebtnclick:) forcontrolevents:uicontroleventtouchupinside]; 
     
    [_viewcontainer addsubview:takebutton]; 
    [_viewcontainer addsubview:_timelabel]; 
    [_viewcontainer addsubview:_scalebtn]; 
    [_viewcontainer addsubview:_switchcamerabtn]; 
    [takebutton mas_makeconstraints:^(masconstraintmaker *make) { 
      make.size.mas_equalto(cgsizemake(60, 40)); 
      make.centerx.mas_equalto(_viewcontainer); 
      make.bottom.mas_equalto(_viewcontainer).offset(-64); 
    }]; 
    [_timelabel mas_makeconstraints:^(masconstraintmaker *make) { 
      make.centerx.mas_equalto(_viewcontainer); 
      make.height.mas_equalto(@30); 
      make.top.mas_equalto(_viewcontainer); 
    }]; 
    [_scalebtn mas_makeconstraints:^(masconstraintmaker *make) { 
      make.size.mas_equalto(cgsizemake(60, 40)); 
      make.left.mas_equalto(_viewcontainer).offset(10); 
      make.top.mas_equalto(_viewcontainer); 
    }]; 
    [_switchcamerabtn mas_makeconstraints:^(masconstraintmaker *make) { 
      make.size.mas_equalto(cgsizemake(60, 40)); 
      make.top.mas_equalto(_viewcontainer); 
      make.right.mas_equalto(_viewcontainer).offset(-10); 
    }]; 
     
    _focuscursor = [[uiimageview alloc] init]; 
    kborder(_focuscursor, 1, [uicolor yellowcolor]); 
    _focuscursor.alpha = 0; 
    [_viewcontainer addsubview:self.focuscursor]; 
    [_focuscursor mas_makeconstraints:^(masconstraintmaker *make) { 
      make.size.mas_equalto(cgsizemake(40, 40)); 
      make.center.mas_equalto(_viewcontainer); 
    }]; 
 
  } 
  return _viewcontainer; 
} 
 
- (void)viewdidload { 
  [super viewdidload]; 
   
  self.title = @"视频录制"; 
  _kcamerascale = 1.0f; 
  //初始化会话对象 
  _capturesession = [[avcapturesession alloc] init]; 
  if ([_capturesession cansetsessionpreset:avcapturesessionpreset1280x720]) { 
    _capturesession.sessionpreset = avcapturesessionpreset1280x720; 
  } 
   
   
  nserror *error = nil; 
 
  //获取视频输入对象 
  avcapturedevice *videocapturedevice = [self cameradevicewithposition:(avcapturedevicepositionback)]; 
  if (!videocapturedevice) { 
    nslog(@"获取后置摄像头失败!"); 
    return; 
  } 
  _videocapturedeviceinput = [[avcapturedeviceinput alloc] initwithdevice:videocapturedevice error:&error]; 
  if (error) { 
    nslog(@"取得视频设备输入对象时出错"); 
    return; 
  } 
   
   
  //获取音频输入对象 
  avcapturedevice *audiocaturedevice = [[avcapturedevice deviceswithmediatype:avmediatypeaudio] firstobject]; 
  _audiocapturedeviceinput = [[avcapturedeviceinput alloc] initwithdevice:audiocaturedevice error:&error]; 
  if (error) { 
    nslog(@"取得音频设备输入对象时出错"); 
    return; 
  } 
   
  //初始化设备输出对象 
  _capturemoviefileoutput = [[avcapturemoviefileoutput alloc] init]; 
   
  //将设备输入添加到会话中 
  if ([_capturesession canaddinput:_videocapturedeviceinput]) { 
    [_capturesession addinput:_videocapturedeviceinput]; 
    [_capturesession addinput:_audiocapturedeviceinput]; 
     
    //防抖功能 
    avcaptureconnection *captureconnection = [_capturemoviefileoutput connectionwithmediatype:avmediatypeaudio]; 
    if ([captureconnection isvideostabilizationsupported]) { 
      captureconnection.preferredvideostabilizationmode = avcapturevideostabilizationmodeauto; 
    } 
  } 
   
  //将设备输出添加到会话中 
  if ([_capturesession canaddoutput:_capturemoviefileoutput]) { 
    [_capturesession addoutput:_capturemoviefileoutput]; 
  } 
   
   
  //创建视频预览图层 
  _capturevideopreviewlayer = [[avcapturevideopreviewlayer alloc] initwithsession:_capturesession]; 
  self.viewcontainer.layer.maskstobounds = yes; 
  _capturevideopreviewlayer.frame = self.viewcontainer.bounds; 
  _capturevideopreviewlayer.videogravity = avlayervideogravityresizeaspectfill; 
  [self.view.layer addsublayer:_capturevideopreviewlayer]; 
   
  //显示自定义控件 
  [self.view addsubview:self.viewcontainer]; 
   
  //添加点按聚焦手势 
  uitapgesturerecognizer *tapgesture = [[uitapgesturerecognizer alloc]initwithtarget:self action:@selector(tapscreen:)]; 
  [self.viewcontainer addgesturerecognizer:tapgesture]; 
   
} 
 
-(void)viewdidappear:(bool)animated{ 
  [super viewdidappear:animated]; 
  [self.capturesession startrunning]; 
} 
 
-(void)viewdiddisappear:(bool)animated{ 
  [super viewdiddisappear:animated]; 
  [self.capturesession stoprunning]; 
  [self.timer invalidate]; 
  self.timer = nil; 
} 
 
- (void)viewwilldisappear:(bool)animated { 
  [super viewwilldisappear:animated]; 
  [self.capturevideopreviewlayer setaffinetransform:cgaffinetransformmakescale(1, 1)]; 
} 
 
- (void)didreceivememorywarning { 
  [super didreceivememorywarning]; 
} 
 
//开始 + 暂停录制 
- (void)takebuttonclick:(uibutton *)sender { 
  if ([self.capturemoviefileoutput isrecording]) { 
    [self.capturemoviefileoutput stoprecording]; 
     
    [self.navigationcontroller popviewcontrolleranimated:yes]; 
     
  } else { 
    avcaptureconnection *captureconnection = [self.capturemoviefileoutput connectionwithmediatype:avmediatypevideo]; 
    captureconnection.videoorientation = [self.capturevideopreviewlayer connection].videoorientation; 
     
    nsstring *filepath = [nstemporarydirectory() stringbyappendingpathcomponent:@"movie.mov"]; 
    nslog(@"%@",filepath); 
    [self.capturemoviefileoutput startrecordingtooutputfileurl:[nsurl fileurlwithpath:filepath] recordingdelegate:self]; 
     
     
    self.switchcamerabtn.hidden = yes; 
     
    sender.backgroundcolor = [uicolor greencolor]; 
    [sender settitle:@"stop" forstate:uicontrolstatenormal]; 
     
    self.timer = [nstimer scheduledtimerwithtimeinterval:1 target:self selector:@selector(timeaction) userinfo:nil repeats:yes]; 
    [self.timer setfiredate:[nsdate distantpast]]; 
  } 
} 
 
//切换摄像头 
- (void)switchcamerabtnclick { 
  avcapturedeviceposition currentposition = self.videocapturedeviceinput.device.position; 
  avcapturedeviceposition toposition; 
  if (currentposition == avcapturedevicepositionunspecified || 
    currentposition == avcapturedevicepositionfront) { 
    toposition = avcapturedevicepositionback; 
  } else { 
    toposition = avcapturedevicepositionfront; 
  } 
   
  avcapturedevice *tocapturdevice = [self cameradevicewithposition:toposition]; 
  if (!tocapturdevice) { 
    nslog(@"获取要切换的设备失败"); 
    return; 
  } 
   
  nserror *error = nil; 
  avcapturedeviceinput *tovideodeviceinput = [[avcapturedeviceinput alloc] initwithdevice:tocapturdevice error:&error]; 
  if (error) { 
    nslog(@"获取要切换的设备输入失败"); 
    return; 
  } 
   
  //改变会话配置 
  [self.capturesession beginconfiguration]; 
   
  [self.capturesession removeinput:self.videocapturedeviceinput]; 
  if ([self.capturesession canaddinput:tovideodeviceinput]) { 
    [self.capturesession addinput:tovideodeviceinput]; 
     
    self.videocapturedeviceinput = tovideodeviceinput; 
  } 
  //提交会话配置 
  [self.capturesession commitconfiguration]; 
} 
 
 
//点按手势 
- (void)tapscreen:(uitapgesturerecognizer *)tap { 
  cgpoint point = [tap locationinview:self.viewcontainer]; 
   
  //将界面point对应到摄像头point 
  cgpoint camerapoint = [self.capturevideopreviewlayer capturedevicepointofinterestforpoint:point]; 
 
  //设置聚光动画 
  self.focuscursor.center = point; 
  self.focuscursor.transform = cgaffinetransformmakescale(1.5, 1.5); 
  self.focuscursor.alpha = 1.0f; 
  [uiview animatewithduration:1 animations:^{ 
    self.focuscursor.transform = cgaffinetransformidentity; 
  } completion:^(bool finished) { 
    self.focuscursor.alpha = 0.0f; 
 
  }]; 
   
  //设置聚光点坐标 
  [self focuswithmode:avcapturefocusmodeautofocus exposuremode:avcaptureexposuremodeautoexpose atpoint:camerapoint]; 
 
} 
 
 
/**设置聚焦点*/ 
-(void)focuswithmode:(avcapturefocusmode)focusmode exposuremode:(avcaptureexposuremode)exposuremode atpoint:(cgpoint)point{ 
   
  avcapturedevice *capturedevice= [self.videocapturedeviceinput device]; 
  nserror *error = nil; 
  //设置设备属性必须先解锁 然后加锁 
  if ([capturedevice lockforconfiguration:&error]) { 
     
    if ([capturedevice isfocusmodesupported:focusmode]) { 
      [capturedevice setfocusmode:focusmode]; 
    } 
    if ([capturedevice isfocuspointofinterestsupported]) { 
      [capturedevice setfocuspointofinterest:point]; 
    } 
    //    //曝光 
    //    if ([capturedevice isexposuremodesupported:exposuremode]) { 
    //      [capturedevice setexposuremode:exposuremode]; 
    //    } 
    //    if ([capturedevice isexposurepointofinterestsupported]) { 
    //      [capturedevice setexposurepointofinterest:point]; 
    //    } 
    //    //闪光灯模式 
    //    if ([capturedevice isflashmodesupported:avcaptureflashmodeauto]) { 
    //      [capturedevice setflashmode:avcaptureflashmodeauto]; 
    //    } 
     
    //加锁 
    [capturedevice unlockforconfiguration]; 
     
  }else{ 
    nslog(@"设置设备属性过程发生错误,错误信息:%@",error.localizeddescription); 
  } 
} 
 
 
 
//调整焦距 
-(void)scalebtnclick:(uibutton *)sender 
{ 
  _kcamerascale += 0.5; 
  if(_kcamerascale > 3.0) { 
    _kcamerascale = 1.0; 
  } 
  //改变焦距 
  avcapturedevice *videodevice = self.videocapturedeviceinput.device; 
  nserror *error = nil; 
  if ([videodevice lockforconfiguration:&error]) { 
     
    [videodevice setvideozoomfactor:_kcamerascale]; 
     
    [videodevice unlockforconfiguration]; 
     
    [sender settitle:[nsstring stringwithformat:@"%lgx",_kcamerascale] forstate:uicontrolstatenormal]; 
 
    [catransaction begin]; 
    [catransaction setanimationduration:0.25]; 
    [self.capturevideopreviewlayer setaffinetransform:cgaffinetransformmakescale(_kcamerascale, _kcamerascale)]; 
    [catransaction commit]; 
     
  } else { 
    nslog(@"修改设备属性失败!") 
  } 
} 
 
 
 
#pragma mark -------- avcapturefileoutputrecordingdelegate ---------- 
- (void)captureoutput:(avcapturefileoutput *)captureoutput didstartrecordingtooutputfileaturl:(nsurl *)fileurl fromconnections:(nsarray *)connections { 
  nslog(@"开始录制"); 
} 
 
- (void)captureoutput:(avcapturefileoutput *)captureoutput didfinishrecordingtooutputfileaturl:(nsurl *)outputfileurl fromconnections:(nsarray *)connections error:(nserror *)error { 
  nslog(@"录制结束"); 
  alassetslibrary *assetslibrary = [[alassetslibrary alloc] init]; 
  [assetslibrary writevideoatpathtosavedphotosalbum:outputfileurl completionblock:^(nsurl *asseturl, nserror *error) { 
    if (error) { 
      nslog(@"保存视频到相簿过程中发生错误,错误信息:%@",error.localizeddescription); 
    } 
  }]; 
} 
 
//录制计时 
- (void)timeaction { 
  self.timelabel.text = [nsstring stringwithformat:@"%.2ld:%.2ld",_num/60,_num%60]; 
  _num ++; 
} 
 
 
/**取得指定位置的摄像头*/ 
- (avcapturedevice *)cameradevicewithposition:(avcapturedeviceposition )position{ 
  nsarray *cameras = [avcapturedevice deviceswithmediatype:avmediatypevideo]; 
  for (avcapturedevice *camera in cameras) { 
    if ([camera position] == position) { 
      return camera; 
    } 
  } 
  return nil; 
} 
  
@end 

参考代码:

#import "videotestviewcontroller.h" 
#import <avfoundation/avfoundation.h> 
#import <assetslibrary/assetslibrary.h> 
 
typedef void(^propertychangeblock)(avcapturedevice *capturedevice); 
 
@interface videotestviewcontroller ()<avcapturefileoutputrecordingdelegate>//视频文件输出代理 
 
@property (strong,nonatomic) avcapturesession *capturesession;//负责输入和输出设备之间的数据传递 
@property (strong,nonatomic) avcapturedeviceinput *capturedeviceinput;//负责从avcapturedevice获得输入数据 
@property (strong,nonatomic) avcapturemoviefileoutput *capturemoviefileoutput;//视频输出流 
@property (strong,nonatomic) avcapturevideopreviewlayer *capturevideopreviewlayer;//相机拍摄预览图层 
 
@property (assign,nonatomic) bool enablerotation;//是否允许旋转(注意在视频录制过程中禁止屏幕旋转) 
@property (assign,nonatomic) cgrect *lastbounds;//旋转的前大小 
@property (assign,nonatomic) uibackgroundtaskidentifier backgroundtaskidentifier;//后台任务标识 
@property (strong,nonatomic) uiview *viewcontainer; 
@property (strong,nonatomic) uibutton *takebutton;//拍照按钮 
@property (strong,nonatomic) uiimageview *focuscursor; //聚焦光标 
 
 
@end 
 
@implementation videotestviewcontroller 
 
#pragma mark - 控制器视图方法 
- (void)viewdidload { 
  [super viewdidload]; 
} 
 
-(void)viewwillappear:(bool)animated{ 
  [super viewwillappear:animated]; 
   
  //初始化会话 
  _capturesession=[[avcapturesession alloc]init]; 
  if ([_capturesession cansetsessionpreset:avcapturesessionpreset1280x720]) {//设置分辨率 
    _capturesession.sessionpreset=avcapturesessionpreset1280x720; 
  } 
  //获得输入设备 
  avcapturedevice *capturedevice=[self getcameradevicewithposition:avcapturedevicepositionback];//取得后置摄像头 
  if (!capturedevice) { 
    nslog(@"取得后置摄像头时出现问题."); 
    return; 
  } 
  //添加一个音频输入设备 
  avcapturedevice *audiocapturedevice=[[avcapturedevice deviceswithmediatype:avmediatypeaudio] firstobject]; 
   
   
  nserror *error=nil; 
  //根据输入设备初始化设备输入对象,用于获得输入数据 
  _capturedeviceinput=[[avcapturedeviceinput alloc]initwithdevice:capturedevice error:&error]; 
  if (error) { 
    nslog(@"取得设备输入对象时出错,错误原因:%@",error.localizeddescription); 
    return; 
  } 
  avcapturedeviceinput *audiocapturedeviceinput=[[avcapturedeviceinput alloc]initwithdevice:audiocapturedevice error:&error]; 
  if (error) { 
    nslog(@"取得设备输入对象时出错,错误原因:%@",error.localizeddescription); 
    return; 
  } 
  //初始化设备输出对象,用于获得输出数据 
  _capturemoviefileoutput=[[avcapturemoviefileoutput alloc]init]; 
   
  //将设备输入添加到会话中 
  if ([_capturesession canaddinput:_capturedeviceinput]) { 
    [_capturesession addinput:_capturedeviceinput]; 
    [_capturesession addinput:audiocapturedeviceinput]; 
    avcaptureconnection *captureconnection=[_capturemoviefileoutput connectionwithmediatype:avmediatypevideo]; 
    if ([captureconnection isvideostabilizationsupported ]) { 
      captureconnection.preferredvideostabilizationmode=avcapturevideostabilizationmodeauto; 
    } 
  } 
   
  //将设备输出添加到会话中 
  if ([_capturesession canaddoutput:_capturemoviefileoutput]) { 
    [_capturesession addoutput:_capturemoviefileoutput]; 
  } 
   
  //创建视频预览层,用于实时展示摄像头状态 
  _capturevideopreviewlayer=[[avcapturevideopreviewlayer alloc]initwithsession:self.capturesession]; 
   
  calayer *layer=self.viewcontainer.layer; 
  layer.maskstobounds=yes; 
   
  _capturevideopreviewlayer.frame=layer.bounds; 
  _capturevideopreviewlayer.videogravity=avlayervideogravityresizeaspectfill;//填充模式 
  //将视频预览层添加到界面中 
  //[layer addsublayer:_capturevideopreviewlayer]; 
  [layer insertsublayer:_capturevideopreviewlayer below:self.focuscursor.layer]; 
   
  _enablerotation=yes; 
  [self addnotificationtocapturedevice:capturedevice]; 
  [self addgensturerecognizer]; 
} 
 
-(void)viewdidappear:(bool)animated{ 
  [super viewdidappear:animated]; 
  [self.capturesession startrunning]; 
} 
 
-(void)viewdiddisappear:(bool)animated{ 
  [super viewdiddisappear:animated]; 
  [self.capturesession stoprunning]; 
} 
 
- (void)didreceivememorywarning { 
  [super didreceivememorywarning]; 
} 
 
-(bool)shouldautorotate{ 
  return self.enablerotation; 
} 
 
////屏幕旋转时调整视频预览图层的方向 
//-(void)willtransitiontotraitcollection:(uitraitcollection *)newcollection withtransitioncoordinator:(id<uiviewcontrollertransitioncoordinator>)coordinator{ 
//  [super willtransitiontotraitcollection:newcollection withtransitioncoordinator:coordinator]; 
////  nslog(@"%i,%i",newcollection.verticalsizeclass,newcollection.horizontalsizeclass); 
//  uiinterfaceorientation orientation = [[uiapplication sharedapplication] statusbarorientation]; 
//  nslog(@"%i",orientation); 
//  avcaptureconnection *captureconnection=[self.capturevideopreviewlayer connection]; 
//  captureconnection.videoorientation=orientation; 
// 
//} 
//屏幕旋转时调整视频预览图层的方向 
-(void)willrotatetointerfaceorientation:(uiinterfaceorientation)tointerfaceorientation duration:(nstimeinterval)duration{ 
  avcaptureconnection *captureconnection=[self.capturevideopreviewlayer connection]; 
  captureconnection.videoorientation=(avcapturevideoorientation)tointerfaceorientation; 
} 
//旋转后重新设置大小 
-(void)didrotatefrominterfaceorientation:(uiinterfaceorientation)frominterfaceorientation{ 
  _capturevideopreviewlayer.frame=self.viewcontainer.bounds; 
} 
 
-(void)dealloc{ 
  [self removenotification]; 
} 
#pragma mark - ui方法 
#pragma mark 视频录制 
- (void)takebuttonclick:(uibutton *)sender { 
  //根据设备输出获得连接 
  avcaptureconnection *captureconnection=[self.capturemoviefileoutput connectionwithmediatype:avmediatypevideo]; 
  //根据连接取得设备输出的数据 
  if (![self.capturemoviefileoutput isrecording]) { 
    self.enablerotation=no; 
    //如果支持多任务则则开始多任务 
    if ([[uidevice currentdevice] ismultitaskingsupported]) { 
      self.backgroundtaskidentifier=[[uiapplication sharedapplication] beginbackgroundtaskwithexpirationhandler:nil]; 
    } 
    //预览图层和视频方向保持一致 
    captureconnection.videoorientation=[self.capturevideopreviewlayer connection].videoorientation; 
    nsstring *outputfielpath=[nstemporarydirectory() stringbyappendingstring:@"mymovie.mov"]; 
    nslog(@"save path is :%@",outputfielpath); 
    nsurl *fileurl=[nsurl fileurlwithpath:outputfielpath]; 
    [self.capturemoviefileoutput startrecordingtooutputfileurl:fileurl recordingdelegate:self]; 
  } 
  else{ 
    [self.capturemoviefileoutput stoprecording];//停止录制 
  } 
} 
#pragma mark 切换前后摄像头 
- (void)togglebuttonclick:(uibutton *)sender { 
  avcapturedevice *currentdevice=[self.capturedeviceinput device]; 
  avcapturedeviceposition currentposition=[currentdevice position]; 
  [self removenotificationfromcapturedevice:currentdevice]; 
  avcapturedevice *tochangedevice; 
  avcapturedeviceposition tochangeposition=avcapturedevicepositionfront; 
  if (currentposition==avcapturedevicepositionunspecified||currentposition==avcapturedevicepositionfront) { 
    tochangeposition=avcapturedevicepositionback; 
  } 
  tochangedevice=[self getcameradevicewithposition:tochangeposition]; 
  [self addnotificationtocapturedevice:tochangedevice]; 
  //获得要调整的设备输入对象 
  avcapturedeviceinput *tochangedeviceinput=[[avcapturedeviceinput alloc]initwithdevice:tochangedevice error:nil]; 
   
  //改变会话的配置前一定要先开启配置,配置完成后提交配置改变 
  [self.capturesession beginconfiguration]; 
  //移除原有输入对象 
  [self.capturesession removeinput:self.capturedeviceinput]; 
  //添加新的输入对象 
  if ([self.capturesession canaddinput:tochangedeviceinput]) { 
    [self.capturesession addinput:tochangedeviceinput]; 
    self.capturedeviceinput=tochangedeviceinput; 
  } 
  //提交会话配置 
  [self.capturesession commitconfiguration]; 
   
} 
 
#pragma mark - 视频输出代理 
-(void)captureoutput:(avcapturefileoutput *)captureoutput didstartrecordingtooutputfileaturl:(nsurl *)fileurl fromconnections:(nsarray *)connections{ 
  nslog(@"开始录制..."); 
} 
-(void)captureoutput:(avcapturefileoutput *)captureoutput didfinishrecordingtooutputfileaturl:(nsurl *)outputfileurl fromconnections:(nsarray *)connections error:(nserror *)error{ 
  nslog(@"视频录制完成."); 
  //视频录入完成之后在后台将视频存储到相簿 
  self.enablerotation=yes; 
  uibackgroundtaskidentifier lastbackgroundtaskidentifier=self.backgroundtaskidentifier; 
  self.backgroundtaskidentifier=uibackgroundtaskinvalid; 
  alassetslibrary *assetslibrary=[[alassetslibrary alloc]init]; 
  [assetslibrary writevideoatpathtosavedphotosalbum:outputfileurl completionblock:^(nsurl *asseturl, nserror *error) { 
    if (error) { 
      nslog(@"保存视频到相簿过程中发生错误,错误信息:%@",error.localizeddescription); 
    } 
    if (lastbackgroundtaskidentifier!=uibackgroundtaskinvalid) { 
      [[uiapplication sharedapplication] endbackgroundtask:lastbackgroundtaskidentifier]; 
    } 
    nslog(@"成功保存视频到相簿."); 
  }]; 
   
} 
 
#pragma mark - 通知 
/** 
 * 给输入设备添加通知 
 */ 
-(void)addnotificationtocapturedevice:(avcapturedevice *)capturedevice{ 
  //注意添加区域改变捕获通知必须首先设置设备允许捕获 
  [self changedeviceproperty:^(avcapturedevice *capturedevice) { 
    capturedevice.subjectareachangemonitoringenabled=yes; 
  }]; 
  nsnotificationcenter *notificationcenter= [nsnotificationcenter defaultcenter]; 
  //捕获区域发生改变 
  [notificationcenter addobserver:self selector:@selector(areachange:) name:avcapturedevicesubjectareadidchangenotification object:capturedevice]; 
} 
-(void)removenotificationfromcapturedevice:(avcapturedevice *)capturedevice{ 
  nsnotificationcenter *notificationcenter= [nsnotificationcenter defaultcenter]; 
  [notificationcenter removeobserver:self name:avcapturedevicesubjectareadidchangenotification object:capturedevice]; 
} 
/** 
 * 移除所有通知 
 */ 
-(void)removenotification{ 
  nsnotificationcenter *notificationcenter= [nsnotificationcenter defaultcenter]; 
  [notificationcenter removeobserver:self]; 
} 
 
-(void)addnotificationtocapturesession:(avcapturesession *)capturesession{ 
  nsnotificationcenter *notificationcenter= [nsnotificationcenter defaultcenter]; 
  //会话出错 
  [notificationcenter addobserver:self selector:@selector(sessionruntimeerror:) name:avcapturesessionruntimeerrornotification object:capturesession]; 
} 
 
/** 
 * 设备连接成功 
 * 
 * @param notification 通知对象 
 */ 
-(void)deviceconnected:(nsnotification *)notification{ 
  nslog(@"设备已连接..."); 
} 
/** 
 * 设备连接断开 
 * 
 * @param notification 通知对象 
 */ 
-(void)devicedisconnected:(nsnotification *)notification{ 
  nslog(@"设备已断开."); 
} 
/** 
 * 捕获区域改变 
 * 
 * @param notification 通知对象 
 */ 
-(void)areachange:(nsnotification *)notification{ 
  nslog(@"捕获区域改变..."); 
} 
 
/** 
 * 会话出错 
 * 
 * @param notification 通知对象 
 */ 
-(void)sessionruntimeerror:(nsnotification *)notification{ 
  nslog(@"会话发生错误."); 
} 
 
#pragma mark - 私有方法 
 
/** 
 * 取得指定位置的摄像头 
 * 
 * @param position 摄像头位置 
 * 
 * @return 摄像头设备 
 */ 
-(avcapturedevice *)getcameradevicewithposition:(avcapturedeviceposition )position{ 
  nsarray *cameras= [avcapturedevice deviceswithmediatype:avmediatypevideo]; 
  for (avcapturedevice *camera in cameras) { 
    if ([camera position]==position) { 
      return camera; 
    } 
  } 
  return nil; 
} 
 
/** 
 * 改变设备属性的统一操作方法 
 * 
 * @param propertychange 属性改变操作 
 */ 
-(void)changedeviceproperty:(propertychangeblock)propertychange{ 
  avcapturedevice *capturedevice= [self.capturedeviceinput device]; 
  nserror *error; 
  //注意改变设备属性前一定要首先调用lockforconfiguration:调用完之后使用unlockforconfiguration方法解锁 
  if ([capturedevice lockforconfiguration:&error]) { 
    propertychange(capturedevice); 
    [capturedevice unlockforconfiguration]; 
  }else{ 
    nslog(@"设置设备属性过程发生错误,错误信息:%@",error.localizeddescription); 
  } 
} 
 
/** 
 * 设置闪光灯模式 
 * 
 * @param flashmode 闪光灯模式 
 */ 
-(void)setflashmode:(avcaptureflashmode )flashmode{ 
  [self changedeviceproperty:^(avcapturedevice *capturedevice) { 
    if ([capturedevice isflashmodesupported:flashmode]) { 
      [capturedevice setflashmode:flashmode]; 
    } 
  }]; 
} 
/** 
 * 设置聚焦模式 
 * 
 * @param focusmode 聚焦模式 
 */ 
-(void)setfocusmode:(avcapturefocusmode )focusmode{ 
  [self changedeviceproperty:^(avcapturedevice *capturedevice) { 
    if ([capturedevice isfocusmodesupported:focusmode]) { 
      [capturedevice setfocusmode:focusmode]; 
    } 
  }]; 
} 
/** 
 * 设置曝光模式 
 * 
 * @param exposuremode 曝光模式 
 */ 
-(void)setexposuremode:(avcaptureexposuremode)exposuremode{ 
  [self changedeviceproperty:^(avcapturedevice *capturedevice) { 
    if ([capturedevice isexposuremodesupported:exposuremode]) { 
      [capturedevice setexposuremode:exposuremode]; 
    } 
  }]; 
} 
/** 
 * 设置聚焦点 
 * 
 * @param point 聚焦点 
 */ 
-(void)focuswithmode:(avcapturefocusmode)focusmode exposuremode:(avcaptureexposuremode)exposuremode atpoint:(cgpoint)point{ 
  [self changedeviceproperty:^(avcapturedevice *capturedevice) { 
    if ([capturedevice isfocusmodesupported:focusmode]) { 
      [capturedevice setfocusmode:avcapturefocusmodeautofocus]; 
    } 
    if ([capturedevice isfocuspointofinterestsupported]) { 
      [capturedevice setfocuspointofinterest:point]; 
    } 
    if ([capturedevice isexposuremodesupported:exposuremode]) { 
      [capturedevice setexposuremode:avcaptureexposuremodeautoexpose]; 
    } 
    if ([capturedevice isexposurepointofinterestsupported]) { 
      [capturedevice setexposurepointofinterest:point]; 
    } 
  }]; 
} 
 
/** 
 * 添加点按手势,点按时聚焦 
 */ 
-(void)addgensturerecognizer{ 
  uitapgesturerecognizer *tapgesture=[[uitapgesturerecognizer alloc]initwithtarget:self action:@selector(tapscreen:)]; 
  [self.viewcontainer addgesturerecognizer:tapgesture]; 
} 
-(void)tapscreen:(uitapgesturerecognizer *)tapgesture{ 
  cgpoint point= [tapgesture locationinview:self.viewcontainer]; 
  //将ui坐标转化为摄像头坐标 
  cgpoint camerapoint= [self.capturevideopreviewlayer capturedevicepointofinterestforpoint:point]; 
  [self setfocuscursorwithpoint:point]; 
  [self focuswithmode:avcapturefocusmodeautofocus exposuremode:avcaptureexposuremodeautoexpose atpoint:camerapoint]; 
} 
 
/** 
 * 设置聚焦光标位置 
 * 
 * @param point 光标位置 
 */ 
-(void)setfocuscursorwithpoint:(cgpoint)point{ 
  self.focuscursor.center=point; 
  self.focuscursor.transform=cgaffinetransformmakescale(1.5, 1.5); 
  self.focuscursor.alpha=1.0; 
  [uiview animatewithduration:1.0 animations:^{ 
    self.focuscursor.transform=cgaffinetransformidentity; 
  } completion:^(bool finished) { 
    self.focuscursor.alpha=0; 
  }]; 
} 
@end 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网