简体   繁体   English

iOS 录屏问题

[英]Trouble with screen recording in iOS

I've got some trouble with screen recording using ReplayKit我在使用ReplayKit进行屏幕录制时遇到了一些问题

So, the strangeness begins in the startCapture 's handler closure所以,奇怪开始于startCapturehandler闭包

Every time it starts to capture and sampleType is .video , the self.videoWriter?.startSession is called, and instantaneously videoWriter.status becomes failure (3)每次开始捕获且sampleType.video时,都会调用self.videoWriter?.startSession ,并且瞬间videoWriter.status变为failure (3)

This behaviour is not throwing any exceptions until I finish recording:在我完成录制之前,此行为不会引发任何异常:

Optional("Cannot Encode")可选(“无法编码”)

Optional("Optional(Error Domain=AVFoundationErrorDomain Code=-11834 "Cannot Encode" UserInfo={AVErrorMediaSubTypeKey=(\n 778924083\n), NSLocalizedFailureReason=The encoder required for this media cannot be found., AVErrorMediaTypeKey=soun, NSLocalizedDescription=Cannot Encode })") Optional("<AVAssetWriter: 0x283ef0920, outputURL = file:///var/mobile/Containers/Data/Application/A85826BA-DCBE-428B-AB9E-84D77F234FF6/Documents/Replays/capture92949FA1-F65D-48A0-8140-207BC892C204.mp4, outputFileType = public.mpeg-4>") Optional("Optional(Error Domain=AVFoundationErrorDomain Code=-11834 "Cannot Encode" UserInfo={AVErrorMediaSubTypeKey=(\n 778924083\n), NSLocalizedFailureReason=找不到此媒体所需的编码器。, AVErrorMediaTypeKey=soun, NSLocalizedDescription=Cannot编码})") 可选("<AVAssetWriter: 0x283ef0920, outputURL = file:///var/mobile/Containers/Data/Application/A85826BA-DCBE-428B-AB9E-84D77F234FF6/Documents/Replays/capture92949FA1-F65D-48A0- 8140-207BC892C204.mp4,输出文件类型 = public.mpeg-4>")

Error Domain=PHPhotosErrorDomain Code=3302 "(null)"错误域=PHPhotosErrorDomain 代码=3302“(空)”

Here is my code:这是我的代码:

let settings = [
    AVFormatIDKey: Int(AudioFormat.kAudioFormatMPEGLayer3.rawValue),
    AVNumberOfChannelsKey: 2,
    AVSampleRateKey: 44100,
    AVEncoderBitRateKey: 128000
]
let audioInput = AVAssetWriterInput(
    mediaType: .audio,
    outputSettings: settings
)

audioInput.expectsMediaDataInRealTime = true
videoWriter.add(audioInput)

self.videoWriterInput = audioInput
self.videoWriter = videoWriter
let videoSettings: [String: Any] = [
   AVVideoCodecKey: AVVideoCodecType.h264,
   AVVideoWidthKey: passingSize.width,
   AVVideoHeightKey: passingSize.height
]

self.videoWriterInput = AVAssetWriterInput(
    mediaType: AVMediaType.video,
    outputSettings: videoSettings
)

self.appAudioWriterInput = AVAssetWriterInput(
    mediaType: .audio,
    outputSettings: settings
)
self.videoWriter.add(appAudioWriterInput!)


self.recorder.startCapture(
    handler: { (sampleBuffer, sampleType, passedError) in 
       switch sampleType {
       case .video:
           self.handleSampleBuffer(sampleBuffer: sampleBuffer)
       case .audioApp:
           self.add(sample: sampleBuffer, to: appAudioWriterInput)
       default:
           break
       }
   },
   completionHandler: { error in
       if let error = error {
          print(">>> Error!")
          errorHandler(error: error)
       }
    }
)

private func handleSampleBuffer(sampleBuffer: CMSampleBuffer) {
    if videoWriter?.status == AVAssetWriter.Status.unknown {
        serialQueue.async {
            if !self.isRecording {
                self.videoWriter?.startWriting()
                self.videoWriter?.startSession(
                    atSourceTime: .zero
                )
                self.isRecording = true
            }
        }
    } else if videoWriter?.status == AVAssetWriter.Status.writing &&
        videoWriterInput?.isReadyForMoreMediaData == true {
            serialQueue.async {
                self.videoWriterInput?.append(sampleBuffer)
            }
    }
}

I'm not familiar with iOS development and I think that I'm missing something obvious.我不熟悉 iOS 开发,我认为我遗漏了一些明显的东西。

Things I've tried:我尝试过的事情:

  1. Clean XCode caches清理 XCode 缓存
  2. Run app on both IPhone and Simulator在 iPhone 和模拟器上运行应用程序
  3. Check PHPhotoLibrary.authorizationStatus() and AVCaptureDevice.authorizationStatus before recording记录前检查PHPhotoLibrary.authorizationStatus()AVCaptureDevice.authorizationStatus
  4. Experiment with audio and video recording settings尝试音频和视频录制设置

Here is my modifications to Info.plist这是我对Info.plist的修改

<key>NSPhotoLibraryAddUsageDescription</key>
<string>The app requires access to Photos to save media to it.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>The app requires access to Photos to interact with it.</string>
<key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
<true/>

The solution was pretty simple: I just passed wrong variable to self.videoWriterInput解决方案非常简单:我只是将错误的变量传递给self.videoWriterInput

Proper initialization should be something like this:正确的初始化应该是这样的:

let screenSize: CGRect = UIScreen.main.bounds
        
let videoSettings: [String: Any] = [
    AVVideoCodecKey: AVVideoCodecType.h264,
    AVVideoWidthKey: screenSize.width,
    AVVideoHeightKey: screenSize.height,
]

let newVideoWriterInput = AVAssetWriterInput(
    mediaType: AVMediaType.video,
    outputSettings: videoSettings
)

        
newVideoWriterInput.expectsMediaDataInRealTime = true
self.videoWriter?.add(newVideoWriterInput)
self.videoWriterInput = newVideoWriterInput // THE ERROR WAS HERE
        
let settings: [String : Any] = [
    AVNumberOfChannelsKey : 2,
    AVFormatIDKey : kAudioFormatMPEG4AAC,
    AVSampleRateKey: 44100,
    AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]

let audioInput = AVAssetWriterInput(
    mediaType: .audio,
    outputSettings: settings
)

audioInput.expectsMediaDataInRealTime = true
self.videoWriter?.add(audioInput)
self.appAudioWriterInput = audioInput
      

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM