2017-09-13 115 views
1

我使用此扩展名将视频文件从AVAsset保存到tmp文件夹。问题是,当我使用AVAssetExportPresetHighestQuality类型的视频文件无法由于这个原因,保存:AVAssetExportPreset类型的AVAssetExportSession问题

错误域= AVFoundationErrorDomain代码= -11800“的操作可能 无法完成”的UserInfo = {NSUnderlyingError = {0x1748482e0错误 域= NSOSStatusErrorDomain代码= -12780 “(空)”}, NSLocalizedFailureReason =出现未知错误(-12780), NSLocalizedDescription =操作无法完成}

还有些时候,甚至当我我正在使用AVAssetExportPresetHighestQuality它ves视频,但以随机顺序。

extension AVAsset { 

    func write(to url: URL, success: @escaping() ->(), failure: @escaping (Error) ->()) { 
     guard let exportSession = AVAssetExportSession(asset: self, presetName: AVAssetExportPresetMediumQuality) else { 
      let error = NSError(domain: "domain", code: 0, userInfo: nil) 
      failure(error) 

      return 
     } 

     exportSession.outputFileType = AVFileTypeMPEG4 
     exportSession.outputURL = url 

     exportSession.exportAsynchronously { 
      switch exportSession.status { 
      case .completed: 
       success() 
      case .unknown, .waiting, .exporting, .failed, .cancelled: 
       let error = NSError(domain: "domain", code: 0, userInfo: nil) 
       failure(error) 
      } 
     } 
    } 
} 

回答

1

此问题与AVAsset组件的长度错误有关。由于某些原因,AVAsset曲目的视频和音频曲目的持续时间不同,这是主要问题。

要解决此问题,我使用了AVAsset的自定义扩展。此功能将基于视频和音频轨道创建新的AVAsset,其条件将修复持续时间问题。因此从normalizingMediaDuration()获得的AVAsset可以成功导出。

extension AVAsset { 
    func normalizingMediaDuration() -> AVAsset? { 
     let mixComposition : AVMutableComposition = AVMutableComposition() 
     var mutableCompositionVideoTrack : [AVMutableCompositionTrack] = [] 
     var mutableCompositionAudioTrack : [AVMutableCompositionTrack] = [] 
     let totalVideoCompositionInstruction : AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction() 

     guard let video = tracks(withMediaType: AVMediaTypeVideo).first else { 
      return nil 
     } 

     guard let audio = tracks(withMediaType: AVMediaTypeAudio).first else { 
      return nil 
     } 

     mutableCompositionVideoTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)) 
     mutableCompositionAudioTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)) 

     let duration = video.timeRange.duration.seconds > audio.timeRange.duration.seconds ? audio.timeRange.duration : video.timeRange.duration 

     do{ 
      try mutableCompositionVideoTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero,duration), of: video, at: kCMTimeZero) 
      try mutableCompositionAudioTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, duration), of: audio, at: kCMTimeZero) 
     }catch{ 
      return nil 
     } 

     totalVideoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero,duration) 

     return mixComposition 
    } 
}