iOS開發(fā) ReplayKit屏幕錄制(適用于視圖中包含視頻播放器)

最近有個需求:把屏幕內(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(@"保存視頻成功"); 
    }
}

demo地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容