Why I can't find a way to play video with AVPlayerViewController - ios

Hello everybody
I've been stuck with this problem with a whole day and actually I don't find a way to play a video file, I will explain a little bit what I did:
I have the following Url: [https://rapidresponse-us-oem-storage11.mios.com/storage/storage/store/8157061/archive?Key=833101823][1]
If you could see in that url I'm getting a video file .mp4 and I need to play this video, the following is the code that I'm using, first I'm saving the file and after that i'm trying to play in the AVPlayerViewController:
let store = self.eventDetail?.EventDetailStore!
let url = "https://" + (self.eventDetail?.EventDetailServerStorage)! + "/storage/storage/store/" + store! + "/archive?Key=" + self.EventKey!
if let videoUrl = NSURL(string: url) {
// create your document folder url
let documentsUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! as NSURL
// your destination file url
let destinationUrl = documentsUrl.URLByAppendingPathComponent(videoUrl.lastPathComponent!)
print(destinationUrl)
// check if it exists before downloading it
if NSFileManager().fileExistsAtPath(destinationUrl.path!) {
print("The file already exists at path")
let player = AVPlayer(URL: destinationUrl)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.presentViewController(playerViewController, animated: true) {
playerViewController.player!.play()
}
} else {
// if the file doesn't exist
// just download the data from your url
if let myAudioDataFromUrl = NSData(contentsOfURL: videoUrl){
// after downloading your data you need to save it to your destination url
if myAudioDataFromUrl.writeToURL(destinationUrl, atomically: true) {
print(destinationUrl)
let player = AVPlayer(URL: destinationUrl)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.presentViewController(playerViewController, animated: true) {
playerViewController.player!.play()
}
} else {
let alert = UIAlertController(title: "Alert", message: "An error occurred", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
}
When I run the code i get the Video Controller but don't reproduce anything like no file exist, but the I debug the code and the file seems to be saved.
I will appreciate any help with this problem
Base on your suggestions I Updated the code, but it isn't work yet:
//video
var player: AVPlayer!
var destinationUrl: NSURL? = nil
dispatch_async(dispatch_get_global_queue(priority, 0)) {
let store = self.eventDetail?.EventDetailStore!
let url = "https://" + (self.eventDetail?.EventDetailServerStorage)! + "/storage/storage/store/" + store! + "/archive?Key=" + self.EventKey!
if let videoUrl = NSURL(string: url) {
let documentsUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! as NSURL
// your destination file url
destinationUrl = documentsUrl.URLByAppendingPathComponent(videoUrl.lastPathComponent!)
if NSFileManager().fileExistsAtPath(destinationUrl!.path!) == false {
if let myAudioDataFromUrl = NSData(contentsOfURL: videoUrl){
myAudioDataFromUrl.writeToURL(destinationUrl!, atomically: true)
}
}
}
dispatch_async(dispatch_get_main_queue()) {
if(destinationUrl != nil){
player = AVPlayer(URL: destinationUrl!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.presentViewController(playerViewController, animated: true, completion: { () -> Void in playerViewController.player!.play() })
}
}
}
}

Your player is going out of scope and is being deallocated before your video has finished playing. Assign it to a class member to extend its lifetime.

You're missing the completion handler parameter:
self.presentViewController(playerViewController, animated: true) {
() in playerViewController.player!.play()
}

Related

How to play a video from file path in AVPlayer?

I have recorded a video from my app which saves the video in Photos app in iPhone. The file path of the video saved is:
file:///var/mobile/Containers/Data/Application/0A8F1D57-7336-4D52-8B64-928C381DBC4F/Documents/2022-04-14#14-26-59GMT+05:00ARVideo.mp4
How can I play the video from the file path in AVPlayer?
class SecondViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
playVideo()
}
private func playVideo() {
guard let filePath = Bundle.main.path(forResource: "file:///var/mobile/Containers/Data/Application/0A8F1D57-7336-4D52-8B64-928C381DBC4F/Documents/2022-04-14#14-26-59GMT+05:00ARVideo.mp4", ofType: "mp4") else { return}
let player = AVPlayer(url: URL(fileURLWithPath: filePath))
let vc = AVPlayerViewController()
vc.player = player
present(vc, animated: true)
}
}
import AVKit
func playVideo(){
let player = AVPlayer(url: URL(video url string) ?? URL(fileURLWithPath: "") )
let playerController = AVPlayerViewController()
playerController.player = player
self.addChild(playerController)
self.view.addSubview(playerController.view)
playerController.view.frame = self.view.frame
playerController.exitsFullScreenWhenPlaybackEnds = true
player.play()
}
class SecondViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
playVideo()
}
// if u have video in app directory/ document directory
private func playVideo() {
guard let url = URL(string: "file:///var/mobile/Containers/Data/Application/0A8F1D57-7336-4D52-8B64-928C381DBC4F/Documents/2022-04-14#14-26-59GMT+05:00ARVideo.mp4")
else {
print("url not exist")
return
}
let player = AVPlayer(url: url)
let vc = AVPlayerViewController()
vc.player = player
present(vc, animated: true)
}
// if u have video locally that u put in ur project then
private func playVideoFromLocal() {
guard let fileURL = Bundle.main.url(forResource: "file_example_MOV_480_700kB", withExtension: "mov") else {return}
let player = AVPlayer(url: fileURL)
let playerController = AVPlayerViewController()
let vc = AVPlayerViewController()
vc.player = player
present(vc, animated: true)
}
}
The path of the documents changes for the app each time it is launched, which changes the first part of the URL.
Try the following updated function to get the current location of the file:
private func playVideo() {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let playerItem = AVPlayerItem(url: URL(fileURLWithPath: documentsPath.appendingFormat("/your-video-name-here.mp4")))
let player = AVPlayer(playerItem: playerItem)
let vc = AVPlayerViewController()
vc.player = player
present(vc, animated: true)
}

Why can I play videos from my app bundle but not videos that were downloaded to the file system?

My objective is to read a video media I downloaded and stored to my iOS device file system. Unfortunately, the video player stalls with the following code:
#IBAction func playVideo(_ sender: UIButton) {
if let video = detailItem {
do {
let url = try FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
.appendingPathComponent(video.uuid)
debugPrint("url: \(url)")
// Create an AVPlayer, passing it the HTTP Live Streaming URL.
let player = AVPlayer(url: url)
// Create a new AVPlayerViewController and pass it a reference to the player.
let controller = AVPlayerViewController()
controller.player = player
// Modally present the player and call the player's play() method when complete.
present(controller, animated: true) {
player.play()
}
} catch {
print("Error: \(error)")
}
}
}
I assumed it was a video format problem and the codec of my video wasn't supported.
But, when I bundle the exact same video within the app, and switch to this code, everything works fine:
#IBAction func playVideo(_ sender: UIButton) {
let url = Bundle.main.url(forResource: "myvideo", withExtension: "mp4")!
// if let video = detailItem {
do {
// let url = try FileManager.default.url(for: .documentDirectory,
// in: .userDomainMask,
// appropriateFor: nil,
// create: false).appendingPathComponent(video.uuid)
debugPrint("url: \(url)")
// Create an AVPlayer, passing it the HTTP Live Streaming URL.
let player = AVPlayer(url: url)
// Create a new AVPlayerViewController and pass it a reference to the player.
let controller = AVPlayerViewController()
controller.player = player
// Modally present the player and call the player's play() method when complete.
present(controller, animated: true) {
player.play()
}
} catch {
print("Error: \(error)")
}
// }
}
I have no idea what I am missing here and could get some help. 🙏
EDIT: The code in charge of the download is here:
let downloadTask = URLSession.shared.downloadTask(with: video.downloadURL, completionHandler: { (tempPathURL, urlResponse, error) in
guard let tempPathURL = tempPathURL else {
return
}
do {
let documentsDirectoryURL = try FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
try FileManager.default.moveItem(at: tempPathURL, to: documentsDirectoryURL.appendingPathComponent(video.uuid))
} catch {
print("Error: \(error)")
}
})
downloadTask.resume()
You are using the wrong URL for playing downloaded video. Please check your code carefully and notice that you are using the documents directory URL for the player, instead of the actual video.
you should use fileURLWithPath to run video from app files, like this:
func PlayVideo() {
let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let player = AVPlayer(url: URL(fileURLWithPath: docPath).appendingPathComponent("IMG_3039.mp4"))
let controller = AVPlayerViewController()
controller.player = player
self.present(controller, animated: true) {
player.play()
}
}

videoplayer with download button in swift

I have a video player , and i want to add a download button.
How can i add this button to my video player or create a button to download that video.
tanks.
My code is :
let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(url: videoURL!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
Please check this below code, The download is proceeded in a background thread, so will not affect the UI.
class func downloadVideo(videoImageUrl:String)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let url=NSURL(string: videoImageUrl)
let urlData=NSData(contentsOfURL: url!)
if((urlData) != nil)
{
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let fileName = videoImageUrl.lastPathComponent //.stringByDeletingPathExtension
let filePath="\(documentsPath)/\(fileName)"
//saving is done on main thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
urlData?.writeToFile(filePath, atomically: true)
})
}
})
}
For calling above function in a button target.
Self.downloadVideo("https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")

Play video from data chunks

I received video from node sever in chunks of data. But video does not play in AVPlayer. Here is my code.
let videoUrl = http://staging.teemo.me/api/video/stream/sample12.MOV
playVideo(path:videoUrl, self)
func playVideo(path:String, controller:UIViewController){
let yourFinalVideoURL = path
try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: [])
if (yourFinalVideoURL != "") {
let player = AVPlayer(url: NSURL(fileURLWithPath: yourFinalVideoURL) as URL)
let playerController = AVPlayerViewController()
playerController.player = player
controller.present(playerController, animated: true) {
//player.play()
if #available(iOS 10.0, *) {
player.playImmediately(atRate: 1.0)
} else {
player.play()
}
}
}
}
The follow code works for me:
let videoURL = URL(string: "Some url")
let player = AVPlayer(url: videoURL!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
However when I tried to use your url it doesn't work.
I added the NSAppTransportSecurity in .plist, but it didn't work either.
It is obvious that you have a problem with the url, try to change the extension of the file sample12.MOV to sample12.mp4

Can't play video from documentsDirectory in iOS

I'm trying to play a video downloaded to the device's document directory. For some reason, it won't happen. All I get is this symbol:
Here's my code:
let documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let videoFileUrl = URL(fileUrlWithPath: documentPath)
let videoFilePath = videoFileUrl.appendingPathComponent("somVideo.mp4").path
if FileManager.default.fileExists(atPath: videFilePath){
let player = AVPlayer(url: URL(string: videoFilePath)!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
}
else {
print("File doesn't exist")
}
The file exists at the location - I have checked my documents directory for the simulator - and the else statement isn't fired. Nothing else is printed to the console.
Any help would be appreciated.
Here's the answer the OP edited into the question (and which was subsequently rolled back because answers should be answers). If OP posts a separate answer, I'll remove this one.
I managed to get it working with a little help from a colleague of mine. Here's the answer if anyone should be interested:
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
if let docDir : URL = urls.first {
let videoUrl = docDir.appendingPathComponent("\(objectId).mp4")
do {
let videoExists : Bool = try videoUrl.checkResourceIsReachable()
if videoExists {
let player = AVPlayer(url: videoUrl)
let playerController = AVPlayerViewController()
playerController.player = player
self.present(playerController, animated: true) {
playerController.player!.play()
}
}
else {
print("Video doesn't exist")
}
}
catch let error as NSError {
print(error)
}
}

Resources