【问题标题】:AVAssetWriter fails only in iOS when writing audio from specific videos从特定视频写入音频时,AVAssetWriter 仅在 iOS 中失败
【发布时间】:2020-10-09 04:04:26
【问题描述】:

我有一个用于调整视频大小的示例项目,它适用于大多数视频。但是,AVAssetWriter 无法写入来自特定视频的音频并出现错误:

Error Domain=AVFoundationErrorDomain 
Code=-11800 "The operation could not be completed" 
UserInfo={
  NSLocalizedFailureReason=An unknown error occurred (-12780), 
  NSLocalizedDescription=The operation could not be completed, 
  NSUnderlyingError=0x282e956e0 {
    Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"
  }
}

更成问题的是,如果我在 macOS 上运行相同的代码,它可以正常工作,但在 iOS 中它会中断。我认为这不是硬件问题,因为它也会在 iOS 模拟器中中断。

这些是我用于(解)压缩资产轨道的设置:

func audioDecompressionSettings() -> [String: Any] {
    return [
        AVFormatIDKey: kAudioFormatLinearPCM
    ]
}

func audioCompressionSettings() -> [String: Any] {
    var audioChannelLayout = AudioChannelLayout()
    memset(&audioChannelLayout, 0, MemoryLayout<AudioChannelLayout>.size)
    audioChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo
    
    return [
        AVFormatIDKey: kAudioFormatMPEG4AAC,
        AVSampleRateKey: 44100,
        AVEncoderBitRateKey: 128000,
        AVNumberOfChannelsKey: 2,
        AVChannelLayoutKey: NSData(bytes: &audioChannelLayout, length: MemoryLayout<AudioChannelLayout>.size)
    ]
}

func videoDecompressionSettings() -> [String: Any] {
    return [
        kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
        kCVPixelBufferMetalCompatibilityKey as String: true
    ]
}

func videoCompressionSettings(size: CGSize) -> [String: Any] {
    return [
        AVVideoCodecKey: AVVideoCodecType.h264,
        AVVideoWidthKey: size.width,
        AVVideoHeightKey: size.height
    ]
}

完整的源代码可以在here找到。

在该项目中有两个目标,一个用于 Mac,另一个用于 iOS,它们都使用相同的代码来调整视频大小。我还包括了两个示例视频文件:fruit.mp4rain.mp4。第一个在两个目标中都运行良好,但第二个在 iOS 中中断。

我是否在这里遗漏了什么或者这很可能是一个 Apple 错误?

【问题讨论】:

    标签: ios avfoundation avassetwriter avassetreader


    【解决方案1】:

    有问题的视频的音频设置是:

    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 386 kb/s (default)

    另外一个是:

    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 137 kb/s (default)

    两者之间的重要区别在于音频通道的数量:第一个为 5.1(5 个全带宽通道 + 一个低频效果通道),第二个为立体声 (2)。

    在读取视频文件时,我们指定解压设置:

    [AVFormatIDKey: kAudioFormatLinearPCM]
    

    这意味着解压后的音频将具有与源文件相同的声道数。在我们的例子中,我们有一个 5.1(实际上是 6 个)通道资产,我们想将它写入一个 2 通道文件。 AVAssetWriterInput 似乎在 iOS 中没有正确处理这种情况,我们得到一个错误。

    解决问题的方法是在从资产中解压音频时指定我们想要的音频通道数,如下所示:

    [
        AVFormatIDKey: kAudioFormatLinearPCM
        AVNumberOfChannelsKey: 2
    ]
    

    【讨论】:

      最近更新 更多