Testiphone
Testiphone

Reputation: 211

How to record IOS screen programmatically

Is there any way to record IOS screen programmatically. Means whatever activity you are doing like clicking buttons, Scrolling tableviews.

Even if a video is playing that will be captured again along with some other activity?

Have tried these

  1. https://www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos
  2. https://github.com/alskipp/ASScreenRecorder

but with these libraries won't provide quality video. I need quality video.

The issue is that with video playing in the background when i capture screen it does not show smooth video. It shows like one frame of video and then after 3-4 secs 2nd frame and so on. Also quality of video is not good its blurred

Upvotes: 18

Views: 31894

Answers (3)

Swifty Codes
Swifty Codes

Reputation: 1102

You can use the screen-cap-view library written in Objective-C to record a view. To use it in Swift:

  • Drag and drop the .m and .h files in your Xcode project.
  • Make a header file and import the file: #import "IAScreenCaptureView.h".
  • Then give a View this class from the PropertyInspector and make an IBOutlet for that view: @IBOutlet weak var contentView: IAScreenCaptureView!
  • Start and stop the recording of the view:
    • contentView.startRecording()
    • contentView.stopRecording()

Upvotes: 0

biomiker
biomiker

Reputation: 3306

As of iOS 9, it looks like ReplayKit is available to greatly simplify this.

https://developer.apple.com/reference/replaykit

https://code.tutsplus.com/tutorials/ios-9-an-introduction-to-replaykit--cms-25458

Update: This may be less relevant now that iOS 11 has a built-in screen recorder, but the following Swift 3 code worked for me:

import ReplayKit

@IBAction func toggleRecording(_ sender: UIBarButtonItem) {
    let r = RPScreenRecorder.shared()

    guard r.isAvailable else {
        print("ReplayKit unavailable")
        return
    }
    
    if r.isRecording {
        self.stopRecording(sender, r)
        
    }
    else {
        self.startRecording(sender, r)
    }
}

func startRecording(_ sender: UIBarButtonItem, _ r: RPScreenRecorder) {
    
    r.startRecording(handler: { (error: Error?) -> Void in
        if error == nil { // Recording has started
            sender.title = "Stop"
        } else {
            // Handle error
            print(error?.localizedDescription ?? "Unknown error")
        }
    })
}

func stopRecording(_ sender: UIBarButtonItem, _ r: RPScreenRecorder) {
    r.stopRecording( handler: { previewViewController, error in

        sender.title = "Record"
        
        if let pvc = previewViewController {

            if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad {
                pvc.modalPresentationStyle = UIModalPresentationStyle.popover
                pvc.popoverPresentationController?.sourceRect = CGRect.zero
                pvc.popoverPresentationController?.sourceView = self.view
            }

            pvc.previewControllerDelegate = self
            self.present(pvc, animated: true, completion: nil)
        }
        else if let error = error {
            print(error.localizedDescription)
        }
        
    })
}

// MARK: RPPreviewViewControllerDelegate
func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
    previewController.dismiss(animated: true, completion: nil)
}

Upvotes: 7

Nattudurai
Nattudurai

Reputation: 856

Check out ScreenCaptureView, this has video-recording support built-in (see link).

What this does is it saves the contents of a UIView to a UIImage. The author suggests you can save a video of the app in use by passing the frames through AVCaptureSession.

I believe it hasn't been tested with an OpenGL subview, but assuming that it works you might be able to modify it slightly to include audio and then you'd be set.

AVCaptureSession Sample

AVCaptureSession Reference

import UIKit
import AVFoundation
class ViewController: UIViewController {
    let captureSession = AVCaptureSession()
    let stillImageOutput = AVCaptureStillImageOutput()
    var error: NSError?
    override func viewDidLoad() {
        super.viewDidLoad()
        let devices = AVCaptureDevice.devices().filter{ $0.hasMediaType(AVMediaTypeVideo) && $0.position == AVCaptureDevicePosition.Back }
        if let captureDevice = devices.first as? AVCaptureDevice  {

            captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &error))
            captureSession.sessionPreset = AVCaptureSessionPresetPhoto
            captureSession.startRunning()
            stillImageOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]
            if captureSession.canAddOutput(stillImageOutput) {
                captureSession.addOutput(stillImageOutput)
            }
            if let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) {
                previewLayer.bounds = view.bounds
                previewLayer.position = CGPointMake(view.bounds.midX, view.bounds.midY)
                previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
                let cameraPreview = UIView(frame: CGRectMake(0.0, 0.0, view.bounds.size.width, view.bounds.size.height))
                cameraPreview.layer.addSublayer(previewLayer)
                cameraPreview.addGestureRecognizer(UITapGestureRecognizer(target: self, action:"saveToCamera:"))
                view.addSubview(cameraPreview)
            }
        }
    }
    func saveToCamera(sender: UITapGestureRecognizer) {
        if let videoConnection = stillImageOutput.connectionWithMediaType(AVMediaTypeVideo) {
            stillImageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection) {
                (imageDataSampleBuffer, error) -> Void in
                let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
                 UIImageWriteToSavedPhotosAlbum(UIImage(data: imageData), nil, nil, nil)
            }
        }
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

Upvotes: 2

Related Questions