skamedly
skamedly

Reputation: 41

AVPlayer & video from documents directory

I've been working on a small project that involves downloading a video file from a web server, copying said file to the documents directory and then playing it via AVPlayer.

Downloading the file to the documents directory hasn't been an issue. I'm able to download the file and save it without issue. However, when it comes to loading the file into AVPlayer, and in doing that I'm playing it in an instance of AVPlayerViewController, the vide controller pops up as it should, but video doesn't load.

I realize that when testing in the simulator the documents directory changes each time you rebuild the project. Which is why I check to see if the file is present before I play, and though I know the file is present, it still refuses to play.

Here is what my player code looks like:

     let fileName = downloadURL.characters.split("/").map(String.init).last as String!
        let fileNameHD = downloadURLHD.characters.split("/").map(String.init).last as String!
        let downloadFilePath = getDocumentsDirectory() + "/" + "\(fileNameHD)"

        let checkValidation = NSFileManager.defaultManager()

        if checkValidation.fileExistsAtPath(downloadFilePath){
            print("video found")
        }

        let videoFile = NSURL(string:downloadFilePath)
        let player = AVPlayer(URL: videoFile!)
        let playerController = AVPlayerViewController()
        playerController.player = player
        playerController.view.frame = self.view.frame
        player.play()
        self.presentViewController(playerController, animated: true) {
            playerController.player!.play()
        }

Upvotes: 1

Views: 3576

Answers (3)

Asad Mehmood
Asad Mehmood

Reputation: 359

func listVideos() -> [URL] {
    let fileManager = FileManager.default
    let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

    let files = try? fileManager.contentsOfDirectory(
        at: documentDirectory,
        includingPropertiesForKeys: nil,
        options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles]
    ).filter {
        [".mp4", ".mkv"].contains($0.pathExtension.lowercased())
    }

    return files ?? []
}

And Then Play Video Like this I am only playing first URL

let videosURLs = self.listVideos()
    
    let player = AVPlayer(url: videosURLs[0])
    let playerViewController = AVPlayerViewController()
    playerViewController.player = player
    present(playerViewController, animated: true) { () -> Void in
         player.play()
    }

Upvotes: 0

Mandeep Singh
Mandeep Singh

Reputation: 2855

Every time when we rebuild the application Our Document Directory Path change.

So you can't play the video from the old document directory path. So instead of that you have to save the last path component of your URL. Like your document directory url look like this after downloaded the video on this path:-

 let videoURL = "/var/mobile/Containers/Data/Application/1F6CDF42-3796-4153-B1E8-50D09D7F5894/Documents/2019_02_20_16_52_47-video.mp4"
 var videoPath = ""
 if let url = videoURL {
   videoPath = url.lastPathComponent
 }
print(videoPath)
 // It will print the last path of your video url: - "2019_02_20_16_52_47-video.mp4"

Now save this path either in the Core Database or Sqlite or User Defaults where ever you want. Then if you want to play the video again. So you have to get this path from where you save it.

 Note:- In Below function you have to pass the last path component of your video. How to call this function.
 func playVideo() {
     self.startVideoFrom(videoPath:"2019_02_20_16_52_47-video.mp4")
 }

 // Play Video from path
func startVideoFrom(videoPath: String) {

    let outputMineURL = self.createNewPath(lastPath: videoPath)
    let player = AVPlayer(url: outputMineURL)
    let playerViewController = AVPlayerViewController()
    playerViewController.player = player
    self.present(playerViewController, animated: true) {
      playerViewController.player!.play()
    }
}

   /// Generate the new document directory path everytime when you rebuild the app and you have to append the last component of your URL.
  func createNewPath(lastPath: String) -> URL {
    let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!

    let destination = URL(fileURLWithPath: String(format: "%@/%@", documentsDirectory,lastPath))
    return destination
  }

For more reference, you can see this question:-        https://stackoverflow.com/q/47864143/5665836

Upvotes: 2

Ketan Parmar
Ketan Parmar

Reputation: 27438

Try AVPlayer instead of AVPlayerViewController like,

let videoURL = NSURL(string: "your url string")
let player = AVPlayer(URL: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
player.play()

And import AVKit, import AVFoundation.

OR With viewController like this,

 let player = AVPlayer(URL: url)
let playerController = AVPlayerViewController()

playerController.player = player
self.addChildViewController(playerController)
self.view.addSubview(playerController.view)
playerController.view.frame = self.view.frame

player.play()  

Upvotes: 0

Related Questions