最近有個需求:把屏幕內(nèi)容錄制下來保持到本地
這里ReplayKit不做介紹,想了解請看下面的鏈接
iOS端使用replaykit錄制屏幕的技術(shù)細(xì)節(jié)
核心代碼(最后附demo)
請求同意使用攝像頭和麥克風(fēng)權(quán)限,如果用戶拒絕了,將無法進(jìn)行錄制。
不支持模擬器
{
RPScreenRecorder *_recorder;
NSURL *_movieUrl;
}
// 開始錄制
[_recorder startRecordingWithHandler:^(NSError * _Nullable error) {
NSLog(@"視頻錄制開啟產(chǎn)生問題=%@",error);
}];
// 結(jié)束錄制
[_recorder stopRecordingWithHandler:^(RPPreviewViewController * _Nullable previewViewController, NSError * _Nullable error) {
self->_movieUrl = [previewViewController valueForKey:@"movieURL"];
[self export:[_movieUrl path] complete:^(ScreenRecError error, NSString *filePath) {
[self writeVideoToAlbum:filePath];
}];
}];
//導(dǎo)出視頻 mp4
- (void)export:(NSString *)filePathUrl complete:(void(^)(ScreenRecError error,NSString* filePath))complete {
if (!filePathUrl) {
NSLog(@"filePathUrl為空");
return;
}
NSDate *date = [NSDate date];
NSString *exportPath = [NSString stringWithFormat:@"%@%d.mp4",[self getCacheDir],(int)[date timeIntervalSince1970]*1000 ];
NSURL *fileUrl = [NSURL fileURLWithPath:filePathUrl];
AVAsset *fileAsset = [AVURLAsset assetWithURL:fileUrl];
AVMutableComposition *mixComposition = [AVMutableComposition composition];
if (!([fileAsset tracksWithMediaType:AVMediaTypeVideo].count>0 && [fileAsset tracksWithMediaType:AVMediaTypeAudio].count>0)) {
complete(exportError,filePathUrl);
return;
}
for (AVAssetTrack *track in fileAsset.tracks) {
if ([track.mediaType isEqual:AVMediaTypeVideo]) {
AVMutableCompositionTrack *compositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
NSError *error;
[compositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, fileAsset.duration) ofTrack:track atTime:kCMTimeZero error:&error];
}
else if([track.mediaType isEqual:AVMediaTypeAudio]){
AVMutableCompositionTrack *compositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
NSError *error;
[compositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, fileAsset.duration) ofTrack:track atTime:kCMTimeZero error:&error];
}
}
AVAssetExportSession *assetExport = [AVAssetExportSession exportSessionWithAsset:mixComposition presetName:AVAssetExportPreset1280x720];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:exportPath]) {
NSError *error = nil;
[fileManager removeItemAtPath:exportPath error:&error];
if (error) {
NSLog(@"移除文件出錯=%@",error);
}
}
assetExport.outputFileType = AVFileTypeMPEG4;
assetExport.outputURL = [NSURL fileURLWithPath:exportPath];
assetExport.shouldOptimizeForNetworkUse = false;
[assetExport exportAsynchronouslyWithCompletionHandler:^{
if (assetExport.status == AVAssetExportSessionStatusCompleted) {
NSLog(@"Record SaveTmpVideo Success");
complete(nil,exportPath);
}
else {
complete(exportError,filePathUrl);
}
}];
}
//保存圖片到相冊
- (void)writeVideoToAlbum:(NSString *)exportFilePath{
UISaveVideoAtPathToSavedPhotosAlbum(exportFilePath, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
}
//保存視頻完成之后的回調(diào)
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
if (error) {
NSLog(@"保存視頻失敗%@", error.localizedDescription);
}
else {
NSLog(@"保存視頻成功");
}
}