Setting track levels on AVMutableComposition

I am trying to combine 4 audio tracks into one song and then export this song to a file. So far, my file has been created successfully, but all the audio tracks play in full instead of the volume levels that I'm trying to set. Here is what I am 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 interesting thing is the audioParamsForTrack method, which is located here:

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

Can anyone determine what I am doing wrong? I tried to transfer all kinds of tracks to create sound parameters, but it doesn't seem to make any difference. I saw something about the preferred track volume - is it something that could help me? I'm a little stuck at this point, any feedback would be appreciated!

+6
source share
2 answers

I had a similar problem, but what worked for me was setting the track identifier explicitly to the input parameters:

  [audioInputParams setTrackID:compositionAudioTrack.trackID]; 
+2
source

When debugging this, I see a problem, but I'm not sure why this is happening.

When you add parameters to an array, for example:

 [inputParams addObject:audioParams]; 

The track ID is set to 0, so it is never attached to any track:

On the console:

 <AVMutableAudioMixInputParameters: 0x16eab300, track ID = 0, volume mix: volume 0.010 at time 0.000> 

I solved this by not using the audioParamsForTrack method, but doing the work immediately before the array, for example:

 NSMutableArray *inputParams = [NSMutableArray arrayWithCapacity:4]; AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:AudioTrack]; [audioInputParams setVolume:.01f atTime:kCMTimeZero]; AVAudioMixInputParameters *audioParams = audioInputParams; [inputParams addObject:audioParams]; audioMix.inputParameters = inputParams; 
+1
source

Source: https://habr.com/ru/post/913365/


All Articles