Я пытаюсь записать кадры в видео с помощью 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], немного больше, чем стандартное разрешение 4k 4096x2160 в H.264 Level 5.1.
Однако это не обязательно означает, что последующие модули поддерживают это разрешение. Стандарт H.264 технически поддерживает разрешения до 8192x4320 (уровень 6.2), но многие устройства и реализации программного обеспечения не поддерживают эти более высокие уровни. Наиболее часто поддерживаемое максимальное разрешение для H.264 — 4096x2160 (уровень 5.1). Модуль FigExportCommon
, который, как я полагаю, представляет собой аппаратно-ускоренную систему экспорта мультимедиа в iOS, реализованную с помощью VideoToolbox, не принимает размеры, превышающие 4096x4096. Интересно, я вижу, что у NV также есть это ограничение:
Nvidia RTX3060 — это архитектура Ampere с NVENC 7-го поколения для кодирования H.264 и H.265. Максимальные возможности кодирования H.264 достигаются при разрешении 4096x4096. Если в Resolve установлено использование аппаратного кодировщика Nvidia, оно не сможет кодировать с более высоким разрешением, чем это. Это 8192x8192 для H.265.
Я создал демо-проект здесь, вы можете поэкспериментировать с ним и увидеть, что если ваш размер больше 4096x4096, произойдет kVTParameterErr
.
Если вам действительно нужен такой размер, как 4400x2200, рассмотрите возможность изменения AVVideoCodecKey
на AVVideoCodecType.hevc
, это работает. Я думаю, что в 2024 году HEVC (H.265) также будет широко поддерживаться.
Приведенный выше код еще не генерирует пиксельный буфер, поэтому я не уверен, как сделать то, что вы написали.