user331244
user331244

Reputation: 611

AVAssetWriter::append() returns false with no extra info (How to do segmenting of captured input to video-chunks with AVFoundation?)

I am building a feature where I record video and audio using AVFoundation. I will record for hours, but I want to upload chunks to our backend so that we can build a live HLS-playlist (after som processing of the segments).

First of all, is there a sample somewhere doing this? I haven't found any reference implementations so to say...

Here is my take on it:

Problems:

  1. Sometimes, the when calling AVAssetWriter::append(), it just fails and returns false
  2. According to the documentation, one shall check AVAssetWriter.status.
    In this situation it is set to AVAssetWriterStatusFailed and more information should be available in AVAssetWriter.error
  3. AVAssetWriter.error is set to Optional(Error Domain=AVFoundationErrorDomain Code=-11800 \"The operation could not be completed\" UserInfo={NSUnderlyingError=0x14e73dc10 {Error Domain=NSOSStatusErrorDomain Code=-16364 \"(null)\"},NSLocalizedFailureReason=An unknown error occurred (-16364), NSLocalizedDescription=The operation could not be completed})
  4. AVFoundationErrorDomain.code 11800 means AVErrorUnknown

Anyone that has had the same problems or knows how to find more info?

Finally, when I switch between writers, there is a period from when I call AVAssetWriter.startWriting() (I do this when I create my idle writer, before it its time to switch to a new segment) to when I have called AVAssetWriter.startSession(atSourceTime: startTime). During this time I need to hold on to sampleBuffers (typically audio). I just make a copy

 var copiedBuffer: CMSampleBuffer?
 CMSampleBufferCreateCopy(nil, sampleBuffer, &copiedBuffer)
 guard copiedBuffer != nil else {
    throw VideoWriterError.failedToCopyBuffer
 }
 pendingSampleBuffers.append((isVideo, copiedBuffer))

After AVAssetWriter.StartSession(), I write them to the new writer:

    while !pendingSampleBuffers.isEmpty {
        let (isVideo, sampleBufferOpt) = pendingSampleBuffers.removeFirst()
        guard let sampleBuffer = sampleBufferOpt else {
            throw VideoWriterError.failedToCopyBuffer
        }
        try capturedFrame(sampleBuffer: sampleBuffer, isVideo: isVideo)
    }

Seems to work, but there is a lot of posts about copying is shallow. I wonder if that can be related to my problems? Sample buffers exist in some kind of pool?

Upvotes: 4

Views: 668

Answers (1)

Nikhil Manapure
Nikhil Manapure

Reputation: 3878

If false is returned, clients can check the value of the AVAssetWriter status property to determine whether the writing operation completed, failed, or was cancelled. If the status is failed, The AVAssetWriter error property will contain an instance of NSErrorß that describes the failure.

From append(_:).

I hope this helps. Please do comment for improvements.

Upvotes: 2

Related Questions