使用AVMutableComposition编写video和audio

我有一个奇怪的问题。 在我的应用程序中,我使用下面的代码组合了多个audio和video文件。 结果video似乎工作正常,一旦我将它从设备下载到计算机和快速时间播放,但每当我试图播放使用UIWebView或AVPLayer新组成的video,我只能看到合并video文件的第一部分。

此外,当我试图使用MPMoviePlayerController播放它挂在“加载”。

我可以听到所有作品的audio。 为了说清楚我有两个数组:1-audiopath与audio文件[歌曲1,歌曲2,歌曲3]的path; 2-电影与video文件path[电影1,电影2,电影3]; 合并这些文件后,我只能看到movie1,但是我可以听到song1 + song2 + song3。 PS歌曲和电影有不同的长度(小于0.2s的差异)。 任何帮助将不胜感激。 先谢谢你,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循环体外。