我尝试使用 AVAssetWriter 将帧写入视频。我写的代码如下:
// 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)")
}
但是使用我的iPhone 14 Pro,会遇到
print("assetWrite status=\(assetWriter.status), error=\(error)")
显示:
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)"}}
那个
size = CGSize(width: 2200, height: 2200)
就是width = size.width * 2 = 4400
如果我写:
let videoSettings: [String : Any] = [
AVVideoCodecKey: AVVideoCodecType.h264,
AVVideoWidthKey: 4090, // width,
AVVideoHeightKey: size.height
]
不会出现错误。如果设置为 4100 或更大也会遇到错误。
有没有办法解决这个问题,使用 4400 或更大的值作为宽度键?
这是内存问题尝试使用autoreleasepool
let pxBuffer = autoreleasepool {return self.newPixelBufferFrom(cgImage: image.cgImage!)}
嗯,正如错误消息所示:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12902),
-12902(即kVTParameterErr
)通常意味着传递给AssertWriter(幕后的VideoToolbox)的参数是错误的。
因此,检查控制台的日志您可以更好地理解:
H264StartSession
首先表示您的分辨率在H.264编码器[4400,2208]可接受的范围内,即略大于H.264 Level 5.1中的标准4k 4096x2160。
但是,这并不一定意味着后续模块支持该分辨率。 H.264 标准在技术上支持高达 8192x4320(级别 6.2)的分辨率,但许多设备和软件实现不支持这些更高级别。 H.264 最常支持的最大分辨率是 4096x2160(级别 5.1)。而
FigExportCommon
模块,我相信是iOS上用VideoToolbox实现的硬件加速媒体导出系统,它不接受任何大于4096x2160的尺寸。
我在这里创建了一个演示项目,你可以摆弄它,你可以看到如果你的尺寸大于4096,就会出现
kVTParameterErr
。
如果您确实想要 4400x2200 这样的尺寸,请考虑将
AVVideoCodecKey
更改为 AVVideoCodecType.hevc
,它可以工作。我相信在2024年,HEVC也会得到广泛的支持。