0
votes

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.

1
Please post some code. What have you tried?onnoweb
The first line when clicked shows my code but I'll try to edit my post so it's visible immediately. New to stackoverflow and posting pictures.Cornelius N.

1 Answers

0
votes

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()
            }
        }
    }
}