使用AVMutableComposition合成视频和音频 [英] Composing video and audio using AVMutableComposition

查看:87
本文介绍了使用AVMutableComposition合成视频和音频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的问题.在我的应用程序中,我使用以下代码组合了多个音频和视频文件.将视频从设备下载到计算机并使用Quick Time播放后,生成的视频似乎可以正常工作,但是每当我尝试使用UIWebView或AVPLayer播放新组成的视频时,我只能看到合并视频文件的第一部分.

I have a weird problem. In my app I am combining multiple audio and video files using the code below. The resulted video seems to work fine once I downloaded it from the device to the computer and play with Quick Time, but whenever I am trying to play the newly composed video using either UIWebView or AVPLayer I can only see first part of merged video files.

此外,当我尝试使用MPMoviePlayerController进行播放时,它挂在正在加载"上.

Furthermore when I tried to use MPMoviePlayerController to play it hangs on "Loading".

我可以听到所有作品的音频.为了清楚起见,我有两个数组: 1- audioPieces,带有音频文件[song1,song2,song3]的路径; 2-moviePieces,具有视频文件[movie1,movie2,movie3]的路径; 合并这些文件后,我只能看到movie1,但是可以听到song1 + song2 + song3. P.S.歌曲和电影的长度不同(相差不到0.2秒). 任何帮助将不胜感激. 先感谢您, 贾努斯(Janusz)

I can hear audio for all composition. To make it clear I have two arrays: 1- audioPieces with paths to audio files [song1, song2, song3]; 2- moviePieces with paths to video files [movie1,movie2,movie3]; After merging those files I can see only movie1 but I can hear song1 + song2 + song3. P.S. songs and movies have different lengths (Less than 0.2s difference). Any help will be appreciated. Thank you in advance, Janusz

-(void)putFilesTogether{
AVMutableComposition *mixComposition = [AVMutableComposition composition]; 
AVMutableCompositionTrack *videoCompositionTrack =[[AVMutableCompositionTrack alloc]init];
AVMutableCompositionTrack *audioCompositionTrack =[[AVMutableCompositionTrack alloc]init];

NSLog(@" movie  %@ audio %@ ", moviePieces, audioPieces);


NSError * error;
for(int i=0;i<moviePieces.count;i++)
{
    NSFileManager * fm = [NSFileManager defaultManager];
    NSString * movieFilePath;
    NSString * audioFilePath;
    movieFilePath = [moviePieces objectAtIndex:i];
    audioFilePath = [audioPieces objectAtIndex:i];


    if(![fm fileExistsAtPath:movieFilePath]){
        NSLog(@"Movie doesn't exist %@ ",movieFilePath);
    }
    else{
        NSLog(@"Movie exist %@ ",movieFilePath);
    }

    if(![fm fileExistsAtPath:audioFilePath]){
        NSLog(@"Audio doesn't exist %@ ",audioFilePath);
    }
    else{
        NSLog(@"Audio exists %@ ",audioFilePath);
    }


   NSURL *videoUrl = [NSURL fileURLWithPath:movieFilePath];
   NSURL *audioUrl = [NSURL fileURLWithPath:audioFilePath];


    AVURLAsset *videoasset = [[AVURLAsset alloc]initWithURL:videoUrl options:nil];
     AVAssetTrack *videoAssetTrack= [[videoasset tracksWithMediaType:AVMediaTypeVideo] lastObject];

    AVURLAsset *audioasset = [[AVURLAsset alloc]initWithURL:audioUrl options:nil];
    AVAssetTrack *audioAssetTrack= [[audioasset tracksWithMediaType:AVMediaTypeAudio] lastObject];

    videoCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

    audioCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

    CMTime tempTime = mixComposition.duration;

    [audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioasset.duration) ofTrack:audioAssetTrack atTime:tempTime error:&error];

    [videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoasset.duration) ofTrack:videoAssetTrack atTime:tempTime error:&error];

    if(error)
    {
        NSLog(@"Ups. Something went wrong! %@", [error debugDescription]);
    }
}


NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0];
NSString *caldate = [now description];

float ran = arc4random()%1000;
NSString * pathToSave = [NSString stringWithFormat:@"Output%@%f.mp4",caldate,ran];
pathToSave =[DOCUMENTS_FOLDER stringByAppendingPathComponent:pathToSave];
NSURL *movieUrl = [NSURL fileURLWithPath:pathToSave];

AVAssetExportSession *exporter =[[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetPassthrough];

exporter.outputFileType=AVFileTypeQuickTimeMovie;
exporter.outputURL=movieUrl;
exporter.shouldOptimizeForNetworkUse=YES;

CMTimeValue val = mixComposition.duration.value;

CMTime start=CMTimeMake(0, 600);
CMTime duration=CMTimeMake(val, 600);
CMTimeRange range=CMTimeRangeMake(start, duration);
exporter.timeRange=range;

[exporter exportAsynchronouslyWithCompletionHandler:^{
    switch ([exporter status]) {
        case AVAssetExportSessionStatusFailed:{
            NSLog(@"Export failed: %@ %@", [[exporter error] localizedDescription],[[exporter error]debugDescription]);
            NSString * message = @"Movie wasn't created. Try again later.";
            [self performSelectorOnMainThread:@selector(dismissMe:) withObject:message waitUntilDone:NO];
            break;}
        case AVAssetExportSessionStatusCancelled:{ NSLog(@"Export canceled");
            NSString * message1 = @"Movie wasn't created. Try again later.";
            [self performSelectorOnMainThread:@selector(dismissMe:) withObject:message1 waitUntilDone:NO];
            break;}
        case AVAssetExportSessionStatusCompleted:
        {
            NSString * message = @"Movie was successfully created.";
            CMTime duration = mixComposition.duration;

            [self saveData:duration ofPath:pathToSave];
            [self cleanFiles];
            [self performSelectorOnMainThread:@selector(dismissMe:) withObject:message waitUntilDone:NO];
        }
    }}];

}

推荐答案

问题出在:

videoCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

audioCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

它们需要移到for循环主体之外.

They need to be moved outside the for loop body.

这篇关于使用AVMutableComposition合成视频和音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆