Video not always exported to Camera Roll: NSFileMa

2019-07-10 06:05发布

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条回答
虎瘦雄心在
2楼-- · 2019-07-10 06:55

A few suggestion that may help resolve your issue:

  1. Check that the video is valid/compatible with the library as done here

    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:videoURL])
    {
        [library writeVideoAtPathToSavedPhotosAlbum:videoURL
                                    completionBlock:^(NSURL *assetURL, NSError *error){}
        ];
    } 
    
  2. ensure that the asset url passed back is not nil as referenced here

    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. consider using the PHPhotoLibrary instead for exporting video

    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
    })
    
查看更多
登录 后发表回答