使用AVFoundations拼接时会丢失一些视频

问题描述

我正在尝试使用AVFoundation合并多个视频。当我仅添加两个视频时,效果很好。但是,当我尝试添加3个视频时,第二个视频轨道为空,但是导出的视频的总时长是正确的。

这是我的示例代码:

添加视频的代码:

func addVideo(videoAsset: AVAsset,isLast: Bool = false)
{
    // Add video track
    guard let videoTrack = self.mixComposition.addMutableTrack(
       withMediaType: .video,preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
       else { return }
        
    do
    {
        try videoTrack.insertTimeRange(
          CMTimeRangeMake(start: .zero,duration: videoAsset.duration),of: videoAsset.tracks(withMediaType: .video)[0],at: totalVideoTrackDuration)
            
          // Add instruction for this track
          // video helper fixes the video orientation 
          let instruction = VideoHelper.videoCompositionInstruction(videoTrack,asset: videoAsset)
            
          if !isLast
          {
             // hide this clip when its done rendering
             instruction.setOpacity(0.0,at: videoAsset.duration)
          }
            
          // add to layer instruction
          self.instructions.append(instruction)
            
          // get the sum of all added track durations
          self.totalVideoTrackDuration = CMTimeAdd(self.totalVideoTrackDuration,videoAsset.duration)
      }
            
      catch
      {
          print("Failed to load track")
          return
      }
}

以下是导出视频的代码:

func export()
{
   // 6
   let mainInstruction = AVMutableVideoCompositionInstruction()
        
    // set time range
    mainInstruction.timeRange = CMTimeRangeMake(   
       start: .zero,duration: self.totalVideoTrackDuration
    )
        
    
    mainInstruction.layerInstructions = self.instructions
        
    let mainComposition = AVMutableVideoComposition()
    mainComposition.instructions = [mainInstruction]
    mainComposition.frameDuration = CMTimeMake(value: 1,timescale: self.timeScale)
    mainComposition.renderSize = self.videoSize
        
    guard let documentDirectory = FileManager.default.urls(
       for: .documentDirectory,in: .userDomainMask).first
       else { return }
        
        // file name
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .long
    dateFormatter.timeStyle = .short
    let date = Date().format(format: "mm-dd-yy-HH-mm-ss")!
    let url = documentDirectory.appendingPathComponent("mergeVideo-\(date).mov")
        
    guard let exporter = AVAssetExportSession(
       asset: self.mixComposition,presetName: AVAssetExportPresetHighestQuality)
       else { return }
        
    exporter.outputURL = url
    exporter.outputFileType = AVFileType.mov
    exporter.shouldOptimizeForNetworkUse = true
    exporter.videoComposition = mainComposition
     
    exporter.exportAsynchronously {
            
    PHPhotoLibrary.shared().performChanges({ 
       PHAssetChangeRequest.
          creationRequestForAssetFromVideo(
            atFileURL: exporter.outputURL!)
          }){ 

          saved,error in
          
             if saved 
             {
                print("Export successful")
             } 
             else
             {
                print("video erro: \(error)")
             }
        }
    }
}

这是我调用addVideo函数的方式:

// 4-second video
self.addVideo(videoAsset: asset1) 

// 3-second video
self.addVideo(videoAsset: asset2) 

// 4-second video
self.addVideo(videoAsset: asset3,isLast: true)

// export
self.export()

// the total duration of the exported video is 11 seconds. But the middle part,is blank.

解决方法

原来有问题的行是:

if !isLast
{
   // hide this clip when its done rendering
   instruction.setOpacity(0.0,at: videoAsset.duration)
}

// get the sum of all added track durations
self.totalVideoTrackDuration = CMTimeAdd(self.totalVideoTrackDuration,videoAsset.duration)

应该是:

// get the sum of all added track durations
self.totalVideoTrackDuration = CMTimeAdd(self.totalVideoTrackDuration,videoAsset.duration)

if !isLast
{
   instruction.setOpacity(0.0,at: self.totalVideoTrackDuration)
}

setOpacity的文档有些混乱。我以为at参数是该特定视频时间范围内的时间。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...