Closed asam139 closed 1 year ago
True, the limitation comes from AVAssetWriter endSession. Unfortunately it does not support multiple sample-writing sessions.
I have an unfinished implementation of the pause by manual subtraction of paused intervals from the presentation time.
I'll try to create a PR with my solution. My idea is to add a computed property in the VideoOuputState to know when it is recording so the session does not need to be ended.
var isRecording: Bool {
guard case .recording = self else {
return false
}
return true
}
Then to check this isRecording property together isReadyForMoreMediaData to control if the pixelBuffer can be added
func append(pixelBuffer: CVPixelBuffer, withPresentationTime time: CMTime) throws {
guard
pixelBufferAdaptor.assetWriterInput.isReadyForMoreMediaData,
state.isRecording // HERE
else { return }
guard pixelBufferAdaptor.append(pixelBuffer, withPresentationTime: time) else {
if assetWriter.status == .failed { throw assetWriter.error ?? Error.unknown }
return
}
let seconds = time.seconds
duration += seconds - lastSeconds
lastSeconds = seconds
}
func appendVideo(sampleBuffer: CMSampleBuffer) throws {
guard
videoInput.isReadyForMoreMediaData,
state.isRecording // HERE
else { return }
guard videoInput.append(sampleBuffer) else {
if assetWriter.status == .failed { throw assetWriter.error ?? Error.unknown }
return
}
let timeStamp: CMTime
let duration: CMTime
if #available(iOS 13.0, *) {
timeStamp = sampleBuffer.presentationTimeStamp
duration = sampleBuffer.duration
} else {
timeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
duration = CMSampleBufferGetDuration(sampleBuffer)
}
self.duration += duration.seconds
lastSeconds = (timeStamp + duration).seconds
}
I did a quick test, and it seems to work fine 🥹
It's already done in https://github.com/gorastudio-ceo/SCNRecorder/blob/e4e1b7c579eff8feb4a93f2c9c31940a54cdcd07/Sources/Outputs/VideoOutput/VideoOutput.State.swift#L249
If your idea works, you can just comment out videoOutput.endSession(at: seconds) in the pause method. And, probably make some changes to the resume method of the state.
But I suppose it will lead to a gap in the video.
Basically any changes to the VideoOutput logic should be done in the VideoOutput.State. VideoOutput is state machine managed.
@v-grigoriev I created the PR with my solution. I tested a while, and it seems to work really well.
Please take a look and give me your feedback ;)
When the recording is resumed, it throws the error
The pause method of the VideoOutput finishes the session which does not allow to resume.