Gilad Novik
Gilad Novik

Reputation: 4604

AVAssetReaderAudioMixOutput with multiple files?

I have 2 WAV files (mono) I would like to merge.

I want to merge them into a stereo WAV file where the first file will use the left channel while the second file will use the right channel (if possible, I would also like to control the volume and lower the second file a bit).

I've tried to use AVAssetReaderAudioMixOutput, but got the following error:

[AVAssetReaderAudioMixOutput initWithAudioTracks:audioSettings:] tracks must all be part of the same AVAsset

I'm not sure how to merge 2 different files.

AVAssetReaderOutput* reader=[AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:[NSArray arrayWithObjects:
                                                                       [[AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[documentDirectory stringByAppendingPathComponent:@"left.wav"]] options:nil].tracks lastObject],
                                                                       [[AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[documentDirectory stringByAppendingPathComponent:@"right.wav"]] options:nil].tracks lastObject],
                                                                       nil] audioSettings:nil];

Upvotes: 2

Views: 548

Answers (1)

i_82
i_82

Reputation: 373

Use AVMutableComposition, which is a subclass of AVAsset.

Example:

AVURLAsset *asset1 = [AVURLAsset assetWithURL:audioURL1];
AVURLAsset *asset2 = [AVURLAsset assetWithURL:audioURL2];

AVMutableComposition *composition = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionTrack1 =
    [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *compositionTrack2 =
    [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

NSArray<AVAssetTrack *> *assetTracks1 = [asset1 tracksWithMediaType:AVMediaTypeAudio];
NSArray<AVAssetTrack *> *assetTracks2 = [asset2 tracksWithMediaType:AVMediaTypeAudio];

AVAssetTrack *assetTrack1 = [assetTracks1 firstObject];
AVAssetTrack *assetTrack2 = [assetTracks2 firstObject];

[compositionTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset1.duration)
                           ofTrack:assetTrack1
                            atTime:kCMTimeZero
                             error:error];

[compositionTrack2 insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset2.duration)
                           ofTrack:assetTrack2
                            atTime:kCMTimeZero
                             error:error];

// Now `compositionTrack1` and `compositionTrack2` are from the same `AVAsset`.

AVAssetReaderAudioMixOutput *mixOutput = [AVAssetReaderAudioMixOutput
            assetReaderAudioMixOutputWithAudioTracks:@[ compositionTrack1, compositionTrack2 ]
                                       audioSettings:processingSettings];

Upvotes: 0

Related Questions