I try to write frames into a video using AVAssetWriter. I wrote codes as below:
// Initial AVAssetWriter
// Write mp4 file
let assetWriter = try AVAssetWriter(outputURL: targetUrl, fileType: .mp4)
let width = size.width * 2
// set options for written video
let videoSettings: [String : Any] = [
AVVideoCodecKey: AVVideoCodecType.h264,
AVVideoWidthKey: width,
AVVideoHeightKey: size.height
]
guard assetWriter.canApply(outputSettings: videoSettings, forMediaType: AVMediaType.video) else {
fatalError("Error applying output settings")
}
// Initial AVAssetWriterInput
let assetWriterInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings)
// set arritbutes
let sourcePixelBufferAttributes: [String : Any] = [
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA]
// Initial AVAssetWriterInputPixelBufferAdaptor
let inputPixelBufferAdaptor =
AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: assetWriterInput,
sourcePixelBufferAttributes: sourcePixelBufferAttributes)
if assetWriter.canAdd(assetWriterInput) == true {
assetWriter.add(assetWriterInput)
assetWriter.startWriting()
assetWriter.startSession(atSourceTime: .zero)
} else {
print("Cannot add asset writer input.")
}
if let error = assetWriter.error {
print("assetWrite status=(assetWriter.status), error=(error)")
}
But using my iPhone 14 Pro, it will run into print("assetWrite status=(assetWriter.status), error=(error)")
shows:
assetWrite status=AVAssetWriterStatus(rawValue: 3), error=Error
Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed"
UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12902),
NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x30189cb10
{Error Domain=NSOSStatusErrorDomain Code=-12902 "(null)"}}
The size = CGSize(width: 2200, height: 2200)
that is width = size.width * 2 = 4400
If I wrote:
let videoSettings: [String : Any] = [
AVVideoCodecKey: AVVideoCodecType.h264,
AVVideoWidthKey: 4090, // width,
AVVideoHeightKey: size.height
]
It won’t run into the error. If set as 4100 or larger will also run into the error.
Is there anyway to solve this issue that using the 4400 or larger value as the width key?
2
Answers
It is a memory issue try using autoreleasepool
let pxBuffer = autoreleasepool {return self.newPixelBufferFrom(cgImage: image.cgImage!)}
Well, as the error message says:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12902),
-12902(which is
kVTParameterErr
) typically means your parameters passed to AssertWriter(VideoToolbox under the hood) is wrong.So, check the logs from console you can get a better understanding:
The
H264StartSession
first says your resolution is within the acceptable range of the H.264 encoder [4400,2208], that is slightly larger than standard 4k 4096×2160 in H.264 Level 5.1.However, this doesn’t necessarily mean that the resolution is supported by subsequent modules. The H.264 standard technically supports resolutions up to 8192×4320 (Level 6.2), but many devices and software implementations do not support these higher levels. The most commonly supported maximum resolution for H.264 is 4096×2160 (Level 5.1). And the
FigExportCommon
module, which I believe is the hardware accelerated media exporting system on iOS implemented with VideoToolbox, it does not accept any dimension who is larger than 4096×2160.I create a demo project here, you can fiddle with it and you can see if your dimension is larger than 4096, a
kVTParameterErr
will occur.If you really want a dimension like 4400×2200, consider change
AVVideoCodecKey
toAVVideoCodecType.hevc
, it works. I believe at the year of 2024, HEVC is also wildly supported.