4

I have some audio files that I need to insert in an AVMutableComposition. Each audio have a different volume. To accomplish that I created an AVMutableTrackComposition and an AVAssetTrack for each audio file. So I change the volume for every track using an instance of AVMutableAudioMix.

let composition = AVMutableComposition()
var trackMixArray = NSMutableArray()

for audio in layer{
   let trackAudio:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())

   let file = project.stringByAppendingPathComponent(audio.name)
   let soundAsset = AVURLAsset(URL: NSURL(fileURLWithPath: file), options: option as [NSObject : AnyObject])
   let sounds = soundAsset.tracksWithMediaType(AVMediaTypeAudio)
   var sound:AVAssetTrack = sounds[0] as! AVAssetTrack
   let duration:CMTime = sound.timeRange.duration

   let audioTimeRange:CMTimeRange = CMTimeRangeFromTimeToTime(kCMTimeZero, duration)
   let start:CMTime = CMTimeMakeWithSeconds(audio.start.toDouble()!, 600)
   let stop:CMTime = CMTimeMakeWithSeconds(audio.stop.toDouble()!, 600)

   let trackMix = AVMutableAudioMixInputParameters(track: trackAudio)
   trackMix.setVolume(audio.volume, atTime: kCMTimeZero)
   trackMixArray.addObject(trackMix)

   trackAudio.insertTimeRange(audioTimeRange, ofTrack: sound, atTime: start, error: nil)
 }

let audioMix = AVMutableAudioMix()
audioMix.inputParameters = trackMixArray as [AnyObject]

Using a single AVMutableCompositionTrack with more AVAssetTrack associated to it doesn't allow me to change the volume for each track.

 let trackMix = AVMutableAudioMixInputParameters(track: sound)
 trackMix.setVolume(audio.volume, atTime: kCMTimeZero)
 trackMixArray.addObject(trackMix)

It's possible to change the volume directly from the AVAssetTrack?

Dharmesh Dhorajiya
  • 3,976
  • 9
  • 30
  • 39
Marco
  • 1,057
  • 1
  • 19
  • 36
  • What do you mean by "doesn't allow me to change the volume for each track"? What do you mean by "change the volume directly"? Explain clearly what you are trying to _do_. – matt May 12 '15 at 04:59
  • I can change the volume for each AVMutableCompositionTrack but not for each AVAssetTrack. To do that I have to assign each AVAssetTrack to a AVMutableCompositionTrack and change the volume from AVMutableCompositionTrack. – Marco May 14 '15 at 20:18
  • My goal is to use a single AVMutableCompositionTrack cause using to much of it slow the declaration of an AVPlayerItem – Marco May 14 '15 at 20:24
  • I still don't see the problem. You have explained beautifully how to set the preferred volume of an asset track, by dropping down to the mutable composition track subclass where it is mutable. So just do that. A mutable composition track _is_ an asset track; you can use the former wherever you can use the latter. – matt May 14 '15 at 20:29
  • Class. Subclass. Do you see? – matt May 14 '15 at 20:33
  • Did you ever figure this out? – Becky Hansmeyer Nov 12 '17 at 04:26
  • Can anyone suggest me how can we set volume for each Video clips? – Anand Gautam Feb 28 '19 at 08:31

1 Answers1

1
    AVMutableComposition *collageComposition = [[AVMutableComposition alloc]init];
        ...
        Some Magic
        ...
    NSArray *tracksToDuck = [collageComposition tracksWithMediaType:AVMediaTypeAudio];
            audioMix = [AVMutableAudioMix audioMix];
            NSMutableArray *trackMixArray = [NSMutableArray array];
            for (int i = 0; i < [tracksToDuck count]; i++) {
                AVMutableAudioMixInputParameters *trackMix = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:[tracksToDuck objectAtIndex:i]];
                        [trackMix setVolume:volume atTime:kCMTimeZero];
                [trackMixArray addObject:trackMix];
            }
            audioMix.inputParameters = trackMixArray;

    ... 
    AVAssetExportSession Magic
    ...
    generalExporter = [[AVAssetExportSession alloc] initWith...
    generalExporter.audioMix = audioMix;

This should help you to change volume in each track, just change it to swift.

EDIT: each AVMutableCompositionTrack have segments, each segment have startTime and duration, you can use AVMutableAudioMixInputParameters to change volume for each CMTimeRange

 - (void)setVolumeRampFromStartVolume:(float)startVolume
                         toEndVolume:(float)endVolume
                           timeRange:(CMTimeRange)timeRange
DimaC
  • 426
  • 2
  • 8
  • this change the volume for each AVMutableCompositionTrack and not for each AVAssetTrack – Marco May 14 '15 at 20:25