iOS仿微信相机拍照、视频录制功能
网上有很多自定义相机的例子,这里只是我临时写的一个iOS自定义相机(仿微信)拍照、视频录制demo,仅供参考:
用到了下面几个库:
#import#import
在使用的时候需要在Info.plist中把相关权限写进去:
Privacy-MicrophoneUsageDescription Privacy-PhotoLibraryUsageDescription Privacy-CameraUsageDescription
我在写这个demo时,是按照微信的样式写的,同样是点击拍照、长按录制视频,视频录制完直接进行播放,这里封装了一个简易的播放器:
m文件
#import"HAVPlayer.h" #import@interfaceHAVPlayer() @property(nonatomic,strong)AVPlayer*player;//播放器对象 @end @implementationHAVPlayer /* //OnlyoverridedrawRect:ifyouperformcustomdrawing. //Anemptyimplementationadverselyaffectsperformanceduringanimation. -(void)drawRect:(CGRect)rect{ //Drawingcode } */ -(instancetype)initWithFrame:(CGRect)framewithShowInView:(UIView*)bgViewurl:(NSURL*)url{ if(self=[selfinitWithFrame:frame]){ //创建播放器层 AVPlayerLayer*playerLayer=[AVPlayerLayerplayerLayerWithPlayer:self.player]; playerLayer.frame=self.bounds; [self.layeraddSublayer:playerLayer]; if(url){ self.videoUrl=url; } [bgViewaddSubview:self]; } returnself; } -(void)dealloc{ [selfremoveAvPlayerNtf]; [selfstopPlayer]; self.player=nil; } -(AVPlayer*)player{ if(!_player){ _player=[AVPlayerplayerWithPlayerItem:[selfgetAVPlayerItem]]; [selfaddAVPlayerNtf:_player.currentItem]; } return_player; } -(AVPlayerItem*)getAVPlayerItem{ AVPlayerItem*playerItem=[AVPlayerItemplayerItemWithURL:self.videoUrl]; returnplayerItem; } -(void)setVideoUrl:(NSURL*)videoUrl{ _videoUrl=videoUrl; [selfremoveAvPlayerNtf]; [selfnextPlayer]; } -(void)nextPlayer{ [self.playerseekToTime:CMTimeMakeWithSeconds(0,_player.currentItem.duration.timescale)]; [self.playerreplaceCurrentItemWithPlayerItem:[selfgetAVPlayerItem]]; [selfaddAVPlayerNtf:self.player.currentItem]; if(self.player.rate==0){ [self.playerplay]; } } -(void)addAVPlayerNtf:(AVPlayerItem*)playerItem{ //监控状态属性 [playerItemaddObserver:selfforKeyPath:@"status"options:NSKeyValueObservingOptionNewcontext:nil]; //监控网络加载情况属性 [playerItemaddObserver:selfforKeyPath:@"loadedTimeRanges"options:NSKeyValueObservingOptionNewcontext:nil]; [[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(playbackFinished:)name:AVPlayerItemDidPlayToEndTimeNotificationobject:self.player.currentItem]; } -(void)removeAvPlayerNtf{ AVPlayerItem*playerItem=self.player.currentItem; [playerItemremoveObserver:selfforKeyPath:@"status"]; [playerItemremoveObserver:selfforKeyPath:@"loadedTimeRanges"]; [[NSNotificationCenterdefaultCenter]removeObserver:self]; } -(void)stopPlayer{ if(self.player.rate==1){ [self.playerpause];//如果在播放状态就停止 } } /** *通过KVO监控播放器状态 * *@paramkeyPath监控属性 *@paramobject监视器 *@paramchange状态改变 *@paramcontext上下文 */ -(void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionary*)changecontext:(void*)context{ AVPlayerItem*playerItem=object; if([keyPathisEqualToString:@"status"]){ AVPlayerStatusstatus=[[changeobjectForKey:@"new"]intValue]; if(status==AVPlayerStatusReadyToPlay){ NSLog(@"正在播放...,视频总长度:%.2f",CMTimeGetSeconds(playerItem.duration)); } }elseif([keyPathisEqualToString:@"loadedTimeRanges"]){ NSArray*array=playerItem.loadedTimeRanges; CMTimeRangetimeRange=[array.firstObjectCMTimeRangeValue];//本次缓冲时间范围 floatstartSeconds=CMTimeGetSeconds(timeRange.start); floatdurationSeconds=CMTimeGetSeconds(timeRange.duration); NSTimeIntervaltotalBuffer=startSeconds+durationSeconds;//缓冲总长度 NSLog(@"共缓冲:%.2f",totalBuffer); } } -(void)playbackFinished:(NSNotification*)ntf{ Plog(@"视频播放完成"); [self.playerseekToTime:CMTimeMake(0,1)]; [self.playerplay]; } @end
另外微信下面的按钮长按会出现圆弧时间条:
m文件
#import"HProgressView.h" @interfaceHProgressView() /** *进度值0-1.0之间 */ @property(nonatomic,assign)CGFloatprogressValue; @property(nonatomic,assign)CGFloatcurrentTime; @end @implementationHProgressView //OnlyoverridedrawRect:ifyouperformcustomdrawing. //Anemptyimplementationadverselyaffectsperformanceduringanimation. -(void)drawRect:(CGRect)rect{ //Drawingcode CGContextRefctx=UIGraphicsGetCurrentContext();//获取上下文 Plog(@"width=%f",self.frame.size.width); CGPointcenter=CGPointMake(self.frame.size.width/2.0,self.frame.size.width/2.0);//设置圆心位置 CGFloatradius=self.frame.size.width/2.0-5;//设置半径 CGFloatstartA=-M_PI_2;//圆起点位置 CGFloatendA=-M_PI_2+M_PI*2*_progressValue;//圆终点位置 UIBezierPath*path=[UIBezierPathbezierPathWithArcCenter:centerradius:radiusstartAngle:startAendAngle:endAclockwise:YES]; CGContextSetLineWidth(ctx,10);//设置线条宽度 [[UIColorwhiteColor]setStroke];//设置描边颜色 CGContextAddPath(ctx,path.CGPath);//把路径添加到上下文 CGContextStrokePath(ctx);//渲染 } -(void)setTimeMax:(NSInteger)timeMax{ _timeMax=timeMax; self.currentTime=0; self.progressValue=0; [selfsetNeedsDisplay]; self.hidden=NO; [selfperformSelector:@selector(startProgress)withObject:nilafterDelay:0.1]; } -(void)clearProgress{ _currentTime=_timeMax; self.hidden=YES; } -(void)startProgress{ _currentTime+=0.1; if(_timeMax>_currentTime){ _progressValue=_currentTime/_timeMax; Plog(@"progress=%f",_progressValue); [selfsetNeedsDisplay]; [selfperformSelector:@selector(startProgress)withObject:nilafterDelay:0.1]; } if(_timeMax<=_currentTime){ [selfclearProgress]; } } @end
接下来就是相机的控制器了,由于是临时写的,所以用的xib,大家不要直接使用,直接上m文件代码吧:
#import"HVideoViewController.h" #import#import"HAVPlayer.h" #import"HProgressView.h" #import #import typedefvoid(^PropertyChangeBlock)(AVCaptureDevice*captureDevice); @interfaceHVideoViewController() //轻触拍照,按住摄像 @property(strong,nonatomic)IBOutletUILabel*labelTipTitle; //视频输出流 @property(strong,nonatomic)AVCaptureMovieFileOutput*captureMovieFileOutput; //图片输出流 //@property(strong,nonatomic)AVCaptureStillImageOutput*captureStillImageOutput;//照片输出流 //负责从AVCaptureDevice获得输入数据 @property(strong,nonatomic)AVCaptureDeviceInput*captureDeviceInput; //后台任务标识 @property(assign,nonatomic)UIBackgroundTaskIdentifierbackgroundTaskIdentifier; @property(assign,nonatomic)UIBackgroundTaskIdentifierlastBackgroundTaskIdentifier; @property(weak,nonatomic)IBOutletUIImageView*focusCursor;//聚焦光标 //负责输入和输出设备之间的数据传递 @property(nonatomic)AVCaptureSession*session; //图像预览层,实时显示捕获的图像 @property(nonatomic)AVCaptureVideoPreviewLayer*previewLayer; @property(strong,nonatomic)IBOutletUIButton*btnBack; //重新录制 @property(strong,nonatomic)IBOutletUIButton*btnAfresh; //确定 @property(strong,nonatomic)IBOutletUIButton*btnEnsure; //摄像头切换 @property(strong,nonatomic)IBOutletUIButton*btnCamera; @property(strong,nonatomic)IBOutletUIImageView*bgView; //记录录制的时间默认最大60秒 @property(assign,nonatomic)NSIntegerseconds; //记录需要保存视频的路径 @property(strong,nonatomic)NSURL*saveVideoUrl; //是否在对焦 @property(assign,nonatomic)BOOLisFocus; @property(strong,nonatomic)IBOutletNSLayoutConstraint*afreshCenterX; @property(strong,nonatomic)IBOutletNSLayoutConstraint*ensureCenterX; @property(strong,nonatomic)IBOutletNSLayoutConstraint*backCenterX; //视频播放 @property(strong,nonatomic)HAVPlayer*player; @property(strong,nonatomic)IBOutletHProgressView*progressView; //是否是摄像YES代表是录制NO表示拍照 @property(assign,nonatomic)BOOLisVideo; @property(strong,nonatomic)UIImage*takeImage; @property(strong,nonatomic)UIImageView*takeImageView; @property(strong,nonatomic)IBOutletUIImageView*imgRecord; @end //时间大于这个就是视频,否则为拍照 #defineTimeMax1 @implementationHVideoViewController -(void)dealloc{ [selfremoveNotification]; } -(void)viewDidLoad{ [superviewDidLoad]; //Doanyadditionalsetupafterloadingtheview. UIImage*image=[UIImageimageNamed:@"sc_btn_take.png"]; self.backCenterX.constant=-(SCREEN_WIDTH/2/2)-image.size.width/2/2; self.progressView.layer.cornerRadius=self.progressView.frame.size.width/2; if(self.HSeconds==0){ self.HSeconds=60; } [selfperformSelector:@selector(hiddenTipsLabel)withObject:nilafterDelay:4]; } -(void)hiddenTipsLabel{ self.labelTipTitle.hidden=YES; } -(void)didReceiveMemoryWarning{ [superdidReceiveMemoryWarning]; //Disposeofanyresourcesthatcanberecreated. } -(void)viewWillAppear:(BOOL)animated{ [superviewWillAppear:animated]; [[UIApplicationsharedApplication]setStatusBarHidden:YES]; [selfcustomCamera]; [self.sessionstartRunning]; } -(void)viewDidAppear:(BOOL)animated{ [superviewDidAppear:animated]; } -(void)viewDidDisappear:(BOOL)animated{ [superviewDidDisappear:animated]; [self.sessionstopRunning]; } -(void)viewWillDisappear:(BOOL)animated{ [superviewWillDisappear:animated]; [[UIApplicationsharedApplication]setStatusBarHidden:NO]; } -(void)customCamera{ //初始化会话,用来结合输入输出 self.session=[[AVCaptureSessionalloc]init]; //设置分辨率(设备支持的最高分辨率) if([self.sessioncanSetSessionPreset:AVCaptureSessionPresetHigh]){ self.session.sessionPreset=AVCaptureSessionPresetHigh; } //取得后置摄像头 AVCaptureDevice*captureDevice=[selfgetCameraDeviceWithPosition:AVCaptureDevicePositionBack]; //添加一个音频输入设备 AVCaptureDevice*audioCaptureDevice=[[AVCaptureDevicedevicesWithMediaType:AVMediaTypeAudio]firstObject]; //初始化输入设备 NSError*error=nil; self.captureDeviceInput=[[AVCaptureDeviceInputalloc]initWithDevice:captureDeviceerror:&error]; if(error){ Plog(@"取得设备输入对象时出错,错误原因:%@",error.localizedDescription); return; } //添加音频 error=nil; AVCaptureDeviceInput*audioCaptureDeviceInput=[[AVCaptureDeviceInputalloc]initWithDevice:audioCaptureDeviceerror:&error]; if(error){ NSLog(@"取得设备输入对象时出错,错误原因:%@",error.localizedDescription); return; } //输出对象 self.captureMovieFileOutput=[[AVCaptureMovieFileOutputalloc]init];//视频输出 //将输入设备添加到会话 if([self.sessioncanAddInput:self.captureDeviceInput]){ [self.sessionaddInput:self.captureDeviceInput]; [self.sessionaddInput:audioCaptureDeviceInput]; //设置视频防抖 AVCaptureConnection*connection=[self.captureMovieFileOutputconnectionWithMediaType:AVMediaTypeVideo]; if([connectionisVideoStabilizationSupported]){ connection.preferredVideoStabilizationMode=AVCaptureVideoStabilizationModeCinematic; } } //将输出设备添加到会话(刚开始是照片为输出对象) if([self.sessioncanAddOutput:self.captureMovieFileOutput]){ [self.sessionaddOutput:self.captureMovieFileOutput]; } //创建视频预览层,用于实时展示摄像头状态 self.previewLayer=[[AVCaptureVideoPreviewLayeralloc]initWithSession:self.session]; self.previewLayer.frame=self.view.bounds;//CGRectMake(0,0,self.view.width,self.view.height); self.previewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;//填充模式 [self.bgView.layeraddSublayer:self.previewLayer]; [selfaddNotificationToCaptureDevice:captureDevice]; [selfaddGenstureRecognizer]; } -(IBAction)onCancelAction:(UIButton*)sender{ [selfdismissViewControllerAnimated:YEScompletion:^{ [UtilityhideProgressDialog]; }]; } -(void)touchesBegan:(NSSet *)toucheswithEvent:(UIEvent*)event{ if([[touchesanyObject]view]==self.imgRecord){ Plog(@"开始录制"); //根据设备输出获得连接 AVCaptureConnection*connection=[self.captureMovieFileOutputconnectionWithMediaType:AVMediaTypeAudio]; //根据连接取得设备输出的数据 if(![self.captureMovieFileOutputisRecording]){ //如果支持多任务则开始多任务 if([[UIDevicecurrentDevice]isMultitaskingSupported]){ self.backgroundTaskIdentifier=[[UIApplicationsharedApplication]beginBackgroundTaskWithExpirationHandler:nil]; } if(self.saveVideoUrl){ [[NSFileManagerdefaultManager]removeItemAtURL:self.saveVideoUrlerror:nil]; } //预览图层和视频方向保持一致 connection.videoOrientation=[self.previewLayerconnection].videoOrientation; NSString*outputFielPath=[NSTemporaryDirectory()stringByAppendingString:@"myMovie.mov"]; NSLog(@"savepathis:%@",outputFielPath); NSURL*fileUrl=[NSURLfileURLWithPath:outputFielPath]; NSLog(@"fileUrl:%@",fileUrl); [self.captureMovieFileOutputstartRecordingToOutputFileURL:fileUrlrecordingDelegate:self]; }else{ [self.captureMovieFileOutputstopRecording]; } } } -(void)touchesEnded:(NSSet *)toucheswithEvent:(UIEvent*)event{ if([[touchesanyObject]view]==self.imgRecord){ Plog(@"结束触摸"); if(!self.isVideo){ [selfperformSelector:@selector(endRecord)withObject:nilafterDelay:0.3]; }else{ [selfendRecord]; } } } -(void)endRecord{ [self.captureMovieFileOutputstopRecording];//停止录制 } -(IBAction)onAfreshAction:(UIButton*)sender{ Plog(@"重新录制"); [selfrecoverLayout]; } -(IBAction)onEnsureAction:(UIButton*)sender{ Plog(@"确定这里进行保存或者发送出去"); if(self.saveVideoUrl){ WS(weakSelf) [UtilityshowProgressDialogText:@"视频处理中..."]; ALAssetsLibrary*assetsLibrary=[[ALAssetsLibraryalloc]init]; [assetsLibrarywriteVideoAtPathToSavedPhotosAlbum:self.saveVideoUrlcompletionBlock:^(NSURL*assetURL,NSError*error){ Plog(@"outputUrl:%@",weakSelf.saveVideoUrl); [[NSFileManagerdefaultManager]removeItemAtURL:weakSelf.saveVideoUrlerror:nil]; if(weakSelf.lastBackgroundTaskIdentifier!=UIBackgroundTaskInvalid){ [[UIApplicationsharedApplication]endBackgroundTask:weakSelf.lastBackgroundTaskIdentifier]; } if(error){ Plog(@"保存视频到相簿过程中发生错误,错误信息:%@",error.localizedDescription); [UtilityshowAllTextDialog:KAppDelegate.windowText:@"保存视频到相册发生错误"]; }else{ if(weakSelf.takeBlock){ weakSelf.takeBlock(assetURL); } Plog(@"成功保存视频到相簿."); [weakSelfonCancelAction:nil]; } }]; }else{ //照片 UIImageWriteToSavedPhotosAlbum(self.takeImage,self,nil,nil); if(self.takeBlock){ self.takeBlock(self.takeImage); } [selfonCancelAction:nil]; } } //前后摄像头的切换 -(IBAction)onCameraAction:(UIButton*)sender{ Plog(@"切换摄像头"); AVCaptureDevice*currentDevice=[self.captureDeviceInputdevice]; AVCaptureDevicePositioncurrentPosition=[currentDeviceposition]; [selfremoveNotificationFromCaptureDevice:currentDevice]; AVCaptureDevice*toChangeDevice; AVCaptureDevicePositiontoChangePosition=AVCaptureDevicePositionFront;//前 if(currentPosition==AVCaptureDevicePositionUnspecified||currentPosition==AVCaptureDevicePositionFront){ toChangePosition=AVCaptureDevicePositionBack;//后 } toChangeDevice=[selfgetCameraDeviceWithPosition:toChangePosition]; [selfaddNotificationToCaptureDevice:toChangeDevice]; //获得要调整的设备输入对象 AVCaptureDeviceInput*toChangeDeviceInput=[[AVCaptureDeviceInputalloc]initWithDevice:toChangeDeviceerror:nil]; //改变会话的配置前一定要先开启配置,配置完成后提交配置改变 [self.sessionbeginConfiguration]; //移除原有输入对象 [self.sessionremoveInput:self.captureDeviceInput]; //添加新的输入对象 if([self.sessioncanAddInput:toChangeDeviceInput]){ [self.sessionaddInput:toChangeDeviceInput]; self.captureDeviceInput=toChangeDeviceInput; } //提交会话配置 [self.sessioncommitConfiguration]; } -(void)onStartTranscribe:(NSURL*)fileURL{ if([self.captureMovieFileOutputisRecording]){ --self.seconds; if(self.seconds>0){ if(self.HSeconds-self.seconds>=TimeMax&&!self.isVideo){ self.isVideo=YES;//长按时间超过TimeMax表示是视频录制 self.progressView.timeMax=self.seconds; } [selfperformSelector:@selector(onStartTranscribe:)withObject:fileURLafterDelay:1.0]; }else{ if([self.captureMovieFileOutputisRecording]){ [self.captureMovieFileOutputstopRecording]; } } } } #pragmamark-视频输出代理 -(void)captureOutput:(AVCaptureFileOutput*)captureOutputdidStartRecordingToOutputFileAtURL:(NSURL*)fileURLfromConnections:(NSArray*)connections{ Plog(@"开始录制..."); self.seconds=self.HSeconds; [selfperformSelector:@selector(onStartTranscribe:)withObject:fileURLafterDelay:1.0]; } -(void)captureOutput:(AVCaptureFileOutput*)captureOutputdidFinishRecordingToOutputFileAtURL:(NSURL*)outputFileURLfromConnections:(NSArray*)connectionserror:(NSError*)error{ Plog(@"视频录制完成."); [selfchangeLayout]; if(self.isVideo){ self.saveVideoUrl=outputFileURL; if(!self.player){ self.player=[[HAVPlayeralloc]initWithFrame:self.bgView.boundswithShowInView:self.bgViewurl:outputFileURL]; }else{ if(outputFileURL){ self.player.videoUrl=outputFileURL; self.player.hidden=NO; } } }else{ //照片 self.saveVideoUrl=nil; [selfvideoHandlePhoto:outputFileURL]; } } -(void)videoHandlePhoto:(NSURL*)url{ AVURLAsset*urlSet=[AVURLAssetassetWithURL:url]; AVAssetImageGenerator*imageGenerator=[AVAssetImageGeneratorassetImageGeneratorWithAsset:urlSet]; imageGenerator.appliesPreferredTrackTransform=YES;//截图的时候调整到正确的方向 NSError*error=nil; CMTimetime=CMTimeMake(0,30);//缩略图创建时间CMTime是表示电影时间信息的结构体,第一个参数表示是视频第几秒,第二个参数表示每秒帧数.(如果要获取某一秒的第几帧可以使用CMTimeMake方法) CMTimeactucalTime;//缩略图实际生成的时间 CGImageRefcgImage=[imageGeneratorcopyCGImageAtTime:timeactualTime:&actucalTimeerror:&error]; if(error){ Plog(@"截取视频图片失败:%@",error.localizedDescription); } CMTimeShow(actucalTime); UIImage*image=[UIImageimageWithCGImage:cgImage]; CGImageRelease(cgImage); if(image){ Plog(@"视频截取成功"); }else{ Plog(@"视频截取失败"); } self.takeImage=image;//[UIImageimageWithCGImage:cgImage]; [[NSFileManagerdefaultManager]removeItemAtURL:urlerror:nil]; if(!self.takeImageView){ self.takeImageView=[[UIImageViewalloc]initWithFrame:self.view.frame]; [self.bgViewaddSubview:self.takeImageView]; } self.takeImageView.hidden=NO; self.takeImageView.image=self.takeImage; } #pragmamark-通知 //注册通知 -(void)setupObservers { NSNotificationCenter*notification=[NSNotificationCenterdefaultCenter]; [notificationaddObserver:selfselector:@selector(applicationDidEnterBackground:)name:UIApplicationWillResignActiveNotificationobject:[UIApplicationsharedApplication]]; } //进入后台就退出视频录制 -(void)applicationDidEnterBackground:(NSNotification*)notification{ [selfonCancelAction:nil]; } /** *给输入设备添加通知 */ -(void)addNotificationToCaptureDevice:(AVCaptureDevice*)captureDevice{ //注意添加区域改变捕获通知必须首先设置设备允许捕获 [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice){ captureDevice.subjectAreaChangeMonitoringEnabled=YES; }]; NSNotificationCenter*notificationCenter=[NSNotificationCenterdefaultCenter]; //捕获区域发生改变 [notificationCenteraddObserver:selfselector:@selector(areaChange:)name:AVCaptureDeviceSubjectAreaDidChangeNotificationobject:captureDevice]; } -(void)removeNotificationFromCaptureDevice:(AVCaptureDevice*)captureDevice{ NSNotificationCenter*notificationCenter=[NSNotificationCenterdefaultCenter]; [notificationCenterremoveObserver:selfname:AVCaptureDeviceSubjectAreaDidChangeNotificationobject:captureDevice]; } /** *移除所有通知 */ -(void)removeNotification{ NSNotificationCenter*notificationCenter=[NSNotificationCenterdefaultCenter]; [notificationCenterremoveObserver:self]; } -(void)addNotificationToCaptureSession:(AVCaptureSession*)captureSession{ NSNotificationCenter*notificationCenter=[NSNotificationCenterdefaultCenter]; //会话出错 [notificationCenteraddObserver:selfselector:@selector(sessionRuntimeError:)name:AVCaptureSessionRuntimeErrorNotificationobject:captureSession]; } /** *设备连接成功 * *@paramnotification通知对象 */ -(void)deviceConnected:(NSNotification*)notification{ NSLog(@"设备已连接..."); } /** *设备连接断开 * *@paramnotification通知对象 */ -(void)deviceDisconnected:(NSNotification*)notification{ NSLog(@"设备已断开."); } /** *捕获区域改变 * *@paramnotification通知对象 */ -(void)areaChange:(NSNotification*)notification{ NSLog(@"捕获区域改变..."); } /** *会话出错 * *@paramnotification通知对象 */ -(void)sessionRuntimeError:(NSNotification*)notification{ NSLog(@"会话发生错误."); } /** *取得指定位置的摄像头 * *@paramposition摄像头位置 * *@return摄像头设备 */ -(AVCaptureDevice*)getCameraDeviceWithPosition:(AVCaptureDevicePosition)position{ NSArray*cameras=[AVCaptureDevicedevicesWithMediaType:AVMediaTypeVideo]; for(AVCaptureDevice*cameraincameras){ if([cameraposition]==position){ returncamera; } } returnnil; } /** *改变设备属性的统一操作方法 * *@parampropertyChange属性改变操作 */ -(void)changeDeviceProperty:(PropertyChangeBlock)propertyChange{ AVCaptureDevice*captureDevice=[self.captureDeviceInputdevice]; NSError*error; //注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁 if([captureDevicelockForConfiguration:&error]){ //自动白平衡 if([captureDeviceisWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]){ [captureDevicesetWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]; } //自动根据环境条件开启闪光灯 if([captureDeviceisFlashModeSupported:AVCaptureFlashModeAuto]){ [captureDevicesetFlashMode:AVCaptureFlashModeAuto]; } propertyChange(captureDevice); [captureDeviceunlockForConfiguration]; }else{ NSLog(@"设置设备属性过程发生错误,错误信息:%@",error.localizedDescription); } } /** *设置闪光灯模式 * *@paramflashMode闪光灯模式 */ -(void)setFlashMode:(AVCaptureFlashMode)flashMode{ [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice){ if([captureDeviceisFlashModeSupported:flashMode]){ [captureDevicesetFlashMode:flashMode]; } }]; } /** *设置聚焦模式 * *@paramfocusMode聚焦模式 */ -(void)setFocusMode:(AVCaptureFocusMode)focusMode{ [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice){ if([captureDeviceisFocusModeSupported:focusMode]){ [captureDevicesetFocusMode:focusMode]; } }]; } /** *设置曝光模式 * *@paramexposureMode曝光模式 */ -(void)setExposureMode:(AVCaptureExposureMode)exposureMode{ [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice){ if([captureDeviceisExposureModeSupported:exposureMode]){ [captureDevicesetExposureMode:exposureMode]; } }]; } /** *设置聚焦点 * *@parampoint聚焦点 */ -(void)focusWithMode:(AVCaptureFocusMode)focusModeexposureMode:(AVCaptureExposureMode)exposureModeatPoint:(CGPoint)point{ [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice){ //if([captureDeviceisFocusPointOfInterestSupported]){ //[captureDevicesetFocusPointOfInterest:point]; //} //if([captureDeviceisExposurePointOfInterestSupported]){ //[captureDevicesetExposurePointOfInterest:point]; //} if([captureDeviceisExposureModeSupported:exposureMode]){ [captureDevicesetExposureMode:exposureMode]; } if([captureDeviceisFocusModeSupported:focusMode]){ [captureDevicesetFocusMode:focusMode]; } }]; } /** *添加点按手势,点按时聚焦 */ -(void)addGenstureRecognizer{ UITapGestureRecognizer*tapGesture=[[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(tapScreen:)]; [self.bgViewaddGestureRecognizer:tapGesture]; } -(void)tapScreen:(UITapGestureRecognizer*)tapGesture{ if([self.sessionisRunning]){ CGPointpoint=[tapGesturelocationInView:self.bgView]; //将UI坐标转化为摄像头坐标 CGPointcameraPoint=[self.previewLayercaptureDevicePointOfInterestForPoint:point]; [selfsetFocusCursorWithPoint:point]; [selffocusWithMode:AVCaptureFocusModeContinuousAutoFocusexposureMode:AVCaptureExposureModeContinuousAutoExposureatPoint:cameraPoint]; } } /** *设置聚焦光标位置 * *@parampoint光标位置 */ -(void)setFocusCursorWithPoint:(CGPoint)point{ if(!self.isFocus){ self.isFocus=YES; self.focusCursor.center=point; self.focusCursor.transform=CGAffineTransformMakeScale(1.25,1.25); self.focusCursor.alpha=1.0; [UIViewanimateWithDuration:0.5animations:^{ self.focusCursor.transform=CGAffineTransformIdentity; }completion:^(BOOLfinished){ [selfperformSelector:@selector(onHiddenFocusCurSorAction)withObject:nilafterDelay:0.5]; }]; } } -(void)onHiddenFocusCurSorAction{ self.focusCursor.alpha=0; self.isFocus=NO; } //拍摄完成时调用 -(void)changeLayout{ self.imgRecord.hidden=YES; self.btnCamera.hidden=YES; self.btnAfresh.hidden=NO; self.btnEnsure.hidden=NO; self.btnBack.hidden=YES; if(self.isVideo){ [self.progressViewclearProgress]; } self.afreshCenterX.constant=-(SCREEN_WIDTH/2/2); self.ensureCenterX.constant=SCREEN_WIDTH/2/2; [UIViewanimateWithDuration:0.25animations:^{ [self.viewlayoutIfNeeded]; }]; self.lastBackgroundTaskIdentifier=self.backgroundTaskIdentifier; self.backgroundTaskIdentifier=UIBackgroundTaskInvalid; [self.sessionstopRunning]; } //重新拍摄时调用 -(void)recoverLayout{ if(self.isVideo){ self.isVideo=NO; [self.playerstopPlayer]; self.player.hidden=YES; } [self.sessionstartRunning]; if(!self.takeImageView.hidden){ self.takeImageView.hidden=YES; } //self.saveVideoUrl=nil; self.afreshCenterX.constant=0; self.ensureCenterX.constant=0; self.imgRecord.hidden=NO; self.btnCamera.hidden=NO; self.btnAfresh.hidden=YES; self.btnEnsure.hidden=YES; self.btnBack.hidden=NO; [UIViewanimateWithDuration:0.25animations:^{ [self.viewlayoutIfNeeded]; }]; } /* #pragmamark-Navigation //Inastoryboard-basedapplication,youwilloftenwanttodoalittlepreparationbeforenavigation -(void)prepareForSegue:(UIStoryboardSegue*)seguesender:(id)sender{ //Getthenewviewcontrollerusing[seguedestinationViewController]. //Passtheselectedobjecttothenewviewcontroller. } */ @end
使用也挺简单:
-(IBAction)onCameraAction:(UIButton*)sender{ //额。。由于是demo,所以用的xib,大家根据需求自己更改,该demo只是提供一个思路,使用时不要直接拖入项目 HVideoViewController*ctrl=[[NSBundlemainBundle]loadNibNamed:@"HVideoViewController"owner:niloptions:nil].lastObject; ctrl.HSeconds=30;//设置可录制最长时间 ctrl.takeBlock=^(iditem){ if([itemisKindOfClass:[NSURLclass]]){ NSURL*videoURL=item; //视频url }else{ //图片 } }; [selfpresentViewController:ctrlanimated:YEScompletion:nil]; }
demo地址也给出来吧:不喜勿碰-_-\
KJCamera
自此就结束啦,写的比较简单,希望能帮助到大家,谢谢!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。