diff --git a/JLScreenRecordDemo/JLScreenRecordDemo.xcodeproj/project.pbxproj b/JLScreenRecordDemo/JLScreenRecordDemo.xcodeproj/project.pbxproj index 44a3eff..45bada6 100644 --- a/JLScreenRecordDemo/JLScreenRecordDemo.xcodeproj/project.pbxproj +++ b/JLScreenRecordDemo/JLScreenRecordDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 81136DAF20247FAB001B203C /* JLRecorderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 81136DAE20247FAB001B203C /* JLRecorderManager.m */; }; 817417982024098F002423D3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 817417972024098F002423D3 /* AppDelegate.m */; }; 8174179B2024098F002423D3 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8174179A2024098F002423D3 /* ViewController.m */; }; 8174179E2024098F002423D3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8174179C2024098F002423D3 /* Main.storyboard */; }; @@ -27,6 +28,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 81136DAD20247FAB001B203C /* JLRecorderManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JLRecorderManager.h; sourceTree = ""; }; + 81136DAE20247FAB001B203C /* JLRecorderManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JLRecorderManager.m; sourceTree = ""; }; 817417932024098F002423D3 /* JLScreenRecordDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JLScreenRecordDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 817417962024098F002423D3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 817417972024098F002423D3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -124,6 +127,8 @@ 817417AD20240F90002423D3 /* JLCaptureUtilities.m */, 817417AF20240F90002423D3 /* JLScreenRecorder.h */, 817417AE20240F90002423D3 /* JLScreenRecorder.m */, + 81136DAD20247FAB001B203C /* JLRecorderManager.h */, + 81136DAE20247FAB001B203C /* JLRecorderManager.m */, ); path = JLScreenRecordKit; sourceTree = ""; @@ -203,6 +208,7 @@ buildActionMask = 2147483647; files = ( 817417BF2024128D002423D3 /* HiARCapture.m in Sources */, + 81136DAF20247FAB001B203C /* JLRecorderManager.m in Sources */, 817417D520244A99002423D3 /* AGLKVertexAttribArrayBuffer.m in Sources */, 817417D320244A99002423D3 /* glViewController.m in Sources */, 8174179B2024098F002423D3 /* ViewController.m in Sources */, diff --git a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLAudioRecord.h b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLAudioRecord.h index c03e2e7..344e82a 100755 --- a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLAudioRecord.h +++ b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLAudioRecord.h @@ -6,7 +6,7 @@ #import @protocol JLAudioRecordDelegate --(void)wavComplete; +//-(void)wavComplete; @end diff --git a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLAudioRecord.m b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLAudioRecord.m index 16ab787..ddc99c9 100755 --- a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLAudioRecord.m +++ b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLAudioRecord.m @@ -6,7 +6,7 @@ static NSString * const JLAudio = @"JLAudio"; @interface JLAudioRecord() -@property (retain, nonatomic) AVAudioRecorder * audioRecorder; +@property (strong, nonatomic) AVAudioRecorder * audioRecorder; @end @implementation JLAudioRecord @@ -56,17 +56,6 @@ - (void)clearAudioFile{ } } -#pragma mark - 开始或结束 --(void)toRecordOrPause:(NSNotification*)sender -{ - NSString* str=(NSString*)[sender object]; - if ([str intValue]) { - [self startRecord]; - } - else{ - [self pauseRecord]; - } -} #pragma mark - 录音开始 -(void)startRecord{ @@ -84,13 +73,14 @@ -(void)pauseRecord{ #pragma mark - 录音结束 - (void)endRecord{ + if (self.audioRecorder.isRecording||(!self.audioRecorder.isRecording&&_nowPause)) { [self.audioRecorder stop]; self.audioRecorder = nil; - if ([self.delegate respondsToSelector:@selector(wavComplete)]) { - [self.delegate wavComplete]; - } +// if ([self.delegate respondsToSelector:@selector(wavComplete)]) { +// [self.delegate wavComplete]; +// } } diff --git a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLRecorderManager.h b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLRecorderManager.h new file mode 100644 index 0000000..c5c08cc --- /dev/null +++ b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLRecorderManager.h @@ -0,0 +1,29 @@ +// +// JLRecorderManager.h +// JLScreenRecordDemo +// +// Created by 孙金亮 on 2018/2/2. +// Copyright © 2018年 hiscene. All rights reserved. +// + +#import + + +typedef void (^VideoCompletionBlock)(NSString * path); + +@interface JLRecorderManager : NSObject +@property (nonatomic, readonly) BOOL isRecording; + +@property(nonatomic,assign)NSInteger maxRecordTime;//最大录屏时间 defalut 60s +@property(nonatomic,assign)NSInteger minRecordTime;//最大录屏时间 defalut 60s +@property (strong, nonatomic) NSURL *videoURL;//视频文件目标目标地址,不设置也可以 +@property(nonatomic,assign)int top_edge; //录屏范围上边距 +@property(nonatomic,assign)int buttom_edge;//录屏范围下边距 + ++ (instancetype)sharedInstance; +- (BOOL)startRecording; +- (void)stopRecordingWithCompletion:(VideoCompletionBlock)completionBlock; +- (void)clear; //单例类必须主动清理 +- (void)clearFile;//清理录制缓存文件; + +@end diff --git a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLRecorderManager.m b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLRecorderManager.m new file mode 100644 index 0000000..61a7155 --- /dev/null +++ b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLRecorderManager.m @@ -0,0 +1,109 @@ +// +// JLRecorderManager.m +// JLScreenRecordDemo +// +// Created by 孙金亮 on 2018/2/2. +// Copyright © 2018年 hiscene. All rights reserved. +// + +#import "JLRecorderManager.h" +#import "JLAudioRecord.h" +#import "JLScreenRecorder.h" +#import "JLCaptureUtilities.h" + + +@interface JLRecorderManager() + +@property(nonatomic,strong) JLAudioRecord * audioRecord; +@property(nonatomic,copy) VideoCompletionBlock completionBlock; +@property(nonatomic,strong)JLScreenRecorder * screenRecord; + +@end + +@implementation JLRecorderManager + + + +#pragma mark - initializers +static dispatch_once_t once; +static JLRecorderManager * sharedInstance; ++ (instancetype)sharedInstance { + + + dispatch_once(&once, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} +- (void)clear{ + once = 0; + sharedInstance = nil; + +} + +- (void)dealloc{ + + [self clearFile]; + +} +- (instancetype)init +{ + self = [super init]; + if (self) { + + self.screenRecord = [[JLScreenRecorder alloc]init]; + self.audioRecord = [[JLAudioRecord alloc]init]; + [self.audioRecord prepareRecord]; + } + + return self; +} +- (void)clearFile{ + [self.screenRecord clearFile]; + [self.audioRecord clearAudioFile]; + +} +- (BOOL)startRecording +{ + + [self.audioRecord beginRecord]; + + return [self.screenRecord startRecording]; + + +} + +- (void)stopRecordingWithCompletion:(VideoCompletionBlock)completionBlock; +{ + self.completionBlock = completionBlock; + [self.audioRecord endRecord]; + __weak typeof(self) weakSelf = self; + [self.screenRecord stopRecordingWithCompletion:^(NSURL *vedioUrl) { + + [JLCaptureUtilities mergeVideo:vedioUrl andAudio:weakSelf.audioRecord.recordFilePath andTarget:weakSelf andAction:@selector(mergedidFinish:WithError:)]; + [weakSelf.screenRecord clearFile]; + + }]; + +} + +- (void)mergedidFinish:(NSString *)videoPath WithError:(NSError *)error +{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.completionBlock) self.completionBlock(videoPath); + }); +} + +- (void)setTop_edge:(int)top_edge{ + _top_edge = top_edge; + self.screenRecord.top_edge = top_edge; + + +} +-(void)setButtom_edge:(int)buttom_edge{ + _buttom_edge = buttom_edge; + self.screenRecord.buttom_edge = buttom_edge; + + +} +@end diff --git a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLScreenRecorder.h b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLScreenRecorder.h index 40bf2d6..c8e73d6 100755 --- a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLScreenRecorder.h +++ b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLScreenRecorder.h @@ -14,13 +14,13 @@ typedef void (^VideoCompletionBlock)(NSString * path); @property(nonatomic,assign)NSInteger maxRecordTime;//最大录屏时间 defalut 60s @property(nonatomic,assign)NSInteger minRecordTime;//最大录屏时间 defalut 60s @property (strong, nonatomic) NSURL *videoURL;//视频文件目标目标地址,不设置也可以 -@property(nonatomic,assign)CGFloat top_edge; -@property(nonatomic,assign)CGFloat buttom_edge; +@property(nonatomic,assign)CGFloat top_edge; //录屏范围上边距 +@property(nonatomic,assign)CGFloat buttom_edge;//录屏范围下边距 + -+ (instancetype)sharedInstance; - (BOOL)startRecording; -- (void)stopRecordingWithCompletion:(VideoCompletionBlock)completionBlock; +- (void)stopRecordingWithCompletion:(void (^)(NSURL * vedioUrl))completionBlock; + (void)clear; //单例类必须主动清理 - (void)clearFile;//清理录制缓存文件; diff --git a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLScreenRecorder.m b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLScreenRecorder.m index 8daee40..2fa1a75 100755 --- a/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLScreenRecorder.m +++ b/JLScreenRecordDemo/JLScreenRecordDemo/JLScreenRecordKit/JLScreenRecorder.m @@ -3,12 +3,11 @@ #import "JLScreenRecorder.h" #import #import -#import -#import "JLAudioRecord.h" + #import "JLCaptureUtilities.h" -@interface JLScreenRecorder() +@interface JLScreenRecorder() @property (strong, nonatomic) AVAssetWriter *videoWriter; @property (strong, nonatomic) AVAssetWriterInput *videoWriterInput; @@ -17,7 +16,7 @@ @interface JLScreenRecorder() @property (strong, nonatomic) NSDictionary *outputBufferPoolAuxAttributes; @property (nonatomic) CFTimeInterval firstTimeStamp; @property (nonatomic) BOOL isRecording; -@property(nonatomic,strong) JLAudioRecord * audioRecord; + @property(nonatomic,copy) VideoCompletionBlock completionBlock; @property(nonatomic,strong)UIImage * image_water; @@ -38,22 +37,7 @@ @implementation JLScreenRecorder CVPixelBufferPoolRef _outputBufferPool; } -#pragma mark - initializers -static dispatch_once_t once; -static JLScreenRecorder *sharedInstance; -+ (instancetype)sharedInstance { - - - dispatch_once(&once, ^{ - sharedInstance = [[self alloc] init]; - }); - return sharedInstance; -} -+ (void)clear{ - once = 0; - sharedInstance = nil; - -} + - (void)clearFile{ @@ -90,7 +74,7 @@ - (instancetype)init self.maxRecordTime = 60; [self setUpWriter]; - [self.audioRecord prepareRecord]; + } return self; } @@ -110,38 +94,49 @@ - (BOOL)startRecording _isRecording = (_videoWriter.status == AVAssetWriterStatusWriting); _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(writeVideoFrame)]; - if ([[UIDevice currentDevice].systemVersion doubleValue] >= 10) { + if (@available(iOS 10.0, *)) { [_displayLink setPreferredFramesPerSecond:30]; - }else{ + } else { _displayLink.frameInterval = 2; - } - + [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - [self.audioRecord beginRecord]; + } return _isRecording; } -- (void)stopRecordingWithCompletion:(VideoCompletionBlock)completionBlock; +- (void)stopRecordingWithCompletion:(void (^)(NSURL * vedioUrl))completionBlock; { if (_isRecording) { _isRecording = NO; [_displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - [self.audioRecord endRecord]; - [self completeRecordingSession:completionBlock]; - } -} - -- (JLAudioRecord *)audioRecord{ - - if (_audioRecord == nil) { - _audioRecord = [[JLAudioRecord alloc]init]; - _audioRecord.delegate=self; + [_displayLink invalidate]; + _displayLink = nil; + dispatch_async(_render_queue, ^{ + dispatch_sync(_append_pixelBuffer_queue, ^{ + + [_videoWriterInput markAsFinished]; + [_videoWriter finishWritingWithCompletionHandler:^{ + + + + dispatch_async(dispatch_get_main_queue(), ^{ + + + if (completionBlock) { + completionBlock(_videoWriter.outputURL); + } + + [self cleanup]; + + }); + + }]; + }); + }); } - - return _audioRecord; } #pragma mark - private @@ -226,37 +221,8 @@ - (void)removeTempFilePath:(NSString*)filePath } } -- (void)completeRecordingSession:(VideoCompletionBlock)completionBlock; -{ - - self.completionBlock = completionBlock; - dispatch_async(_render_queue, ^{ - dispatch_sync(_append_pixelBuffer_queue, ^{ - - [_videoWriterInput markAsFinished]; - [_videoWriter finishWritingWithCompletionHandler:^{ - - - - dispatch_async(dispatch_get_main_queue(), ^{ - - [JLCaptureUtilities mergeVideo:_videoWriter.outputURL andAudio:self.audioRecord.recordFilePath andTarget:self andAction:@selector(mergedidFinish:WithError:)]; - - }); - }]; - }); - }); -} -- (void)mergedidFinish:(NSString *)videoPath WithError:(NSError *)error -{ - - - [self cleanup]; - dispatch_async(dispatch_get_main_queue(), ^{ - if (self.completionBlock) self.completionBlock(videoPath); - }); -} + - (void)cleanup @@ -336,4 +302,6 @@ - (CGContextRef)createPixelBufferAndBitmapContext:(CVPixelBufferRef *)pixelBuffe return bitmapContext; } + + @end diff --git a/JLScreenRecordDemo/JLScreenRecordDemo/ViewController.m b/JLScreenRecordDemo/JLScreenRecordDemo/ViewController.m index 7549563..e1bfd90 100644 --- a/JLScreenRecordDemo/JLScreenRecordDemo/ViewController.m +++ b/JLScreenRecordDemo/JLScreenRecordDemo/ViewController.m @@ -7,7 +7,7 @@ // #import "ViewController.h" -#import "JLScreenRecorder.h" +#import "JLRecorderManager.h" #import "OpenGLView.h" #import "HiARCapture.h" #import @@ -38,7 +38,7 @@ - (void)viewDidLoad { } - (void)initView{ - [JLScreenRecorder sharedInstance]; + [JLRecorderManager sharedInstance]; [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; @@ -131,7 +131,7 @@ - (void)recordButtonLongPress:(UILongPressGestureRecognizer *)ges{ dispatch_async(dispatch_get_main_queue(), ^{ - [[JLScreenRecorder sharedInstance]startRecording]; + [[JLRecorderManager sharedInstance]startRecording]; }); @@ -140,7 +140,7 @@ - (void)recordButtonLongPress:(UILongPressGestureRecognizer *)ges{ }else if (ges.state == UIGestureRecognizerStateEnded){ - [[JLScreenRecorder sharedInstance]stopRecordingWithCompletion:^(NSString *path) { + [[JLRecorderManager sharedInstance]stopRecordingWithCompletion:^(NSString *path) { MPMoviePlayerController * playerVC = [[MPMoviePlayerController alloc]initWithContentURL:[NSURL fileURLWithPath:path]]; @@ -166,7 +166,7 @@ - (void)recordButtonLongPress:(UILongPressGestureRecognizer *)ges{ - (void)recordScreenfail{ - [[JLScreenRecorder sharedInstance]stopRecordingWithCompletion:^(NSString *path) { + [[JLRecorderManager sharedInstance]stopRecordingWithCompletion:^(NSString *path) { }]; }