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
// ...
}
}