错误域= NSCocoaErrorDomain代码= -1“(null)”将.mov移动到相机胶卷时

时间:2017-07-11 08:20:01

标签: ios swift phphotolibrary

我将我的应用创建的.mov文件从文档文件夹移动到相机胶卷时遇到了一个奇怪的问题。一点背景:

该应用程序制作延时电影。它专门用于具有1200万像素4032x3024传感器的设备。它在应用程序的文档文件夹中创建了电影。电影可以保存为4k或HD。它们也可以保存为整个传感器的4:3宽高比电影,或传感器的16:9裁剪。如果用户希望将电影存储在设备的相机胶卷中,则可以设置该选项。 尝试将全尺寸电影(4032x3024)从应用的文档文件夹移动到相机胶卷时,我的问题存在。我收到这个错误:

  

错误域= NSCocoaErrorDomain代码= -1“(null)”

电影很好,它仍然位于文档的文件夹中。它无法复制到相机胶卷。如果我通过相同的代码执行相同的操作与任何其他大小,没有问题。一个4:3高清(1440x1080)工作正常,16:9高清(1920x1080)工作正常,16:9 4k(3880x2160)工作正常。这只是4:3 4k(4032x3024),当我试图移动它时会产生这个错误。

这是移动的代码:

PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: cameraRollURL!)

网址正常,因为它适用于其他尺寸。

2 个答案:

答案 0 :(得分:0)

当我从拉动方式切换为推入方式时,确实做到了这一点(从扭弯机一侧看)。

拉方法是当我有一个UIImage数组(从相机捕获)时,当准备好处理下一个图像时,它是feed writer。 推入方法是当我一个接一个UIImage(从相机捕获),并准备好处理下一个图像时供稿器。

不确定是什么原因。也许正在处理AVWritter调用之间的消息循环。

优势:如果捕获更长的视频,则您不会在UIImage数组中随时分配GB内存。

缺点:如果捕获速度太快,编写器可能没有准备好编写样本,因为可以实时处理,因此可以丢弃帧。

迅速4:

func initVideo(videoSettings: [String: Any]) -> (assetWriter: AVAssetWriter, writeInput: AVAssetWriterInput, bufferAdapter:AVAssetWriterInputPixelBufferAdaptor)? {

    if(FileManager.default.fileExists(atPath: ImagesToVideoUtils.tempPath)){
        guard (try? FileManager.default.removeItem(atPath: ImagesToVideoUtils.tempPath)) != nil else {
            print("remove path failed")
            return nil
        }
    }

    let assetWriter = try! AVAssetWriter(url: ImagesToVideoUtils.fileURL, fileType: AVFileType.mov)

    let writeInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: videoSettings)
    assert(assetWriter.canAdd(writeInput), "add failed")

    assetWriter.add(writeInput)
    let bufferAttributes:[String: Any] = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32ARGB)]
    let bufferAdapter = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: writeInput, sourcePixelBufferAttributes: bufferAttributes)

    return (assetWriter, writeInput, bufferAdapter)

}

func exportVideo_start(assetWriter: AVAssetWriter) -> (DispatchQueue) {

    assetWriter.startWriting()
    assetWriter.startSession(atSourceTime: CMTime.zero)

    let mediaInputQueue = DispatchQueue(label: "mediaInputQueue")

    return (mediaInputQueue)
}

func exportVideo_write(videoSettings: [String: Any], img: UIImage, assetWriter: AVAssetWriter, writeInput: AVAssetWriterInput, bufferAdapter:AVAssetWriterInputPixelBufferAdaptor, mediaInputQueue: DispatchQueue, timestamp: CMTime) {

    if (writeInput.isReadyForMoreMediaData){
        var sampleBuffer:CVPixelBuffer?
        autoreleasepool{
            sampleBuffer = self.newPixelBufferFrom(cgImage: img.cgImage!, videoSettings: videoSettings)
        }

        bufferAdapter.append(sampleBuffer!, withPresentationTime: timestamp)
        print("Adding frame at \(timestamp)")
    }
}

func exportVideo_end( assetWriter: AVAssetWriter, writeInput: AVAssetWriterInput) {

    writeInput.markAsFinished()
        assetWriter.finishWriting {
            DispatchQueue.main.sync {
                print("Finished writting")
                ImagesToVideoUtils.saveToCameraRoll(videoURL: ImagesToVideoUtils.fileURL)
            }
        }
}

答案 1 :(得分:0)

- (void)saveVideoPath:(NSString *)videoPath {
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), 
  dispatch_get_main_queue(), ^{
    NSURL *url = [NSURL fileURLWithPath:videoPath];
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
      [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
      if (success) {
        NSLog(@"succ");
      }
      if (error) {
        NSLog(@"%@",error);
      }
    }];
  });
}