Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift / iOS 10 : How to download a VIDEO and store within the app

I'm new to SWIFT/Programming & I couldn't find an answer on my question, that's why I'm gonna give it a try here:

  1. HOW Do I download a video (mp4) from an URL and store it within the app**

  2. HOW Do I display the video then in a container**

I've already found this topic:

Swift - Downloading video with downloadTaskWithURL

But in my case, I wouldn't want the video to be safed in the camera-roll. Just within the app.

Thanks for any kind of help/hint !

like image 935
Julian M Avatar asked Nov 06 '16 13:11

Julian M


1 Answers

You can use URLSession's dataTask or downloadTask to download any file from url(if it's downloadble)

Here's the way to use dataTask for downloading:

    let videoUrl = "Some video url"

        let docsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

    let destinationUrl = docsUrl.appendingPathComponent("MyFileSaveName.mp4")
    if(FileManager().fileExists(atPath: destinationUrl.path)){
            print("\n\nfile already exists\n\n")
        }
        else{
            //DispatchQueue.global(qos: .background).async {
                var request = URLRequest(url: URL(string: videoUrl)!)
                request.httpMethod = "GET"
                _ = session.dataTask(with: request, completionHandler: { (data, response, error) in
    if(error != nil){
        print("\n\nsome error occured\n\n")
        return
    }
    if let response = response as? HTTPURLResponse{
        if response.statusCode == 200{
            DispatchQueue.main.async {
                if let data = data{
                    if let _ = try? data.write(to: destinationUrl, options: Data.WritingOptions.atomic){
                        print("\n\nurl data written\n\n")
                    }
                    else{
                        print("\n\nerror again\n\n")
                    }
                }//end if let data
            }//end dispatch main
        }//end if let response.status
    }
}).resume()
            //}//end dispatch global
        }//end outer else

Now to play the saved file:

class MyViewController: UIViewController {
 override func viewDidLoad() {
let baseUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

    let assetUrl = baseUrl.appendingPathComponent("MyFileSaveName.mp4")

    let url = assetUrl
    print(url)
    let avAssest = AVAsset(url: url)
    let playerItem = AVPlayerItem(asset: avAssest)


    let player = AVPlayer(playerItem: playerItem)

    let playerViewController = AVPlayerViewController()
    playerViewController.player = player

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

However, most sites do not provide a direct dwonloadable link for video. You can get that link by playing the video in a UIWebView and register this following observer to get that link:

NotificationCenter.default.addObserver(self, selector: #selector(videoPlayedInWebView), name: NSNotification.Name(rawValue: "AVPlayerItemBecameCurrentNotification"), object: nil)

 @objc func videoPlayedInWebView(aNotification: NSNotification) {
    if let playerItem: AVPlayerItem = aNotification.object as? AVPlayerItem{
        let asset: AVURLAsset = playerItem.asset as! AVURLAsset
        var downloadebaleVideoUrl = asset.url
        print(downloadebaleVideoUrl)
 }
}

Here "downloadebaleVideoUrl" is the link that will be generated once the video plays in the webview. If you have any questions, feel free to ask. Note: This is will work only for sites that have mp4 files. 'HLS' streams won't be downloaded with this method. For that you can refer to this following answer: https://stackoverflow.com/a/54493233/10758374

Edit: this works only with UIWebView and it won't work with WKWebView.

like image 196
AfnanAhmad Avatar answered Sep 22 '22 01:09

AfnanAhmad