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

Fis*_*les 10 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!)
Run Code Online (Sandbox Code Playgroud)

该URL正常,因为它可以很好地与其他大小一起使用.

ved*_*ano -1

当我从拉式方法切换到推式方法时,我确实解决了这个问题(从作者的角度来看)。

拉方法是当我有一个 UIImage 数组(从相机捕获)时,并在准备好处理下一个图像时提供写入器。推送方法是当我一张一张地拥有单个 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)
            }
        }
}
Run Code Online (Sandbox Code Playgroud)