5

Is it possible to copy a video file located at iOS photo library to our application's documents directory? I tried it using uiimagepickercontroller from where we get the NSUrl of the video file, then converting it into NSData and then writing it into the file. But unfortunately it is not working. I there any alternate method?

My intention is to load the video to OpenCV CvCapture.

4

1 に答える 1

0

Hey Isarathg this is classic use case of IOS devices. Which don't let you access any Photo Album assets directly using path value. To cross check my answer please just check FileExistsAtPath for your file like below -:

println(NSFileManager.defaultManager().fileExistsAtPath( urlvalue.path!))

O/P you will get => False

I also end up with this issue couple of days back After reading the whole IOS documentation. What I have figured it out "We can only access PhotoAlbum Assets if and only if we have PHImageManager session open". To cross check this statement please try below code -:

var currentVideofetch: PHFetchResult!
required init(coder aDecoder: NSCoder) {
    let options = PHFetchOptions()
    options.sortDescriptors = [
        NSSortDescriptor(key: "creationDate", ascending: true)
    ]
    currentVideofetch = PHAsset.fetchAssetsWithMediaType(.Video, options: options)
    super.init(coder: aDecoder)
}
func checkImageExists(){
let asset = self.currentVideofetch.objectAtIndex(1) as? PHAsset
}
if let checkedAsset = asset {
        PHImageManager.defaultManager().requestAVAssetForVideo(checkedAsset, options: nil, resultHandler: {[weak self](result: AVAsset!, audioMix: AVAudioMix!, info: [NSObject : AnyObject]!) in
            println(NSFileManager.defaultManager().fileExistsAtPath(self.urlvalue.path!))
            })
    }
O/P you will get => True

After opening the PHImageManager session and then when i tried accessing the video with the path. It worked fine. Also able to successfully copy all videos files to our local app directory using the relative path of videos in Photo Album.

If you need i can send you my implementation for this. But not sure if it is correct way or not. But working fine for me.

Second and most effective solution i found is using

AVAssetExportSession

It works like a charm. My implementation is as follows -:

func importVideoToAppDir(videoURL: NSURL, videoFinalPath: NSURL, handler: ((NSURL?) -> Void)?) {

    var assetDuration:  CMTime!
    var asset: AVAsset!

    asset = AVAsset.assetWithURL(videoURL) as! AVAsset
    assetDuration = asset!.duration
    if (DirOperations.DeleteIfExists(videoTempPath) &&  DirOperations.DeleteIfExists(videoFinalPath)) {
        let startTime = kCMTimeZero
        let assetDurationSeconds = CMTimeGetSeconds(self.asset!.duration)
        var range: CMTimeRange!
        if assetDurationSeconds > Float64(maxDuration) {
            let stopTime = CMTimeMakeWithSeconds(Float64(maxDuration), 1)
            range = CMTimeRangeFromTimeToTime(startTime, stopTime)
            } else {
                let stopTime = CMTimeMakeWithSeconds(assetDurationSeconds, 1)
                range = CMTimeRangeFromTimeToTime(startTime, stopTime)
            }
            var exporter :AVAssetExportSession = AVAssetExportSession(asset: self.asset, presetName: AVAssetExportPresetHighestQuality)
            exporter.outputURL = videoFinalPath
            exporter.outputFileType = AVFileTypeQuickTimeMovie
            exporter.timeRange = range
            exporter.exportAsynchronouslyWithCompletionHandler { () -> Void in
                switch exporter.status {
                    case  AVAssetExportSessionStatus.Failed:
                    println("failed import video: \(exporter.error)")
                    handler?(nil)
                    case AVAssetExportSessionStatus.Cancelled:
                    println("cancelled import video: \(exporter.error)")
                    handler?(nil)
                    default:
                    println("completed import video")
                    println(videoFinalPath)
                    handler?(videoFinalPath)

                }
            }
    }
}

   func DeleteIfExists(path: NSURL) -> Bool {
        var deleted = true
        var error: NSError?
        if (NSFileManager.defaultManager().fileExistsAtPath(path.path!)) {
            deleted = NSFileManager.defaultManager().removeItemAtPath(path.path!, error: &error)
        }
        return deleted
    }

Hope it helps.

于 2015-06-26T14:18:47.447 に答える