【问题标题】:AVAssetExportSession gives me AVFoundationErrorDomain Code=-11800AVAssetExportSession 给我 AVFoundationErrorDomain Code=-11800
【发布时间】:2019-12-14 21:42:19
【问题描述】:

我在 ios 13.3 的真实设备中面临同样的问题,它在 ios 13.2 模拟器中运行,但出现以下错误。

Error Domain=AVFoundationErrorDomain Code=-11800 "该操作可能 未完成” UserInfo={NSLocalizedFailureReason=未知错误 发生 (-17508), NSLocalizedDescription=操作不能 完成,NSUnderlyingError=0x2816d11d0 {错误 Domain=NSOSStatusErrorDomain Code=-17508 "(null)"}}

这是我想将 .mov 文件转换为 mp4 的代码。

class func encodeVideo(at videoURL: String, completionHandler: ((URL?, Error?) -> Void)?)  {  
    let avAsset = AVURLAsset(url: URL.init(fileURLWithPath: videoURL), options: nil)  

    let startDate = Date()  

    //Create Export session  
    guard let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) else {  
        completionHandler?(nil, nil)  
        return  
    }  

    //Creating temp path to save the converted video  
    let filename = "Video_\(Date().timeIntervalSince1970).mp4"  
      // Below Folder Path used tor getting directory path  
    let strfilePath = (FolderPath.temporaryDirectory.getDirectoryPath as NSString).appendingPathComponent(filename)  
    let filePath = URL.init(fileURLWithPath: strfilePath)  

    //Check if the file already exists then remove the previous file  
    if FileManager.default.fileExists(atPath: filePath.path) {  
        do {  
            try FileManager.default.removeItem(at: filePath)  
        } catch {  
            completionHandler?(nil, error)  
        }  
    }  

    exportSession.outputURL = filePath  
    exportSession.outputFileType = AVFileType.mp4  
    exportSession.shouldOptimizeForNetworkUse = true  
    let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)  
    let range = CMTimeRangeMake(start: start, duration: avAsset.duration)  
    exportSession.timeRange = range  

    exportSession.exportAsynchronously(completionHandler: {() -> Void in  
        switch exportSession.status {  
        case .failed:  
            print(exportSession.error ?? "NO ERROR")  
            completionHandler?(nil, exportSession.error)  
        case .cancelled:  
            print("Export canceled")  
            completionHandler?(nil, nil)  
        case .completed:  
            //Video conversion finished  
            let endDate = Date()  

            let time = endDate.timeIntervalSince(startDate)  
            print(time)  
            print("Successful!")  
            print(exportSession.outputURL ?? "NO OUTPUT URL")  
            completionHandler?(exportSession.outputURL, nil)  

            default: break  
        }  

    })  
}  

【问题讨论】:

    标签: swift avfoundation ios13 avassetexportsession


    【解决方案1】:
    let strfilePath = (FolderPath.temporaryDirectory.getDirectoryPath as NSString).appendingPathComponent(filename)  
    

    您不能直接存储在该文件夹中,但您需要将文件存储在子文件夹中,例如像这样:

    let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL
    
    let strfilePath = documentDirectoryURL.appendingPathComponent("Subfolder/filename.mp4") as URL  
    

    您可以进一步阅读article

    【讨论】:

    • 这不是我遇到同样问题的情况。
    【解决方案2】:

    最后,我通过使用 AVMutableComposition 而不是直接使用 AVURL 资产来解决我的问题。我在 AVMutableComposition 中添加音频和视频轨道。

    【讨论】:

      【解决方案3】:

      这是我用来将 .mov 转换为 .mp4 的代码

        var outputURL: URL!
      
         func exportVideo(key:String, inputurl: URL, presetName: String, outputFileType: AVFileType = .mp4, fileExtension: String = "mp4", then completion: @escaping (URL?) -> Void) {
      
              let asset = AVAsset(url: inputurl)
      
              outputURL = FileManager.default.temporaryDirectory.appendingPathComponent(key)
      
              if let session = AVAssetExportSession(asset: asset, presetName: presetName) {
                  session.outputURL = outputURL
                  session.outputFileType = outputFileType
      
                  session.shouldOptimizeForNetworkUse = true
                  session.exportAsynchronously {
                      switch session.status {
                      case .completed:
                          completion(self.outputURL)
                      case .cancelled:
                          debugPrint("Video export cancelled.")
                          completion(nil)
                      case .failed:
                          let errorMessage = session.error?.localizedDescription ?? "n/a"
                          debugPrint("Video export failed with error: \(errorMessage)")
                          completion(nil)
                      default:
                          break
                      }
                  }
              } else {
                  completion(nil)
              }
          }
      

      然后我调用这个函数来获取转换文件的输出URL并使用它

      exportVideo(key: key, inputurl: path, presetName: AVAssetExportPresetHighestQuality, outputFileType: .mp4, fileExtension: "mp4") { (outputURL) in 
      
          // do whatever with the file here
      }
      

      【讨论】:

        【解决方案4】:

        对于任何陷入这个令人沮丧的错误的人。使用 AVmutablecomposition 作为导出资产。

        剪辑视频的示例代码:

        let manager = FileManager.default
                guard let documentDirectory = try?  manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)  else { print("TRIM Failed to access directory")
                    return}
             
               
                
                
                let mediaType = "mp4"
                if mediaType == kUTTypeMovie as String || mediaType == "mp4" as String {
                       let asset = AVAsset(url:videoURL!)
                    let length = Float(asset.duration.value) / Float(asset.duration.timescale)
                       print("TRIM video length: \(length) seconds")
                    
               
                    let composition = AVMutableComposition()
                    let audioTrack: AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)!
                    let videoTrack: AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)!
                    
             
                    var outURL_speed=documentDirectory.appendingPathComponent("output")
                    var outputURL = documentDirectory.appendingPathComponent("output")
                    
                            do {
                                
                             
                                try audioTrack.insertTimeRange(CMTimeRangeFromTimeToTime(start: self.startTime, end: self.endTime), of: asset.tracks(withMediaType: AVMediaType.audio)[0], at: CMTime.zero)
                                try videoTrack.insertTimeRange(CMTimeRangeFromTimeToTime(start: self.startTime, end: self.endTime), of: asset.tracks(withMediaType: AVMediaType.video)[0], at: CMTime.zero)
                             
                                try manager.createDirectory(at: outputURL, withIntermediateDirectories: true, attributes: nil)
                                outputURL = outputURL.appendingPathComponent("preVideo-\(self.postID).\(mediaType)")
                                outURL_speed = outURL_speed.appendingPathComponent("Video-\(self.postID).\(mediaType)")
                                print("TRIM output dir: \(outputURL)")
                            }catch let error {
                                print(error)
                            }
        
                    _ = try? manager.removeItem(at: outputURL)
                    
                    
                
                    
                    guard let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else {return}
                    
                    exportSession.outputURL = outputURL
                    exportSession.shouldOptimizeForNetworkUse = true
                    exportSession.outputFileType = .mp4
                    let timeRange = CMTimeRange(start: self.startTime, end: self.endTime)
                    exportSession.timeRange = timeRange
                    
                    exportSession.exportAsynchronously{
                        switch exportSession.status {
                        case .completed:
                            print("TRIM exported at \(outputURL)")
                            self.changeSpeed(url: outputURL,outUrl:outURL_speed)
                        case .failed:
                            print("TRIM failed \(exportSession.error)")
        
                        case .cancelled:
                            print("TRIM cancelled \(exportSession.error)")
        
                        default: break
                        }
                    }
        

        【讨论】:

          猜你喜欢
          • 2019-11-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-09
          • 1970-01-01
          • 2018-12-16
          • 2017-07-09
          • 1970-01-01
          相关资源
          最近更新 更多