【iOS】iOS系統(tǒng)錄制屏幕框架 ReplayKit 使用教程

ReplayKit

Record or stream video from the screen, and audio from the app and microphone.

Overview

Using the ReplayKit framework, users can record video from the screen, and audio from the app and microphone. They can then share their recordings with other users through email, messages, and social media. You can build app extensions for live broadcasting your content to sharing services. ReplayKit is incompatible with AVPlayer content.

概述

使用 ReplayKit 框架,用戶可以從屏幕上錄制視頻,并從應(yīng)用程序內(nèi)和麥克風(fēng)錄制音頻干跛。 然后他們也可以通過電子郵件、消息和社交媒體與其他用戶共享他們的錄音烂叔。 您還可以構(gòu)建應(yīng)用擴展程序,共享服務(wù)嵌牺。 注意:ReplayKit 與 AVPlayer 內(nèi)容不兼容蒙保。

ReplayKit 優(yōu)點:

1、內(nèi)存奴曙、CPU占用極小可以忽略不計
2别凹、錄制清晰度和流暢度非常高
3、不需要導(dǎo)入一些SDK包洽糟,對APP的負(fù)擔(dān)幾乎為0
4番川、錄制代碼實現(xiàn)簡單

ReplayKit 缺點:

1、不支持AVPlayer播放的視頻錄制
2脊框、不支持模擬器
3、無法自定義RPPreviewViewController預(yù)覽視圖
4践啄、無法修改錄制視頻保存路徑
5浇雹、錄制的原始視頻清晰度非常高,導(dǎo)致整個視頻文件非常大
6屿讽、部分機型部分系統(tǒng)錄制會有失敗的情況昭灵,穩(wěn)定性有待商榷
7、只支持 iOS9.0+ 版本

錄屏過程:

1伐谈、檢測是否有相冊權(quán)限(后期不需要本地操作錄屏可省略)
2烂完、檢測是否支持錄屏(iOS9.0+)
3、開始錄屏
4诵棵、結(jié)束錄屏
5抠蚣、將錄屏保存到相冊
6、拿出相冊里當(dāng)前錄屏進行壓縮處理(壓縮規(guī)格可修改)
7履澳、壓縮后的錄屏保存至沙盒后可進行任意操作

部分代碼:

1嘶窄、獲取相冊權(quán)限
- (void)startRecord {
    
    [MXReplayManager mx_getPHAuthorizationStatusBlock:^(BOOL success) {
        if (success) {
            [self mx_recorderAvailable];
        }
    }];
}
2怀跛、錄屏是否可用
// 錄屏是否可用
- (void)mx_recorderAvailable {
    
    if ([_recorder isAvailable]) {
        [self mx_startCapture];
    } else {
        NSLog(@"請允許App錄制屏幕且使用麥克風(fēng)(選擇第一項),否則無法進行錄屏");
    }
}
3柄冲、開始錄屏
// 開始錄屏(分系統(tǒng))
- (void)mx_startCapture {
    
    //是否錄麥克風(fēng)的聲音(如果只想要App內(nèi)的聲音吻谋,設(shè)置為NO即可)
    _recorder.microphoneEnabled = NO;

    if ([_recorder isRecording]) {
        NSLog(@"正在錄制...");
    } else {
        if (@available(iOS 11.0, *)) {
            [_recorder startCaptureWithHandler:^(CMSampleBufferRef _Nonnull sampleBuffer, RPSampleBufferType bufferType, NSError * _Nullable error) {
                //CMSampleBufferRef 視頻+音頻原始幀數(shù)據(jù) (幀數(shù)據(jù)處理可參考部分開源直播SDk)
                switch (bufferType) {
                    case RPSampleBufferTypeVideo:     //視頻
                        break;
                     case RPSampleBufferTypeAudioApp: //App內(nèi)音頻
                        break;
                    case RPSampleBufferTypeAudioMic:  //麥克風(fēng)音頻
                        break;
                    default:
                        break;
                }
            } completionHandler:^(NSError * _Nullable error) {
                
            }];
        } else if (@available(iOS 10.0, *)) {
            [_recorder startRecordingWithHandler:^(NSError * _Nullable error) {
                if (!error) {
                    NSLog(@"啟動錄屏成功...");
                }
            }];
        } else if (@available(iOS 9.0, *)) {
            [_recorder startRecordingWithMicrophoneEnabled:NO handler:^(NSError * _Nullable error) {
                if (!error) {
                    NSLog(@"啟動錄屏成功...");
                }
            }];
        }
    }
}
4、結(jié)束錄屏
//停止錄屏
- (void)stopRecord {
 
    if (@available(iOS 11.0, *)) {
        [_recorder stopCaptureWithHandler:^(NSError * _Nullable error) {
            
        }];
    } else {
        [_recorder stopRecordingWithHandler:^(RPPreviewViewController * _Nullable previewViewController, NSError * _Nullable error) {
            NSURL * videoURL = [previewViewController valueForKey:@"movieURL"];
            if (!videoURL) {
                NSLog(@"錄屏失敗...");
            } else {
                //是否需要展示預(yù)覽界面給用戶现横,自行決定
                [self mx_saveVideoToPhoto:videoURL];
            }
        }];
    }
}
5漓拾、保存視頻至相冊
//保存視頻至相冊
- (void)mx_saveVideoToPhoto:(NSURL *)videoURL {
    
    NSString * videoPath = [videoURL path];
    BOOL compatible = UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(videoPath);
    if (compatible) {
        UISaveVideoAtPathToSavedPhotosAlbum(videoPath, self, @selector(savedPhotoImage:didFinishSavingWithError:contextInfo:), nil);
    }
}

6、保存視頻完成之后的回調(diào)
//保存視頻完成之后的回調(diào)
- (void)savedPhotoImage:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    
    if (error) {
        NSLog(@"保存視頻失敗 == %@", error.description);
    } else {
        //取出這個視頻并按創(chuàng)建日期排序
        PHFetchOptions * options = [[PHFetchOptions alloc] init];
        options.sortDescriptors  = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
        PHFetchResult * assetsFetchResults = [PHAsset fetchAssetsWithOptions:options];
        PHAsset * phasset = [assetsFetchResults lastObject];
        if (phasset) {
            //視頻文件
            if (phasset.mediaType == PHAssetMediaTypeVideo) {
                PHImageManager * manager = [PHImageManager defaultManager];
                [manager requestAVAssetForVideo:phasset options:nil resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
                    AVURLAsset * urlAsset = (AVURLAsset *)asset;
                    [self mx_saveVideoToDocument:urlAsset.URL];
                }];
            } else {
                NSLog(@"未成功保存視頻...");
            }
        } else {
            NSLog(@"未成功保存視頻...");
        }
    }
}
7戒祠、保存視頻至沙盒
//保存視頻至沙盒
- (void)mx_saveVideoToDocument:(NSURL *)videoURL {
    
    NSString * outPath  = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[@"mx_test_replay" stringByAppendingString:@".mp4"]];
    [MXReplayManager mx_compressQuailtyWithInputURL:videoURL outputURL:[NSURL fileURLWithPath:outPath] blockHandler:^(AVAssetExportSession * _Nonnull session) {
        if (session.status == AVAssetExportSessionStatusCompleted) {
            NSLog(@"視頻已處理好可以對其進行操作");
            //處理完的視頻是否需要刪除骇两?自行決定
        } else {
            NSLog(@"視頻壓縮出錯...");
        }
    }];
}
8、壓縮視頻
+ (void)mx_compressQuailtyWithInputURL:(NSURL *)inputURL
                             outputURL:(NSURL *)outputURL
                          blockHandler:(void (^)(AVAssetExportSession * _Nonnull))handler {
    
    AVURLAsset * asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
    AVAssetExportSession * session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
    session.outputURL = outputURL;
    session.outputFileType = AVFileTypeMPEG4;
    [session exportAsynchronouslyWithCompletionHandler:^(void) {
        if (handler) {
            handler(session);
        }
    }];
}

GitHub地址


原創(chuàng)文章得哆,轉(zhuǎn)載請注明出處脯颜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市贩据,隨后出現(xiàn)的幾起案子栋操,更是在濱河造成了極大的恐慌,老刑警劉巖饱亮,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矾芙,死亡現(xiàn)場離奇詭異,居然都是意外死亡近上,警方通過查閱死者的電腦和手機剔宪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壹无,“玉大人葱绒,你說我怎么就攤上這事《范В” “怎么了地淀?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長岖是。 經(jīng)常有香客問我帮毁,道長,這世上最難降的妖魔是什么豺撑? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任烈疚,我火速辦了婚禮,結(jié)果婚禮上聪轿,老公的妹妹穿的比我還像新娘爷肝。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布阶剑。 她就那樣靜靜地躺著跃巡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牧愁。 梳的紋絲不亂的頭發(fā)上素邪,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機與錄音猪半,去河邊找鬼兔朦。 笑死,一個胖子當(dāng)著我的面吹牛磨确,可吹牛的內(nèi)容都是我干的沽甥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼乏奥,長吁一口氣:“原來是場噩夢啊……” “哼摆舟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起邓了,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤恨诱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后骗炉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體照宝,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年句葵,在試婚紗的時候發(fā)現(xiàn)自己被綠了厕鹃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡乍丈,死狀恐怖剂碴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情轻专,我是刑警寧澤汗茄,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站铭若,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏递览。R本人自食惡果不足惜叼屠,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绞铃。 院中可真熱鬧镜雨,春花似錦、人聲如沸儿捧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至颓影,卻和暖如春各淀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诡挂。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工碎浇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人璃俗。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓奴璃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親城豁。 傳聞我的和親對象是個殘疾皇子苟穆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355