iOS短视频:基于GPUIMage的短视频录制(GPUImage自定义相机)
生活随笔
收集整理的這篇文章主要介紹了
iOS短视频:基于GPUIMage的短视频录制(GPUImage自定义相机)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
主要涉及到的GPUIMage的類
- GPUImageVideoCamera:錄制視頻,采集數據使用到的類,GPUImage中一種是GPUImageStillCamera,另一種為GPUImageVideoCamera.正如其命名,如果只是拍照使用前者.錄制視頻使用后者.
- GPUImageView:用于顯示視頻的GPUImageView
- GPUImageBeautifyFilter:繼承自GPUImageFilterGroup,涉及使用到的類有GPUImageBilateralFilter(磨皮:本質就是讓像素點模糊,可以使用高斯模糊,但是可能導致邊緣會不清晰,用雙邊濾波(Bilateral Filter) ,有針對性的模糊像素點,能保證邊緣不被模糊。),GPUImageCannyEdgeDetectionFilter(邊緣檢測算法,更強烈的黑白對比度),GPUImageCombinationFilter(組合濾鏡),GPUImageHSBFilter(線性亮度調節)。
- GPUImageMovieWriter:用于保存濾鏡處理過的視頻
視頻錄制整體原理
- 首先通過GPUImageVideoCamera采集音視頻數據
- 視頻部分:經過filter濾鏡的視頻幀分兩步,一步用于在屏幕預覽GPUImageView上顯示,另一步用于寫入GPUImageMovieWriter。
- 音頻部分:從GPUImageVideoCamera分離的音頻直接寫入GPUImageMovieWriter。另外,如果需要對音頻進行混響、變聲等處理,可以從這個節點分支處理寫入。
視頻錄制具體實現流程
初始化相機
//AVCaptureSessionPreset1280x720 相機分辨率//AVCaptureDevicePositionBack 后置攝像頭//AVCaptureDevicePositionFront 前置攝像頭//GPUImageVideoCamera用于錄制視頻,采集數據videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset1280x720 cameraPosition:AVCaptureDevicePositionBack];//Alan 為了在AVCaptureDevice上設置硬件屬性,比如focusMode和exposureMode,客戶端必須首先獲取設備上的鎖。if ([videoCamera.inputCamera lockForConfiguration:nil]) {//自動對焦if ([videoCamera.inputCamera isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {[videoCamera.inputCamera setFocusMode:AVCaptureFocusModeContinuousAutoFocus];}//自動曝光if ([videoCamera.inputCamera isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {[videoCamera.inputCamera setExposureMode:AVCaptureExposureModeContinuousAutoExposure];}//自動白平衡if ([videoCamera.inputCamera isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]) {[videoCamera.inputCamera setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];} //Alan 解鎖設備,提交配置[videoCamera.inputCamera unlockForConfiguration];}_position = CameraManagerDevicePositionBack;//豎屏方向采集數據videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;//錄制的時候添加聲音,添加輸入源和輸出源會暫時會使錄制暫時卡住,所以在要使用聲音的情況下要先調用該方法來防止錄制被卡住。[videoCamera addAudioInputsAndOutputs];//前置不是鏡像,后置是鏡像videoCamera.horizontallyMirrorFrontFacingCamera = YES;videoCamera.horizontallyMirrorRearFacingCamera = NO;//先添加一個空的濾鏡filter = [[LFGPUImageEmptyFilter alloc] init];//用于顯示視頻的GPUImageViewfilteredVideoView = [[GPUImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];[videoCamera addTarget:filter];[filter addTarget:filteredVideoView];給相機設置UI
timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 27.0, 80, 26.0)];timeLabel.font = [UIFont systemFontOfSize:13.0f];timeLabel.text = @"錄制 00:00";timeLabel.textAlignment = NSTextAlignmentCenter;timeLabel.backgroundColor = [UIColor colorWithRed:253/256.0 green:91/256.0 blue:73/256.0 alpha:1];timeLabel.textColor = [UIColor whiteColor];[filteredVideoView addSubview:timeLabel]; // [[AppDelegate appDelegate].cmImageSize setLabelsRounded:timeLabel cornerRadiusValue:2 borderWidthValue:0 borderColorWidthValue:[UIColor clearColor]];timeLabel.hidden = YES;_btView = [[UIView alloc]initWithFrame:CGRectMake(SCREEN_WIDTH/2 - 36.5, SCREEN_HEIGHT - 125, 73, 73)];[_btView makeCornerRadius:36.5 borderColor:nil borderWidth:0];_btView.backgroundColor = [UIColor colorWithRed:(float)0xfe/256.0 green:(float)0x65/256.0 blue:(float)0x53/256.0 alpha:1];[filteredVideoView addSubview:_btView];_photoCaptureButton = [[UIButton alloc] initWithFrame:CGRectMake(SCREEN_WIDTH/2 - 31.5, SCREEN_HEIGHT- 120, 63, 63)];_photoCaptureButton.backgroundColor = [UIColor colorWithRed:(float)0xfe/256.0 green:(float)0x65/256.0 blue:(float)0x53/256.0 alpha:1];[_photoCaptureButton addTarget:self action:@selector(startRecording:) forControlEvents:UIControlEventTouchUpInside];[_photoCaptureButton makeCornerRadius:31.5 borderColor:[UIColor blackColor] borderWidth:1.5];[filteredVideoView addSubview:_photoCaptureButton];_camerafilterChangeButton = [[UIButton alloc] init];_camerafilterChangeButton.frame = CGRectMake(SCREEN_WIDTH - 160, 25, 30.0, 30.0);UIImage* img = [UIImage imageNamed:@"beautyOFF"];[_camerafilterChangeButton setImage:img forState:UIControlStateNormal];[_camerafilterChangeButton setImage:[UIImage imageNamed:@"beautyON"] forState:UIControlStateSelected];[_camerafilterChangeButton addTarget:self action:@selector(changebeautifyFilterBtn:) forControlEvents:UIControlEventTouchUpInside];[filteredVideoView addSubview:_camerafilterChangeButton];UIButton* backBtn = [[UIButton alloc] initWithFrame:CGRectMake(SCREEN_WIDTH - 60, 25, 30, 30)];[backBtn setImage:[UIImage imageNamed:@"BackToHome"] forState:UIControlStateNormal];[backBtn addTarget:self action:@selector(clickBackToHome) forControlEvents:UIControlEventTouchUpInside];[filteredVideoView addSubview:backBtn];_cameraPositionChangeButton = [[UIButton alloc] initWithFrame:CGRectMake(SCREEN_WIDTH - 110, 25, 30, 30)];UIImage* img2 = [UIImage imageNamed:@"cammera"];[_cameraPositionChangeButton setImage:img2 forState:UIControlStateNormal];[_cameraPositionChangeButton addTarget:self action:@selector(changeCameraPositionBtn:) forControlEvents:UIControlEventTouchUpInside];[filteredVideoView addSubview:_cameraPositionChangeButton];_cameraChangeButton = [[UIButton alloc] init];_cameraChangeButton.hidden = YES;_cameraChangeButton.frame = CGRectMake(SCREEN_WIDTH - 100 , SCREEN_HEIGHT - 105.0, 52.6, 50.0);UIImage* img3 = [UIImage imageNamed:@"complete"];[_cameraChangeButton setImage:img3 forState:UIControlStateNormal];[_cameraChangeButton addTarget:self action:@selector(stopRecording:) forControlEvents:UIControlEventTouchUpInside];[filteredVideoView addSubview:_cameraChangeButton];_dleButton = [[UIButton alloc] init];_dleButton.hidden = YES;_dleButton.frame = CGRectMake( 50 , SCREEN_HEIGHT - 105.0, 50, 50.0);UIImage* img4 = [UIImage imageNamed:@"del"];[_dleButton setImage:img4 forState:UIControlStateNormal];[_dleButton addTarget:self action:@selector(clickDleBtn:) forControlEvents:UIControlEventTouchUpInside];[filteredVideoView addSubview:_dleButton];_inputLocalVieoBtn = [[UIButton alloc] init]; // _inputLocalVieoBtn.hidden = YES;_inputLocalVieoBtn.frame = CGRectMake( 50 , SCREEN_HEIGHT - 105.0, 50, 50.0);UIImage* img5 = [UIImage imageNamed:@"record_ico_input_1"];[_inputLocalVieoBtn setImage:img5 forState:UIControlStateNormal];[_inputLocalVieoBtn addTarget:self action:@selector(clickInputBtn:) forControlEvents:UIControlEventTouchUpInside];[filteredVideoView addSubview:_inputLocalVieoBtn];progressPreView = [[UIView alloc]initWithFrame:CGRectMake(0, SCREEN_HEIGHT -4 , 0, 4)];progressPreView.backgroundColor = UIColorFromRGB(0xffc738);[progressPreView makeCornerRadius:2 borderColor:nil borderWidth:0];[filteredVideoView addSubview:progressPreView];給相機設置點擊聚焦
-(void)cameraViewTapAction:(UITapGestureRecognizer *)tgr {//識別為手勢觸摸if (tgr.state == UIGestureRecognizerStateRecognized && (_focusLayer == nil || _focusLayer.hidden)) {CGPoint location = [tgr locationInView:filteredVideoView];[self setfocusImage];[self layerAnimationWithPoint:location];AVCaptureDevice *device = videoCamera.inputCamera;CGPoint pointOfInterest = [self convertToPointOfInterestFromViewCoordinates:location];NSError *error;//需要先鎖定,防止其他線程訪問if ([device lockForConfiguration:&error]) {//判斷是否支持控制對焦if ([device isFocusPointOfInterestSupported] && [device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {[device setFocusPointOfInterest:pointOfInterest];[device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];}if([device isExposurePointOfInterestSupported] && [device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]){[device setExposurePointOfInterest:pointOfInterest];[device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];}//操作完成后,記得進行unlock。[device unlockForConfiguration];NSLog(@"FOCUS OK");} else {NSLog(@"ERROR = %@", error);} } }- (void)layerAnimationWithPoint:(CGPoint)point {if (_focusLayer) {CALayer *focusLayer = _focusLayer;focusLayer.hidden = NO;[CATransaction begin];[CATransaction setDisableActions:YES];[focusLayer setPosition:point];focusLayer.transform = CATransform3DMakeScale(2.0f,2.0f,1.0f);[CATransaction commit];CABasicAnimation *animation = [ CABasicAnimation animationWithKeyPath: @"transform" ];//CATransform3DMakeScale (CGFloat sx, CGFloat sy,CGFloat sz),用來表示針對X(sx)軸,Y(sy)軸,Z(sz)軸的3D比例縮放,animation.toValue = [ NSValue valueWithCATransform3D: CATransform3DMakeScale(1.0f,1.0f,1.0f)]; // animation.delegate = self;animation.duration = 0.3f;animation.repeatCount = 1;animation.removedOnCompletion = NO;animation.fillMode = kCAFillModeForwards;[focusLayer addAnimation: animation forKey:@"animation"];// 0.5秒鐘延時[self performSelector:@selector(focusLayerNormal) withObject:self afterDelay:0.5f];} }相機切換和解除美顏
if (!sender.selected) {//開啟美顏sender.selected = YES;[videoCamera removeAllTargets];filter = [[GPUImageBeautifyFilter alloc] init];[videoCamera addTarget:filter];[filter addTarget:filteredVideoView];}else{//關閉美顏sender.selected = NO;[videoCamera removeAllTargets];filter = [[LFGPUImageEmptyFilter alloc] init];[videoCamera addTarget:filter];[filter addTarget:filteredVideoView];}開啟攝像頭
//開啟攝像頭[videoCamera startCameraCapture];開始錄制
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(720.0, 1280.0)];//GPUImageMovieWriter 保存濾鏡處理過的視頻movieWriter.isNeedBreakAudioWhiter = YES;//GPUImageMovieWriter添加的新屬性movieWriter.encodingLiveVideo = YES;movieWriter.shouldPassthroughAudio = YES;//是否使用聲音[filter addTarget:movieWriter];videoCamera.audioEncodingTarget = movieWriter;//加入聲音[movieWriter startRecording];暫停錄制,也就是實現斷點續拍,就是把視頻先保存起來,并將視頻地址保存在數組中,最后結束錄制的時候取出數組中的所有視頻
[movieWriter finishRecording];[filter removeTarget:movieWriter];[urlArray addObject:[NSURL URLWithString:[NSString stringWithFormat:@"file://%@",pathToMovie]]];_isRecoding = NO;在下一篇視頻導出中會有將斷開的視頻整合到一起,實現斷點續拍的講解。
地址:https://blog.csdn.net/weixin_42433480/article/details/90109873
總結
以上是生活随笔為你收集整理的iOS短视频:基于GPUIMage的短视频录制(GPUImage自定义相机)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SDOI2015 寻宝游戏
- 下一篇: C语言小游戏-寻宝(幸运之星)