欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS AVCaptureSession实现视频录制功能

程序员文章站 2023-12-14 22:24:10
本文实例为大家分享了avcapturesession实现视频录制功能的具体代码,供大家参考,具体内容如下 #import "recordingvideoviewc...

本文实例为大家分享了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 

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

上一篇:

下一篇: