Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting Track Levels on AVMutableComposition

I'm trying to combine 4 audio tracks to a single composition, then export this composition to a file. So far my file is created successfully but all of the audio tracks play back at full volume instead of the volume levels I'm trying to set. Here is what I'm doing now:

AVMutableComposition *trackComposition = [AVMutableComposition composition];

AVAsset *asset1 = ...
AVAsset *asset2 = ...
AVAsset *asset3 = ...
AVAsset *asset4 = ...

NSMutableArray *inputParams = [NSMutableArray arrayWithCapacity:4];

// Add 4 tracks to composition (but only if there are no errors and the track isn't muted
NSError *err;
if(asset1 && ![self trackIsMuted:1]){
    AVAssetTrack *rawTrack = [[asset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    AVMutableCompositionTrack *compositionAudioTrack = [trackComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset1 duration]) ofTrack:rawTrack atTime:kCMTimeZero error:&err];
    AVAudioMixInputParameters *audioParams = [self audioParamsForTrack:compositionAudioTrack volume:[self gainForTrack:1]];
    [inputParams addObject:audioParams];
}
if(asset2 && !err && ![self trackIsMuted:2]){
    AVAssetTrack *rawTrack = [[asset2 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    AVMutableCompositionTrack *compositionAudioTrack = [trackComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset2 duration]) ofTrack:rawTrack atTime:kCMTimeZero error:&err];
    AVAudioMixInputParameters *audioParams = [self audioParamsForTrack:compositionAudioTrack volume:[self gainForTrack:2]];
    [inputParams addObject:audioParams];
}
if(asset3 && !err && ![self trackIsMuted:3]){
    AVAssetTrack *rawTrack = [[asset3 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    AVMutableCompositionTrack *compositionAudioTrack = [trackComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset3 duration]) ofTrack:rawTrack atTime:kCMTimeZero error:&err];
    AVAudioMixInputParameters *audioParams = [self audioParamsForTrack:compositionAudioTrack volume:[self gainForTrack:3]];
    [inputParams addObject:audioParams];
}
if(asset4 && !err && ![self trackIsMuted:4]){
    AVAssetTrack *rawTrack = [[asset4 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    AVMutableCompositionTrack *compositionAudioTrack = [trackComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset4 duration]) ofTrack:rawTrack atTime:kCMTimeZero error:&err];
    AVAudioMixInputParameters *audioParams = [self audioParamsForTrack:compositionAudioTrack volume:[self gainForTrack:4]];
    [inputParams addObject:audioParams];
}

AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
audioMix.inputParameters = inputParams;

// Export the composition to a file
AVAssetExportSession *export = [AVAssetExportSession exportSessionWithAsset:trackComposition presetName:AVAssetExportPresetAppleM4A];

NSURL *outputURL = [NSURL fileURLWithPath:[[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString guidString]] stringByAppendingPathExtension:@"m4a"]];

[export setOutputURL:outputURL];
[export setOutputFileType:@"com.apple.m4a-audio"];

[export setAudioMix:audioMix];

[export exportAsynchronouslyWithCompletionHandler:^{ ... }];

The only other interesting thing is the audioParamsForTrack method, which is here:

- (AVAudioMixInputParameters *)audioParamsForTrack:(AVAssetTrack *)track volume:(float)vol{
    AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];
    [audioInputParams setVolume:vol atTime:kCMTimeZero];

    return [audioInputParams copy];
}

Can anyone spot what I'm doing wrong? I've tried passing all sorts of different tracks to create the audio parameters but it doesn't seem to make a difference. I saw something about a track's preferred volume - is this something that might help me? I'm a bit stuck at this point, any feedback is appreciated!

like image 642
Cory Imdieke Avatar asked Apr 16 '12 20:04

Cory Imdieke


1 Answers

I had a similar problem but what worked for me was setting the track Id explicitly on the input parameters:

    [audioInputParams setTrackID:compositionAudioTrack.trackID];
like image 85
Oren Avatar answered Oct 03 '22 20:10

Oren