2016-01-08 45 views
2

我是新來的視頻編程。我正在嘗試使用它,但我遇到了麻煩,它將兩個視頻文件合併爲一個。是否有可能將兩個視頻文件合併到一個文件,iOS中的一個屏幕?

我的意思是如下合併..

我第一視頻這樣 enter image description it i

第二部影片也是這樣 enter image description here

我希望他們合併像這樣 enter image description here

我不想使用2個視頻播放器,因爲我想將合併的視頻文件發送給某人。我整天搜查解決這個問題,但我無法找到答案。

我寫了代碼參考this鏈接,但它只顯示第一個視頻,沒有合併。

我的代碼:

NSURL *firstURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"video1" ofType:@"mp4"]] 
AVURLAsset *firstAsset = [[AVURLAsset alloc]initWithURL:firstURL options:nil]; 

NSURL *secondURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"video2" ofType:@"mp4"]]; 
VURLAsset *secondAsset = [[AVURLAsset alloc]initWithURL:secondURL options:nil]; 

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

AVMutableCompositionTrack *secondTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo 
                    preferredTrackID:kCMPersistentTrackID_Invalid]; 

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

[secondTrack setPreferredTransform:CGAffineTransformMakeScale(0.25f,0.25f)]; 

NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *docsDir = [dirPaths objectAtIndex:0]; 
NSString *outputFilePath = [docsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"FinalVideo.mov"]]; 

NSLog(@"%@", outputFilePath); 

NSURL *outputFileUrl = [NSURL fileURLWithPath:outputFilePath]; 
if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath]) 
    [[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil]; 


AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality]; 
assetExport.outputFileType = @"com.apple.quicktime-movie"; 
assetExport.outputURL = outputFileUrl; 

[assetExport exportAsynchronouslyWithCompletionHandler: ^(void) { 

    switch (assetExport.status) { 
     case AVAssetExportSessionStatusFailed: 
      NSLog(@"AVAssetExportSessionStatusFailed"); 
      break; 
     case AVAssetExportSessionStatusCompleted: 
      NSLog(@"AVAssetExportSessionStatusCompleted"); 
      break; 
     case AVAssetExportSessionStatusWaiting: 
      NSLog(@"AVAssetExportSessionStatusWaiting"); 
      break; 
     default: 
      break; 
    } 
} 
]; 

我缺少什麼?我不知道如何解決這個問題。

欣賞任何想法。 謝謝。

編輯:

我犯了該引用鏈接馬特寫道,由於亞光一個新的代碼。但是當我試圖導出它時,只導出了第一個視頻。不在一起.. :(

我的新代碼..

NSURL *originalVideoURL1 = [[NSBundle mainBundle] URLForResource:@"video1" withExtension:@"mov"]; 
NSURL *originalVideoURL2 = [[NSBundle mainBundle] URLForResource:@"video2" withExtension:@"mov"]; 


AVURLAsset *firstAsset = [AVURLAsset URLAssetWithURL:originalVideoURL1 options:nil]; 
AVURLAsset *secondAsset = [AVURLAsset URLAssetWithURL:originalVideoURL2 options:nil]; 

AVMutableComposition* mixComposition = [[AVMutableComposition alloc] init]; //[AVMutableComposition composition]; 

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

if(error) { 
    NSLog(@"firstTrack error!!!. %@", error.localizedDescription); 
} 

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

if(error) { 
    NSLog(@"secondTrack error!!!. %@", error.localizedDescription); 
} 


AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, firstAsset.duration); 

AVMutableVideoCompositionLayerInstruction *firstLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:firstTrack]; 
CGAffineTransform scale = CGAffineTransformMakeScale(0.7, 0.7); 
CGAffineTransform move = CGAffineTransformMakeTranslation(230, 230); 
[firstLayerInstruction setTransform:CGAffineTransformConcat(scale, move) atTime:kCMTimeZero]; 

AVMutableVideoCompositionLayerInstruction *secondLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:secondTrack]; 
CGAffineTransform secondScale = CGAffineTransformMakeScale(1.2, 1.5); 
CGAffineTransform secondMove = CGAffineTransformMakeTranslation(0, 0); 
[secondLayerInstruction setTransform:CGAffineTransformConcat(secondScale, secondMove) atTime:kCMTimeZero]; 

mainInstruction.layerInstructions = @[firstLayerInstruction, secondLayerInstruction]; 

AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition]; 
mainCompositionInst.instructions = @[mainInstruction]; 
mainCompositionInst.frameDuration = CMTimeMake(1, 30); 
mainCompositionInst.renderSize = CGSizeMake(640, 480); 

AVPlayerItem *newPlayerItem = [AVPlayerItem playerItemWithAsset:mixComposition]; 
newPlayerItem.videoComposition = mainCompositionInst; 

AVPlayer *player = [[AVPlayer alloc] initWithPlayerItem:newPlayerItem]; 

AVPlayerLayer *playerLayer =[AVPlayerLayer playerLayerWithPlayer:player]; 

[playerLayer setFrame:self.view.bounds]; 
[self.view.layer addSublayer:playerLayer]; 
[player seekToTime:kCMTimeZero]; 
[player play]; // play is Good!! 


NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 

NSString *tempS2 = [documentsDirectory stringByAppendingPathComponent:@"FinalVideo.mov"]; 

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


NSURL *url = [[NSURL alloc] initFileURLWithPath: tempS2]; 

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

exportSession.outputURL=url; 

NSLog(@"%@", [exportSession supportedFileTypes]); 

exportSession.outputFileType = AVFileTypeQuickTimeMovie; 
[exportSession exportAsynchronouslyWithCompletionHandler:^{ 
    if (exportSession.status==AVAssetExportSessionStatusFailed) { 
     NSLog(@"failed"); 
    } 
    else { 
     NSLog(@"AudioLocation : %@",tempS2); 
    } 
}]; 

如何導出我mixComposition和layerInstruction兩者兼而有之?

請給我多一點的想法。

謝謝

+2

但你看過這裏的討論:https://abdulazeem.wordpress.com/2012/04/02/video-manipulation-in-ios-resizingmerging-and-overlapping-videos-in-ios/?關鍵是使用AVMutableVideoCompositionLayerInstruction,並且我沒有看到你在任何地方做這件事。 – matt

+0

感謝您的評論亞光。但是當我導出最終文件時,我遇到了麻煩。你能給我多一點提示嗎? – MoonSoo

回答

1

參考第二次編輯中的代碼,就像您告訴AVPlayerItem關於您的AVMutableVideoComposition一樣,您還需要t ELL的AVAssetExportSession太:

exportSession.videoComposition = mainCompositionInst; 
// exportAsynchronouslyWithCompletionHandler etc 

注:設置你的指示時段時,確保你選擇兩個軌道持續時間較長:

mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMaximum(firstAsset.duration, secondAsset.duration)); 

AVPlayer如果你得到這個錯誤並不介意,但不AVAssetExportSession將返回一個AVErrorInvalidVideoComposition(-11841)的錯誤。

N.B. 2你的AVPlayer實際上並沒有超出範圍,但當我看着它時,它讓我感到緊張。如果我是你,我會把它分配給一個物業。

相關問題