Cornelius N.
Cornelius N.

Reputation: 29

How to save video to app's directory and playback in view controller?

I'm trying to save a video in my app directory and then play it back in my view controller. I'm having an issue with saving and making the path. Can anyone help?

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        // Save the video to the app directory
        let videoURL = info[UIImagePickerControllerMediaURL] as! NSURL
        let videoData = NSData(contentsOf: videoURL as URL)
        let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
        let documentsDirectory: AnyObject = paths[0] as AnyObject
        let dataPath = documentsDirectory.appendingPathComponent("/vid1.mp4")

        videoData?.write(toFile: dataPath, atomically: false)
        self.dismiss(animated: true, completion: nil)

}

@IBAction func playVideoAction(_ sender: Any)
{
    let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
    let documentsDirectory: AnyObject = paths[0] as AnyObject
    let dataPath = documentsDirectory.appendingPathComponent("/vid1.mp4")

    let videoAsset = (AVAsset(url: NSURL(fileURLWithPath: dataPath) as URL))
    let playerItem = AVPlayerItem(asset: videoAsset)

    let player = AVPlayer(playerItem: playerItem)
    let playerViewController = AVPlayerViewController()
    playerViewController.player = player

    self.present(playerViewController, animated: true)
    {
        playerViewController.player!.play()
    }
}

how to save video file into document directory

I've used code from this link but with the update to xcode 8/swift 3 it is not as helpful. Been stuck on this problem for awhile now.

Upvotes: 0

Views: 688

Answers (1)

StephenG
StephenG

Reputation: 86

You want to use PHImageManager.requestExportSession(forVideo:options:). This will prepare the asset asynchronously (including downloading it if needed), and create an AVExportSession you can use to save the file. By specifying you want the original, and to passthrough the content (if possible) you should get the best quality video available.

var dataPath: URL {
    let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
    let documentsDirectory = URL(fileURLWithPath: paths[0])
    return documentsDirectory.appendingPathComponent("/vid1.mp4")
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    let url = info[UIImagePickerControllerReferenceURL] as! URL

    let assets = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
    let asset = assets.object(at: 0)
    let options = PHVideoRequestOptions()
    options.version = .original
    PHImageManager.default().requestExportSession(forVideo: asset, options: options, exportPreset: AVAssetExportPresetPassthrough) { (exportSession, info) in
        guard let session = exportSession else { return }
        session.outputURL = self.dataPath
        session.outputFileType = AVFileTypeMPEG4
        session.exportAsynchronously {
            DispatchQueue.main.async {
                self.dismiss(animated: true, completion: nil)
            }
        }
    }
}

If you didn't want to save to disk but just playback, you can use requestPlayerItem to get an AVPlayerItem you can use in your player:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    let url = info[UIImagePickerControllerReferenceURL] as! URL

    let assets = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
    let asset = assets.object(at: 0)
    let options = PHVideoRequestOptions()
    options.version = .original
    PHImageManager.default().requestPlayerItem(forVideo: asset, options: options) { (playerItem, info) in
        let player = AVPlayer(playerItem: playerItem)
        let playerViewController = AVPlayerViewController()
        playerViewController.player = player

        DispatchQueue.main.async {
            self.dismiss(animated: true, completion: nil)
            self.present(playerViewController, animated: true) {
                playerViewController.player!.play()
            }
        }
    }
}

Upvotes: 0

Related Questions