2013-08-30 43 views
2

在我的應用程序,我錄製的視頻小和將它們添加到一個NSMutableArrayAVAsset讓我保持的東西已被抓獲的紀錄。當用戶按下按鈕合併它們時,最終結果只是拍攝的第一個視頻(例如,如果拍攝了三個短視頻,則合併後的最終結果只是第一個視頻,其他視頻不會出現)。我上的NSMutableArray的迭代和拼接在一起的視頻代碼是在這裏:合併在一起的視頻(AVFoundation)

if (self.capturedVideos.count != 0) {   
    //Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack. 
    AVMutableComposition* mixComposition = [[AVMutableComposition alloc] init]; 

    for (AVAsset *asset in self.capturedVideos) { 
     //check if the video is the first one captures so that it is placed at time 0. 
     if ([self.capturedVideos indexOfObject:asset] == 0) { 
      AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
      [firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil]; 
      previousAsset = asset; 
     } else{ 
      AVMutableCompositionTrack *track = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
      [track insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:previousAsset.duration error:nil]; 
      previousAsset = asset; 
     } 
    } 

    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]; 
    // 5 - Create exporter 
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality]; 
    exporter.outputURL=url; 
    exporter.outputFileType = AVFileTypeQuickTimeMovie; 
    exporter.shouldOptimizeForNetworkUse = YES; 
    [exporter exportAsynchronouslyWithCompletionHandler:^{ 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self exportDidFinish:exporter]; 
     }); 
    }]; 
} 

什麼是後for循環用於導出視頻被保存在相機膠捲。那麼我的錯誤在哪裏?持續時間是正確的(所以沒有重疊)。然而,我懷疑的東西。有一個實例變量,我在@implementation後面添加了大括號,它是previousAsset,跟蹤之前添加的資源,從而知道下一個放置的位置。它的類AVAsset,所以我沒有初始化它,因爲當我嘗試它是顯示我一個錯誤。

previousAsset = [[AVAsset alloc] init];

+0

試試這個: - https://stackoverflow.com/questions/37210154/IOS合併,二,視頻成單視頻文件與音頻/ 45296947#45296947 – Datt1994

回答

3

這將正常工作

 AVMutableComposition *mainComposition = [[AVMutableComposition alloc] init]; 
     AVMutableCompositionTrack *compositionVideoTrack = [mainComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 


     AVMutableCompositionTrack *soundtrackTrack = [mainComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
     CMTime insertTime = kCMTimeZero; 

     for (AVAsset *videoAsset in assets) { 

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

      [soundtrackTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:insertTime error:nil]; 

      // Updating the insertTime for the next insert 
      insertTime = CMTimeAdd(insertTime, videoAsset.duration); 
     } 

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

     // Creating a full path and URL to the exported video 
     NSString *outputVideoPath = [documentsDirectory stringByAppendingPathComponent: 
           [NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]]; 

     // NSString *documentsDirectory = [paths objectAtIndex:0]; 
     NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent: 
         current_name]; 
     NSURL *outptVideoUrl = [NSURL fileURLWithPath:myPathDocs]; 
     AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mainComposition presetName:AVAssetExportPreset640x480]; 

     // Setting attributes of the exporter 
     exporter.outputURL=outptVideoUrl; 
     exporter.outputFileType =AVFileTypeMPEG4; //AVFileTypeQuickTimeMovie; 
     exporter.shouldOptimizeForNetworkUse = YES; 
     [exporter exportAsynchronouslyWithCompletionHandler:^{ 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       //completion(exporter); 
       [self exportDidFinish:exporter]; 
       // [self exportDidFinish:exporter:assets]; 
      }); 
     }]; 

這將正常工作..

0

斯威夫特版本

func merge(arrayVideos:[AVAsset], completion:@escaping (_ exporter: AVAssetExportSession) ->()) -> Void { 

    let mainComposition = AVMutableComposition() 
    let compositionVideoTrack = mainComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid) 
    compositionVideoTrack?.preferredTransform = CGAffineTransform(rotationAngle: .pi/2) 

    let soundtrackTrack = mainComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) 

    var insertTime = kCMTimeZero 

    for videoAsset in arrayVideos { 
    try! compositionVideoTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType: .video)[0], at: insertTime) 
    try! soundtrackTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType: .audio)[0], at: insertTime) 

    insertTime = CMTimeAdd(insertTime, videoAsset.duration) 
    } 

    let outputFileURL = URL(fileURLWithPath: NSTemporaryDirectory() + "merge.mp4") 

    let fileManager = FileManager() 
    fileManager.removeItemIfExisted(outputFileURL) 

    let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality) 

    exporter?.outputURL = outputFileURL 
    exporter?.outputFileType = AVFileType.mp4 
    exporter?.shouldOptimizeForNetworkUse = true 

    exporter?.exportAsynchronously { 
    DispatchQueue.main.async { 
     completion(exporter!) 
    } 
    } 
}