Как объединить аудио и видео с помощью AVMutableCompositionTrack

В моем приложении мне нужно объединить аудио и видео, а затем мне нужно воспроизвести аудиофайл в медиаплеере. Как я могу объединить аудио и видео в IOS. Есть ли исходный код для этого. Пожалуйста, предложите мне несколько идей

заранее спасибо


person btmanikandan    schedule 01.03.2013    source источник
comment
Проведите некоторое исследование — например, просмотрите видео WWDC + пример кода.   -  person spring    schedule 02.03.2013


Ответы (4)


Использовать это

AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:audioUrl options:nil];
AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:videoUrl options:nil];

AVMutableComposition* mixComposition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionCommentaryTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio 
                                                                                    preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionCommentaryTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) 
                                    ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] 
                                     atTime:kCMTimeZero error:nil];

AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo 
                                                                                    preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) 
                               ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] 
                                atTime:kCMTimeZero error:nil];

AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition 
                                                                      presetName:AVAssetExportPresetHighestQuality];   

NSString* videoName = @"export.mov";

NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName];
NSURL    *exportUrl = [NSURL fileURLWithPath:exportPath];

if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) 
{
    [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}

_assetExport.outputFileType = @"com.apple.quicktime-movie";
_assetExport.outputURL = exportUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;

[_assetExport exportAsynchronouslyWithCompletionHandler:
 ^(void ) {      
            // your completion code here
     }       
 }
 ];
person dineshprasanna    schedule 02.03.2013
comment
Я попробовал этот код. Это не работает, а также есть одна ошибка в приведенном выше коде. Замените initWithURL на URLAssetWithURL. - person btmanikandan; 02.03.2013
comment
Я использовал этот код с аудиофайлом 1s и видеофайлом 3s. Результатом было видео с 1 секундой звука с черным экраном, затем 2 секунды черного экрана, а затем 3 секунды видео. Знаете ли вы, что может быть причиной этой проблемы? Я просто хочу добавить звук в начало видео. - person ill_always_be_a_warriors; 01.07.2014
comment
Я объединяю только один аудио/видео файл. Проблема в том, что мой видеофайл длится 40 секунд, а аудиофайл - 28 секунд. Итак, для оставшихся 12 (40-28) секунд — я хочу повторить это с 0 секунд в аудиофайле. Как мне это? Есть ли прямой способ сделать это? - person Hemang; 18.06.2015
comment
@BrandonA : NSString *videoPath = [[NSBundle mainBundle] pathForResource:@имя ресурса ofType:@MOV]; NSURL *videoURl = [NSURL fileURLWithPath:videoPath]; - person Sandeep Singh; 29.08.2016

Вы можете объединить видео, создав изменяемую композицию.

AVMutableComposition* composition = [[AVMutableComposition alloc]init];
AVURLAsset* video1 = [[AVURLAsset alloc]initWithURL:[NSURL fileURLWithPath:path1]options:nil];

NSArray *pathComponents = [NSArray arrayWithObjects:
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],@"MyAudio.m4a",nil];

  NSURL *outputFileURL = [NSURL fileURLWithPathComponents:pathComponents];
AVAsset *audioAsset = [AVAsset assetWithURL:outputFileURL];

//Create mutable composition of audio type
 AVMutableCompositionTrack *audioTrack = [composition    addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,video1.duration)
ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];

  AVMutableCompositionTrack* composedTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

[composedTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, video1.duration)
ofTrack:[[video1 tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
atTime:kCMTimeZero error:nil];


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

[exporter exportAsynchronouslyWithCompletionHandler:^{
           case AVAssetExportSessionStatusFailed:
                 NSLog(@"Failed to export video");
                 break;
           case AVAssetExportSessionStatusCancelled:
                 NSLog(@"export cancelled");
                 break;

}

Для слияния видео посетите этот учебник. http://iosbucket.blogspot.in/2015/04/mp4-conversion-and-video-merging-in-ios.html

Вы также можете найти пример проекта для слияния видео.

person CodeCracker    schedule 17.04.2015

http://www.raywenderlich.com/13418/how-to-play-record-edit-videos-in-ios посетите это руководство по объединению аудио- и видеофайлов

person Ankita    schedule 01.11.2013
comment
Обратите внимание, что ответы только по ссылкам не рекомендуются, ответы SO должны быть конечной точкой поиска. для решения (по сравнению с еще одной остановкой ссылок, которые со временем устаревают). Пожалуйста, рассмотрите возможность добавления здесь отдельного синопсиса, оставив ссылку в качестве ссылки. - person kleopatra; 01.11.2013

Немного поздно отвечать, но это может помочь кому-то в будущем. повторяет аудио, если продолжительность видео больше, чем аудио.

+ (void)mergeVideoWithAudio:(NSURL *)videoUrl audioUrl:(NSURL *)audioUrl success:(void (^)(NSURL *url))success failure:(void (^)(NSError *error))failure {
    AVMutableComposition *mixComposition = [AVMutableComposition new];
    NSMutableArray<AVMutableCompositionTrack *> *mutableCompositionVideoTrack = [NSMutableArray new];
    NSMutableArray<AVMutableCompositionTrack *> *mutableCompositionAudioTrack = [NSMutableArray new];
    AVMutableVideoCompositionInstruction *totalVideoCompositionInstruction = [AVMutableVideoCompositionInstruction new];
    
    AVAsset *aVideoAsset = [AVAsset assetWithURL:videoUrl];
    AVAsset *aAudioAsset = [AVAsset assetWithURL:audioUrl];
    
    AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    if (videoTrack && audioTrack) {
        [mutableCompositionVideoTrack addObject:videoTrack];
        [mutableCompositionAudioTrack addObject:audioTrack];
        
        AVAssetTrack *aVideoAssetTrack = [aVideoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
        AVAssetTrack *aAudioAssetTrack = [aAudioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject;
        
        if (aVideoAssetTrack && aAudioAssetTrack) {
            [mutableCompositionVideoTrack.firstObject insertTimeRange:CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration) ofTrack:aVideoAssetTrack atTime:kCMTimeZero error:nil];
            
            CMTime videoDuration = aVideoAsset.duration;
            if (CMTimeCompare(videoDuration, aAudioAsset.duration) == -1) {
                [mutableCompositionAudioTrack.firstObject insertTimeRange:CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration) ofTrack:aAudioAssetTrack atTime:kCMTimeZero error:nil];
            } else if (CMTimeCompare(videoDuration, aAudioAsset.duration) == 1) {
                CMTime currentDuration = kCMTimeZero;
                while (CMTimeCompare(currentDuration, videoDuration) == -1) {
                    // repeats audio
                    CMTime restTime = CMTimeSubtract(videoDuration, currentDuration);
                    CMTime maxTime = CMTimeMinimum(aAudioAsset.duration, restTime);
                    [mutableCompositionAudioTrack.firstObject insertTimeRange:CMTimeRangeMake(kCMTimeZero, maxTime) ofTrack:aAudioAssetTrack atTime:currentDuration error:nil];
                    currentDuration = CMTimeAdd(currentDuration, aAudioAsset.duration);
                }
            }
            videoTrack.preferredTransform = aVideoAssetTrack.preferredTransform;
            totalVideoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration);
        }
    }
    
    NSString *outputPath = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp/screenCapture.mp4"];
    if ([[NSFileManager defaultManager] fileExistsAtPath:outputPath]) {
        [[NSFileManager defaultManager] removeItemAtPath:outputPath error:nil];
    }
    NSURL *outputURL = [NSURL fileURLWithPath:outputPath];
    
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
    exportSession.outputURL = outputURL;
    exportSession.outputFileType = AVFileTypeMPEG4;
    exportSession.shouldOptimizeForNetworkUse = YES;
    
    // try to export the file and handle the status cases
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        switch (exportSession.status) {
            case AVAssetExportSessionStatusFailed:
                failure(exportSession.error);
                break;
            case AVAssetExportSessionStatusCancelled:
                failure(exportSession.error);
                break;
            default:
                success(outputURL);
                break;
        }
    }];
}
person Le Ding    schedule 17.12.2020