I am trying to stitch a bunch of videos together and then add some music over the video in iOS. The audio is added using AVMutableAudioMix
. However when the video is finally exported the audio mix is missing. Here is how the code looks like :
- (void)mergeVideos:(NSArray *)videos{
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime currentTime = kCMTimeZero;
for (AVAsset *asset in videos) {
// 2 - Video track
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
ofTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:currentTime error:nil];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
ofTrack:[[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:currentTime error:nil];
currentTime = CMTimeAdd(currentTime, asset.duration);
}
// 4 - Get path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:@"mergeVideo-%d.mp4",arc4random() % 1000]];
NSURL *url = [NSURL fileURLWithPath:myPathDocs];
// 5 - Create exporter
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:mixComposition];
NSString *quality = AVAssetExportPresetHighestQuality;
//load the audio
AVMutableAudioMix *audioMix = nil;
NSURL *audioURL = [self loadAudioFile];// gives a url for a .caf file from the bundle
if (audioURL) {
AVURLAsset *audioAsset = [AVURLAsset assetWithURL:audioURL];
AVAssetTrack *aTrack = (AVAssetTrack *)[[audioAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];
AVMutableAudioMixInputParameters *trackMix =
[AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:aTrack];
[trackMix setVolumeRampFromStartVolume:0 toEndVolume:1 timeRange:
CMTimeRangeMake(CMTimeMakeWithSeconds(0, 1), CMTimeMakeWithSeconds(3, 1))];
[trackMix setVolume:1.0 atTime:kCMTimeZero];
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
audioMix.inputParameters = [NSArray arrayWithObject:trackMix];
}
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:quality];
if (audioMix) {
exporter.audioMix = audioMix;
}
exporter.outputURL=url;
exporter.outputFileType = AVFileTypeMPEG4;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinish:exporter];
});
}];
}
There is no error while executing. Just that the music contained in the .caf
file doesnt get mixed to the exported file. Any idea what is going on?
You haven't inserted the audio from the .caf file into any AVMutableCompositionTrack
, so the audio mix associated with aTrack
is not going to adjust the volume for the .caf file. If you'd like the audio from the .caf file to be included in the video with the associated audio mix, create another AVMutableCompositionTrack
to hold the audio from the .caf file:
AVMutableCompositionTrack *audioTrackCAF = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
(with the time ranges set to your liking):
[audioTrackCAF insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration)
ofTrack:aTrack atTime:kCMTimeZero error:nil]
Additionally, is helpful to pass an NSError *
(instead of nil
) to insertTimeRange:ofTrack:atTime:error
to make sure you had valid time ranges and your media was inserted.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.