1
votes

I'm trying to mix 2 audios tracks into one (Video's sound and some music).

With AVFoundation I can set two tracks to a video file with this method :

https://stackoverflow.com/a/16316985/5120292

Here is the result output file, inspected with ffmpeg on my computer :

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'IMG_3789.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp41mp42isom
    creation_time   : 2017-05-11T15:46:52.000000Z
  Duration: 00:00:22.63, start: 0.000000, bitrate: 38210 kb/s
    Stream #0:0(und): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p, 1696x848, 37782 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 180k tbc (default)
    Metadata:
      creation_time   : 2017-05-11T15:46:52.000000Z
      handler_name    : Core Media Video
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 250 kb/s (default)
    Metadata:
      creation_time   : 2017-05-11T15:46:52.000000Z
      handler_name    : Core Media Audio
    Stream #0:2(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default)
    Metadata:
      creation_time   : 2017-05-11T15:46:52.000000Z
      handler_name    : Core Media Audio 

You can see that the file contains two audio tracks. I would need to merge the two tracks into one, because some players only play the first track.

Is it possible to mix them into only one track instead of 2 separated tracks ?

Thanks in advance ! Any help would be appreciated

1

1 Answers

1
votes

This code merges the audio tracks down into one - I think that's thanks to the AVMutableComposition (and not the AVAssetExportSession):

AVAssetTrack *videoTrack = ...;
AVAssetTrack *audioTrack1 = ...;
AVAssetTrack *audioTrack2 = ...;

AVMutableComposition *composition = [AVMutableComposition composition];

for (AVAssetTrack* inputTrack in @[videoTrack, audioTrack1, audioTrack2]) {
    AVMutableCompositionTrack* outputTrack;
    outputTrack = [composition addMutableTrackWithMediaType:inputTrack.mediaType preferredTrackID:kCMPersistentTrackID_Invalid];

    NSError* error;
    if (![outputTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, inputTrack.timeRange.duration) ofTrack:inputTrack atTime:kCMTimeZero error:&error]) {
        NSLog(@"insertTimeRange error: %@", error);
    }
}

AVAssetExportSession* exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetHighestQuality];

NSURL *outputURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0] URLByAppendingPathComponent:@"output.mp4"];
[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];

exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.outputURL = outputURL;

[exportSession exportAsynchronouslyWithCompletionHandler:^{
    if (AVAssetExportSessionStatusCompleted == exportSession.status) {
        NSLog(@"success %@", outputURL);
    } else {
        NSLog(@"failed %li", (long)exportSession.status);
    }
}];