RPScreenRecorder not calling handler

Hi,


In my app, I have to implement a screen recording functionality. To do so, I use the RPScreenRecorder class but the startRecording() handler is never called and I am never prompted the permission to record the screen. So it does not do anything...

Here is my code:


let recorder = RPScreenRecorder.shared()

if #available(iOS 10.0, *) {
 print("startRecording") // this prints
  recorder.startRecording { (error) in
   pritn("startRecording() handler") // this never prints
    guard error == nil else {
      print(error!.localizedDescription) // no error printed
      return
    }
  }
} else {
  recorder.startRecording(withMicrophoneEnabled: true, handler: { (error) in
    guard error == nil else {
      print(error!.localizedDescription)
      return
    }
  })
}


Does anyone have any idea why it does not work?


Thanks

Replies

Same problem here. It either takes forever or at least a very long time.

I suspected and tested against

  • slow network condition
  • SpriteKit
  • iCloud and CloudKit
  • Mix mode of AV-Session
  • GameCenter
  • iTunes Store and StoreKit

Non of them changed the behaviour of recording-start when commented out. Also, there's no task in the OperationQueue. Really strange.

This behaviour started with XCode 8, Swift 3, iOS 10.

I'm seeing almost the same thing. The startRecording handler is not called when the app is run on some devices, in this case iPhone 7 and iPhone 7 Plus. When I run the app oni Phone 6 Plus, the handler is called. iOS versions are the same.

I've this confirmed that this is only an issue on iOS versions prior to 10.1. It works fine on iOS 10.1.

This isn't correct I am able to call start recording completion handler without any error in iOS 9.1.

But I have trouble with strop recording completion handler!

I've been getting this problem in my app - the completion handler for stopRecording only works some of the time. Did you ever find a solution? I find a lot of questions online from people with the same problem but I can't find any answers...

I'm having the same issue on iOS 11 GM. The handler is not being called. If I try restarting the device multiple times, one of the times it seems to work! 😐

Seeing the same behavior in 11.0 and 11.0.1. stopRecording hardly works right, which is very similar to what it was doing in iOS 9. They finally worked out the kinks in iOS 10.1, but with 11 it appears to have problems again. Please file a bug report. If they get enough, it will hopefully be addressed sooner than later.

It would be nice if Apple would reply or fix this. This seems like a widespread issue, and apps that rely on ReplayKit are completely broken when the stop handler isn't called...

Im getting the same issue.


The strangeness is that sometimes it works as expected.


Other times, I get the action popup to ask for permission for recording but stopRecording doesnt get executed when it should.

Other times, startRecording doesnt do anything.

Has anyone tried to make a custom app screen recording ?

I'm also having the issues on iOS 10. Additionaly, it's a pain to get access to the recorded video file. And the user experience is far from ideal with the forced preview of the recorded video.


Luckily, iOS 11 provides the capture API in ReplayKit, and it seems to work properly so far. The setup is a bit tricky though, and it's not well documented.

This is the code I'm using:

var assetWriter: AVAssetWriter
var url: URL
var videoInput: AVAssetWriterInput
var audioInput: AVAssetWriterInput
let screenRecorder = RPScreenRecorder.shared()

if #available(iOS 11.0, *) {
    do {
        assetWriter = try AVAssetWriter(outputURL: url, fileType: AVFileTypeQuickTimeMovie)
        // video
        let videoOutputSettings = [
            AVVideoCodecKey : AVVideoCodecType.h264,
            AVVideoWidthKey : UIScreen.main.bounds.width * UIScreen.main.scale,
            AVVideoHeightKey : UIScreen.main.bounds.height * UIScreen.main.scale
            ] as [String : Any]
        videoInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: videoOutputSettings)
        videoInput.expectsMediaDataInRealTime = true
        assetWriter.add(videoInput)
        // audio
        var acl = AudioChannelLayout()
        acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono
        let audioOutputSettings = [
            AVFormatIDKey: kAudioFormatMPEG4AAC,
            AVNumberOfChannelsKey: 1,
            AVSampleRateKey: 44100.0,
            AVEncoderBitRateKey: 64000,
            AVChannelLayoutKey: NSData(bytes: &acl, length: MemoryLayout<AudioChannelLayout>.size)
            ] as [String : Any]
        audioInput = AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: audioOutputSettings)
        audioInput.expectsMediaDataInRealTime = true
        assetWriter.add(audioInput)
    }
    catch {
        NSLog("Failed starting screen capture: \(error.localizedDescription)")
        // handle error
    }

    // start the screen capturing
    screenRecorder.isMicrophoneEnabled = true
    screenRecorder.startCapture(handler: { (sample, bufferType, error) in
        if let error = error {
            NSLog("Error capturing screen: \(error)")
        }

        // store the video/audio samples
        if bufferType == .video && self.assetWriter.status == .unknown {
            self.assetWriter.startWriting()
            self.assetWriter.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(sample))
            NSLog("asset writer started")
        }

        if self.assetWriter.status == .failed {
            NSLog("Error writing screencast to file: \(self.assetWriter.status.rawValue)")
        }

        if bufferType == .video {
            if self.videoInput.isReadyForMoreMediaData {
                self.videoInput.append(sample)
            }
        }
        else if bufferType == .audioMic && self.assetWriter.status == .writing {
            if self.audioInput.isReadyForMoreMediaData {
                self.audioInput.append(sample)
            }
        }
    }, completionHandler: { error in
        DispatchQueue.main.async {
            if let error = error {
                NSLog("Failed starting screen capture: \(error.localizedDescription)")
                // handle error
            }
            else {
                NSLog("Screen capture started successfully.")
                // handle success
            }
        }
    })
} else {
    // Fallback on earlier versions
    screenRecorder.startRecording(withMicrophoneEnabled: true) { error in
        // ...
    }
}

Sir, you are a life saver!!!
I am still getting some errors when trying to append audio data. I am developing in objective C. But strangely enough, the video is recorded nicely.

0   CoreMedia                     
0x0000000187243d90 CMSampleBufferGetSampleSize + 268
1   AVFoundation                  
0x000000018a120a00 <redacted> + 224
2   AVFoundation                  
0x000000018a120e18 <redacted> + 712
3   AVFoundation                  
0x000000018a11aab0 <redacted> + 376
4   AVFoundation                  
0x000000018a118078 <redacted> + 320
5   MYAPP                     
0x0000000101b3963c __35-[ReplayKitWrapper startRecording:]_block_invoke + 864
6   ReplayKit                     
0x000000019f3e5514 <redacted> + 304
7   libdispatch.dylib             
0x0000000183a9d088 <redacted> + 24
8   libdispatch.dylib             
0x0000000183a9d048 <redacted> + 16
9   libdispatch.dylib             
0x0000000183aa6e48 <redacted> + 528
10  libdispatch.dylib             
0x0000000183aa77d8 <redacted> + 340
11  libdispatch.dylib             
0x0000000183aa8200 <redacted> + 400
12  libdispatch.dylib             
0x0000000183ab04a0 <redacted> + 644
13  libsystem_pthread.dylib       
0x0000000183d42fd0 _pthread_wqthread + 932
14  libsystem_pthread.dylib       
0x0000000183d42c20 start_wqthread + 4
2017-11-15 19:53:15.675252+0800 MYAPP[1047:988400] [] CMSampleBufferGetSampleSize signalled err=-12735 (kCMSampleBufferError_BufferHasNoSampleSizes) (sbuf->numSampleSizeEntries == 0) at /BuildRoot/Library/Caches/com.apple.xbs/Sources/EmbeddedCoreMediaFramework/EmbeddedCoreMedia-2180.7/Sources/Core/FigSampleBuffer/FigSampleBuffer.c:3831

Does Replaykit -> startCapture record the screEn even when the app is in background?