Skip to content

Instantly share code, notes, and snippets.

@sohilmemon
Last active December 19, 2019 04:14
Show Gist options
  • Save sohilmemon/1ea444223e42c489697ad132137c3696 to your computer and use it in GitHub Desktop.
Save sohilmemon/1ea444223e42c489697ad132137c3696 to your computer and use it in GitHub Desktop.
Screen Recorder Using ReplayKit (Swift 4.0+) - Drag & Drop Helper
//
// 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