Video not always exported to Camera Roll: NSFileManager's removeItemAtPath non-blocking?

时间:2015-06-25 18:34:05

标签: ios swift video avfoundation pbjvision

After reading several tutorials like this and looking at other code exporting videos, we still can't resolve an issue.

Sometimes a new video gets exported to the Camera Roll, and sometimes it doesn't. We can't even reproduce the problem consistently.

The only issue we can imagine is if NSFileManager.defaultManager().removeItemAtPath is not a blocking call, but no documentation suggests it's asynchronous, so we assume it's not the case.

Each time, the "Saved video" println inside the writeVideoAtPathToSavedPhotosAlbum closure gets called, suggesting the video was successfully written to the Camera Roll, but we don't see the video there.

Suggestions on how to troubleshoot?

Code:

        // -- Get path
        let fileName = "/editedVideo.mp4"
        let allPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        let docsPath = allPaths[0] as! NSString
        let exportPath = docsPath.stringByAppendingFormat(fileName)
        let exportUrl = NSURL.fileURLWithPath(exportPath as String)!

        println(exportPath)

        // -- Remove old video?
        if NSFileManager.defaultManager().fileExistsAtPath(exportPath as String) {
            println("Deleting existing file\n")
            NSFileManager.defaultManager().removeItemAtPath(exportPath as String, error: nil)
        }

        // -- Create exporter
        let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
        exporter.videoComposition = mutableComposition
        exporter.outputFileType = AVFileTypeMPEG4
        exporter.outputURL = exportUrl
        exporter.shouldOptimizeForNetworkUse = true

        // -- Export video
        exporter.exportAsynchronouslyWithCompletionHandler({
            self.exportDidFinish(exporter)
        })
    }


    func exportDidFinish(exporter: AVAssetExportSession) {
        println("Finished exporting video!")

        // Write out video to photo album
        let assetLibrary = ALAssetsLibrary()
        assetLibrary.writeVideoAtPathToSavedPhotosAlbum(exporter.outputURL, completionBlock: {(url: NSURL!, error: NSError!) in
            println("Saved video \(exporter.outputURL)")

            if (error != nil) {
                println("Error saving video")
            }
        })
    } 

1 个答案:

答案 0 :(得分:1)

一些可能有助于解决问题的建议:

  1. 检查视频是否与库here

    一样有效/兼容
    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:videoURL])
    {
        [library writeVideoAtPathToSavedPhotosAlbum:videoURL
                                    completionBlock:^(NSURL *assetURL, NSError *error){}
        ];
    } 
    
  2. 确保传回的资产网址不是引用here

    的nil
    if(error){
        NSLog(@"Error: Domain = %@, Code = %@", [error domain], [error localizedDescription]);
    } else if(assetURL == nil){
    
        //It's possible for writing to camera roll to fail, without receiving an error message, but assetURL will be nil
        //Happens when disk is (almost) full
        NSLog(@"Error saving to camera roll: no error message, but no url returned");
    
    } else {
        //remove temp file
        NSError *error;
        [[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error];
        if(error){
            NSLog(@"error: %@", [error localizedDescription]);
        }
    
    }
    
  3. 考虑使用PHPhotoLibrary来导出视频

    PHPhotoLibrary.sharedPhotoLibrary().performChanges({
        let assetRequest = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(videoURL)
        let assetPlaceholder = assetRequest.placeholderForCreatedAsset
    },
    completionHandler: { success, error in
        // check and handle error
        // do something with your asset local identifier
    })