2014-03-19 137 views
1

任何人都可以幫我合併2個視頻和音頻文件嗎?用XCode覆蓋音頻視頻

以下是Ray Wanderlich的代碼。它可以幫助我一個接一個地合併這兩個視頻。然後,它讓一個添加音頻。但是,當它添加來自音頻文件的音頻時,它會刪除任何組合視頻中的任何音頻。

所以,我真正想要的是 -

  1. 相結合的影片,一前一
  2. 添加/覆蓋音樂與音頻文件
  3. 還保留存在於音頻後任何視頻

例如,如果在視頻文件1中,我在說「你好,你好嗎?」而在第二個視頻文件中,我會在音頻文件中用爵士音樂說「我很好」,我希望最終的視頻能夠伴隨着「你好,你好嗎?」一起演奏爵士音樂。並在最後的視頻中聽到「我很好」。因此,簡而言之,我想合併2個視頻並將視頻文件中的音頻與音頻文件中的音頻疊加在一起。

以下是我的代碼。

請問有人可以幫忙嗎?

雷Wanderlich代碼:

- (IBAction)MergeAndSave:(id)sender{ 
if(firstAsset !=nil && secondAsset!=nil){ 
    [ActivityView startAnimating]; 
    //Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack. 
    AVMutableComposition* mixComposition = [[AVMutableComposition alloc] init]; 

    //VIDEO TRACK 
    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:firstAsset.duration error:nil]; 

    //AUDIO TRACK 
    if(audioAsset!=nil){ 
     AVMutableCompositionTrack *AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
     [AudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, CMTimeAdd(firstAsset.duration, secondAsset.duration)) ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil]; 


    } 

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

    //FIXING ORIENTATION// 
    AVMutableVideoCompositionLayerInstruction *FirstlayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:firstTrack]; 
    AVAssetTrack *FirstAssetTrack = [[firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    UIImageOrientation FirstAssetOrientation_ = UIImageOrientationUp; 
    BOOL isFirstAssetPortrait_ = NO; 
    CGAffineTransform firstTransform = FirstAssetTrack.preferredTransform; 
    if(firstTransform.a == 0 && firstTransform.b == 1.0 && firstTransform.c == -1.0 && firstTransform.d == 0) {FirstAssetOrientation_= UIImageOrientationRight; isFirstAssetPortrait_ = YES;} 
    if(firstTransform.a == 0 && firstTransform.b == -1.0 && firstTransform.c == 1.0 && firstTransform.d == 0) {FirstAssetOrientation_ = UIImageOrientationLeft; isFirstAssetPortrait_ = YES;} 
    if(firstTransform.a == 1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == 1.0) {FirstAssetOrientation_ = UIImageOrientationUp;} 
    if(firstTransform.a == -1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == -1.0) {FirstAssetOrientation_ = UIImageOrientationDown;} 
    CGFloat FirstAssetScaleToFitRatio = 320.0/FirstAssetTrack.naturalSize.width; 
    if(isFirstAssetPortrait_){ 
     FirstAssetScaleToFitRatio = 320.0/FirstAssetTrack.naturalSize.height; 
     CGAffineTransform FirstAssetScaleFactor = CGAffineTransformMakeScale(FirstAssetScaleToFitRatio,FirstAssetScaleToFitRatio); 
     [FirstlayerInstruction setTransform:CGAffineTransformConcat(FirstAssetTrack.preferredTransform, FirstAssetScaleFactor) atTime:kCMTimeZero]; 
    }else{ 
     CGAffineTransform FirstAssetScaleFactor = CGAffineTransformMakeScale(FirstAssetScaleToFitRatio,FirstAssetScaleToFitRatio); 
     [FirstlayerInstruction setTransform:CGAffineTransformConcat(CGAffineTransformConcat(FirstAssetTrack.preferredTransform, FirstAssetScaleFactor),CGAffineTransformMakeTranslation(0, 160)) atTime:kCMTimeZero]; 
    } 
    [FirstlayerInstruction setOpacity:0.0 atTime:firstAsset.duration]; 

    AVMutableVideoCompositionLayerInstruction *SecondlayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:secondTrack]; 
    AVAssetTrack *SecondAssetTrack = [[secondAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    UIImageOrientation SecondAssetOrientation_ = UIImageOrientationUp; 
    BOOL isSecondAssetPortrait_ = NO; 
    CGAffineTransform secondTransform = SecondAssetTrack.preferredTransform; 
    if(secondTransform.a == 0 && secondTransform.b == 1.0 && secondTransform.c == -1.0 && secondTransform.d == 0) {SecondAssetOrientation_= UIImageOrientationRight; isSecondAssetPortrait_ = YES;} 
    if(secondTransform.a == 0 && secondTransform.b == -1.0 && secondTransform.c == 1.0 && secondTransform.d == 0) {SecondAssetOrientation_ = UIImageOrientationLeft; isSecondAssetPortrait_ = YES;} 
    if(secondTransform.a == 1.0 && secondTransform.b == 0 && secondTransform.c == 0 && secondTransform.d == 1.0) {SecondAssetOrientation_ = UIImageOrientationUp;} 
    if(secondTransform.a == -1.0 && secondTransform.b == 0 && secondTransform.c == 0 && secondTransform.d == -1.0) {SecondAssetOrientation_ = UIImageOrientationDown;} 
    CGFloat SecondAssetScaleToFitRatio = 320.0/SecondAssetTrack.naturalSize.width; 
    if(isSecondAssetPortrait_){ 
     SecondAssetScaleToFitRatio = 320.0/SecondAssetTrack.naturalSize.height; 
     CGAffineTransform SecondAssetScaleFactor = CGAffineTransformMakeScale(SecondAssetScaleToFitRatio,SecondAssetScaleToFitRatio); 
     [SecondlayerInstruction setTransform:CGAffineTransformConcat(SecondAssetTrack.preferredTransform, SecondAssetScaleFactor) atTime:firstAsset.duration]; 
    }else{ 
     ; 
     CGAffineTransform SecondAssetScaleFactor = CGAffineTransformMakeScale(SecondAssetScaleToFitRatio,SecondAssetScaleToFitRatio); 
     [SecondlayerInstruction setTransform:CGAffineTransformConcat(CGAffineTransformConcat(SecondAssetTrack.preferredTransform, SecondAssetScaleFactor),CGAffineTransformMakeTranslation(0, 160)) atTime:firstAsset.duration]; 
    } 


    MainInstruction.layerInstructions = [NSArray arrayWithObjects:FirstlayerInstruction,SecondlayerInstruction,nil];; 

    AVMutableVideoComposition *MainCompositionInst = [AVMutableVideoComposition videoComposition]; 
    MainCompositionInst.instructions = [NSArray arrayWithObject:MainInstruction]; 
    MainCompositionInst.frameDuration = CMTimeMake(1, 30); 
    MainCompositionInst.renderSize = CGSizeMake(320.0, 480.0); 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]]; 

    NSURL *url = [NSURL fileURLWithPath:myPathDocs]; 

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality]; 
    exporter.outputURL=url; 
    exporter.outputFileType = AVFileTypeQuickTimeMovie; 
    exporter.videoComposition = MainCompositionInst; 
    exporter.shouldOptimizeForNetworkUse = YES; 
    [exporter exportAsynchronouslyWithCompletionHandler:^ 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self exportDidFinish:exporter]; 
     }); 
    }]; 
} 

}

回答

0

嘗試添加以下代碼:

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

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

那麼你可以使用preferredVolumeAVMutableCompositionTrack的財產,要纏得audioTrack量。

祝你好運