Last active
December 19, 2019 04:14
-
-
Save sohilmemon/1ea444223e42c489697ad132137c3696 to your computer and use it in GitHub Desktop.
Screen Recorder Using ReplayKit (Swift 4.0+) - Drag & Drop Helper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ScreenRecorder.swift | |
// Sohil R. Memon | |
// | |
// Created by Sohil R. Memon | |
// Copyright © 2018 Sohil R. Memon. All rights reserved. | |
// | |
import Foundation | |
import ReplayKit | |
import AVKit | |
class ScreenRecorder { | |
static let shared = ScreenRecorder() | |
fileprivate let screenRecorder = ScreenRecordCoordinator() | |
typealias RecordingCompletion = (URL?, Error?) -> () | |
var recordCompleted: RecordingCompletion? | |
func startRecording(withFileName fileName: String = "ScreenRecording", recordingHandler: @escaping (Error?) -> (), onCompletion: @escaping RecordingCompletion) { | |
screenRecorder.startRecording(withFileName: fileName) { (error) in | |
recordingHandler(error) | |
self.recordCompleted = onCompletion | |
} | |
} | |
func stopRecording() { | |
screenRecorder.stopRecording { (recordingURL, error) in | |
if let error = error { | |
self.recordCompleted?(nil, error) | |
} else { | |
self.recordCompleted?(recordingURL, nil) | |
} | |
} | |
} | |
} | |
fileprivate class ScreenRecordCoordinator { | |
fileprivate var assetWriter:AVAssetWriter! | |
fileprivate var videoInput:AVAssetWriterInput! | |
fileprivate var recordingURL: URL? | |
//MARK: Screen Recording | |
func startRecording(withFileName fileName: String, recordingHandler:@escaping (Error?) -> Void) { | |
recordingURL = URL(fileURLWithPath: ReplayFileUtil.shared.createFile(ofName: fileName)) | |
assetWriter = try! AVAssetWriter(outputURL: recordingURL!, fileType: AVFileType.mp4) | |
if #available(iOS 11.0, *) { | |
let videoOutputSettings: Dictionary<String, Any> = [ | |
AVVideoCodecKey : AVVideoCodecType.h264, | |
AVVideoWidthKey : UIScreen.main.bounds.size.width, | |
AVVideoHeightKey : UIScreen.main.bounds.size.height | |
] | |
videoInput = AVAssetWriterInput (mediaType: AVMediaType.video, outputSettings: videoOutputSettings) | |
videoInput.expectsMediaDataInRealTime = true | |
assetWriter.add(videoInput) | |
RPScreenRecorder.shared().startCapture(handler: { (sample, bufferType, error) in | |
recordingHandler(error) | |
if CMSampleBufferDataIsReady(sample) { | |
if self.assetWriter.status == AVAssetWriter.Status.unknown { | |
self.assetWriter.startWriting() | |
self.assetWriter.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(sample)) | |
} | |
if self.assetWriter.status == AVAssetWriter.Status.failed { | |
print("Error occured, status = \(self.assetWriter.status.rawValue), \(self.assetWriter.error!.localizedDescription) \(String(describing: self.assetWriter.error))") | |
return | |
} | |
if (bufferType == .video) { | |
if self.videoInput.isReadyForMoreMediaData { | |
self.videoInput.append(sample) | |
} | |
} | |
} | |
}) { (error) in | |
debugPrint("Recording Error \(error?.localizedDescription ?? "No Error")") | |
recordingHandler(error) | |
} | |
} else { | |
// Fallback on earlier versions | |
}; | |
} | |
func stopRecording(handler: @escaping (URL?, Error?) -> ()) { | |
if #available(iOS 11.0, *) { | |
RPScreenRecorder.shared().stopCapture {(error) in | |
if let error = error { | |
handler(nil, error) | |
} else { | |
self.assetWriter.finishWriting { | |
handler(self.recordingURL, nil) | |
} | |
} | |
} | |
} else { | |
// Fallback on earlier versions | |
} | |
} | |
} | |
fileprivate class ReplayFileUtil { | |
//Shared | |
static let shared = ReplayFileUtil() | |
let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! | |
private init() { | |
createReplaysFolder() | |
} | |
func createReplaysFolder() { | |
let replayDirectoryPath = documentDirectoryPath.appending("/Replays") | |
let fileManager = FileManager.default | |
if !fileManager.fileExists(atPath: replayDirectoryPath) { | |
do { | |
try fileManager.createDirectory(atPath: replayDirectoryPath, | |
withIntermediateDirectories: false, | |
attributes: nil) | |
} catch { | |
print("Error creating Replays folder in documents dir: \(error)") | |
} | |
} | |
} | |
func createFile(ofName name: String) -> String { | |
let filePath = "\(documentDirectoryPath)/Replays/\(name)_\(Int(Date.timeIntervalSinceReferenceDate)).mp4" | |
return filePath | |
} | |
var allReplays: [URL] { | |
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first | |
let replayPath = documentsDirectory?.appendingPathComponent("/Replays") | |
let directoryContents = try! FileManager.default.contentsOfDirectory(at: replayPath!, includingPropertiesForKeys: nil, options: []) | |
return directoryContents | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment