5

Does someone know how to use the AVAssetWriterInput init with more than 2 channels?

I'm trying to init an audioInput, to add it after on AVAssetWriter this way:

let audioInput = AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: audioOutputSettings)

assetWriter.add(audioInput)

assetWriter.startWriting()

But it crashes when I init the audioInput with the audioOutputSettings dictionary containing the number of channels key greater than 2. The error is:

Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ’*** -[AVAssetWriterInput initWithMediaType:outputSettings:sourceFormatHint:] 6 is not a valid channel count for Format ID ‘aac ’. Use kAudioFormatProperty_AvailableEncodeNumberChannels (<AudioToolbox/AudioFormat.h>) to enumerate available channel counts for a given format.

  • I _think_ aac can encode more than 2 channels, but it looks like apple's implementation doesn't do it, at least not via `AVAssetWriter`. What if you add 3 stereo `AVAssetWriterInput`s? If it works, you'd probably have 3 selectable audio tracks, which might not be what you want... How are you playing back this 6 channel file? – Rhythmic Fistman Apr 08 '18 at 09:11
  • On the AVAssetWriterInput's init has the comment: `If AVNumberOfChannelsKey specifies a channel count greater than 2, the dictionary must also specify a value for AVChannelLayoutKey.` But I don't know what value should be passed for this key. I'm able to play back the video with 6 channels from the iPad's simulator. – Anne Kariny Silva Freitas Apr 09 '18 at 22:00
  • Oh wow - here it says it should be an NSData of AudioChannelLayout: https://developer.apple.com/documentation/avfoundation/avchannellayoutkey but I don’t know what the layout should be. Is it some kind of surround sound? – Rhythmic Fistman Apr 09 '18 at 22:30
  • This is my point. I don't know what should be passed. I've tried a lot of values but still didn't work and I have no idea what to do. And about the sound, it is a surround sound. – Anne Kariny Silva Freitas Apr 09 '18 at 22:38
  • Can you show your attempt at creating an `AudioChannelLayout`? E.g. left, right, center left, center right and behind? Do you get the same error when you pass the channel layout? – Rhythmic Fistman Apr 09 '18 at 23:15
  • I can't because I deleted the attempt I have made before, because I found the example on the internet in Obj-C and wasn't understanding the logic :/ – Anne Kariny Silva Freitas Apr 12 '18 at 19:58

2 Answers2

6

As you found in the AVAssetWriterInput comment:

If AVNumberOfChannelsKey specifies a channel count greater than 2, the dictionary must also specify a value for AVChannelLayoutKey.

What it fails to mention is that the channel count depends on your format ID, so passing a AudioChannelLayout won't make AAC support anything other than 1 or 2 channels.

Formats that do support 6 channels include LPCM kAudioFormatLinearPCM and, probably more interestingly, High Efficiency AAC (kAudioFormatMPEG4AAC_HE) which supports 2, 4, 6 and 8 channel audio.

The following code creates an AVAssetWriterInput that is ready for 6 channel AAC HE sample buffers:

var channelLayout = AudioChannelLayout()
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_D

let audioOutputSettings: [String : Any] = [
    AVNumberOfChannelsKey: 6,

    AVFormatIDKey: kAudioFormatMPEG4AAC_HE,
    AVSampleRateKey: 44100,
    AVChannelLayoutKey: NSData(bytes: &channelLayout, length: MemoryLayout.size(ofValue: channelLayout)),
]
let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioOutputSettings)
Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
  • Great answer! As you said, `kAudioFormatMPEG4AAC_HE` supports 2, 4, 6 and 8 channels audio, but I also have to support 1 channel audio and this example won't fit for me. What do you suggest for me? Check if the audio has 1 or 2 and use `kAudioFormatMPEG4AAC` and if it's higher use `kAudioFormatMPEG4AAC_HE`? Or use `kAudioFormatLinearPCM`? – Anne Kariny Silva Freitas Apr 12 '18 at 19:52
  • 1
    That's right. I'll check the number of channels before init the `AVAssetWriterInput` and choose properly the `AVFormatIDKey`. Thanks for the answer :) – Anne Kariny Silva Freitas Apr 12 '18 at 23:25
  • @Rhythmic, How to check the number of channels for AVAssetWriterInput? – Diken Shah Mar 09 '20 at 06:56
  • You can recover the channel configuration like this: `assetWriterInput.outputSettings[AVNumberOfChannelsKey]` - is that what you mean? – Rhythmic Fistman Mar 09 '20 at 07:45
  • Thank you @RhythmicFistman for the quick reply but I am facing this crash in my device. [AVAssetWriterInput initWithMediaType:outputSettings:sourceFormatHint:] 6 is not a valid channel count for Format ID 'aach'. Use kAudioFormatProperty_AvailableEncodeNumberChannels () to enumerate available channel counts for a given format.' – Diken Shah Mar 09 '20 at 07:58
  • Interesting - AAC_HE claims it supports 1, 2, 4, 6 and 8 channel! Can you start a new question showing how you're setting up your `AVAssetWriterInput`? – Rhythmic Fistman Mar 09 '20 at 11:52
  • 1
    I got an error: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVAssetWriterInput initWithMediaType:outputSettings:sourceFormatHint:] 6 is not a valid channel count for Format ID 'aach'. Use kAudioFormatProperty_AvailableEncodeNumberChannels () to enumerate available channel counts for a given format.' *** First throw call stack: How can I fix this issue ? Thanks – Sergey Burd Apr 27 '20 at 07:26
  • 1
    Can you show some code @SergeyBurd? Maybe in a new question? – Rhythmic Fistman Apr 27 '20 at 09:49
  • In my case, it fails for 4 channel audio input with even LPCM codec. – Deepak Sharma Oct 10 '22 at 15:03
  • what's the container format? – Rhythmic Fistman Oct 11 '22 at 04:50
  • @RhythmicFistman It is mov format (container). – Deepak Sharma Oct 29 '22 at 11:04
  • @RhythmicFistman Have a look at this question - https://stackoverflow.com/questions/74264972/avassetwriter-audio-settings-failure-with-compression-settings – Deepak Sharma Oct 31 '22 at 14:53
0

Change these two lines:

channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_2_0
AVNumberOfChannelsKey : 2,

I hope it helps you in my code it worked.