merging videos together (AVFoundation)

前端 未结 4 2122
心在旅途
心在旅途 2021-02-06 18:17

In my app, I\'m recording small videos and adding them into an NSMutableArray as AVAsset so that i keep record of what has been captured. when the user

相关标签:
4条回答
  • 2021-02-06 18:47

    updated @brenoxp's answer for Swift 5.1

    func merge(arrayVideos:[AVAsset], completion:@escaping (URL?, Error?) -> ()) {
    
      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 = CMTime.zero
    
      for videoAsset in arrayVideos {
        try! compositionVideoTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.duration), of: videoAsset.tracks(withMediaType: .video)[0], at: insertTime)
        try! soundtrackTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: 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()
      try? fileManager.removeItem(at: outputFileURL)
    
      let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)
    
      exporter?.outputURL = outputFileURL
      exporter?.outputFileType = AVFileType.mp4
      exporter?.shouldOptimizeForNetworkUse = true
    
      exporter?.exportAsynchronously {
        if let url = exporter?.outputURL{
            completion(url, nil)
        }
        if let error = exporter?.error {
            completion(nil, error)
        }
      }
    }
    
    0 讨论(0)
  • 2021-02-06 18:57

    This will work fine

          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];
              });
          }];
    

    this will work fine..

    0 讨论(0)
  • 2021-02-06 19:00

    There is a great example project on Git Hub that is a really good starting point for how to do this in a more reusable way within an app

    https://github.com/khoavd-dev/MergeVideos/blob/master/MergeVideos/VideoManager/KVVideoManager.swift

    0 讨论(0)
  • 2021-02-06 19:01

    Swift version

    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!)
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题