I've downloaded a file, now I'm trying to play it back
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let the = (paths as String) + "/" + (df.destinationURL?.lastPathComponent)!
print(the)
let fileUrl = NSURL.fileURL(withPath: the)
let asset = WKAudioFileAsset(url: fileUrl)
self.downloadProgress.setText(String(asset.duration))
let playerItem = WKAudioFilePlayerItem(asset: asset)
self.player = WKAudioFilePlayer(playerItem: playerItem)
print(self.player.description)
self.player.play()
No sound is played.
However, any playing music IS paused, asset.duration DOES return the correct duration for the file.
Despite this, no audio is played at all.
Using self.presentMediaController() DOES work (using the same file URL), however, this pauses when I leave the app.
Any ideas?
Related
I tried to run a remote mpga format audio file with AVPlayer in ios and doesn't play. Below code works fine for remote mp3 files. Can i change the MIME type for the file loaded or are there any options to play the mpga file in ios.
let audioUrl = "https://example-files.online-convert.com/audio/mpga/example.mpga"
let url = URL(string: audioUrl)
let player: AVPlayer = AVPlayer(url: url!)
player.play()
console shows
nw_endpoint_flow_copy_multipath_subflow_counts Called on non-Multipath connection
let audioUrl = "https://example-files.online-convert.com/audio/mpga/example.mpga"
if let url = URL(string: audioUrl){
let playerItem = AVPlayerItem(url: url)
let player: AVPlayer(playerItem: playerItem)
player.play()
}
When selecting a video from the Photo Library, iOS compresses the video and stores it in the tmp/ folder. That location is returned as the '.mediaURL' and is used to load the video into an AVPlayer. I am trying to save the location of the selected video so it can be played back later, but I found that the tmp/ url is cleared out at some point after closing the app and reopening it. For music, I can store the 'persistentID' to retrieve the songs later. I have not been able to find a good way to persist the location of the originally selected video so it can be replayed later without having to select it again during the current session. Looking for suggestions.
I am using Swift 5 for iOS.
Thanks...
When you use imagePicker to select a video from gallery , you need to copy it someWhere say inside the documents folder to be able to persistently reference it when you open the app again
This is the solution I found:
To save the selected video:
func saveVideoToDirectory(videoUrl: NSURL) {
let videoData = NSData(contentsOf: videoUrl as URL)
let path = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let newPath = path.appendingPathComponent("/backgroundVideo.mp4")
do {
try videoData?.write(to: newPath)
let movieData = NSKeyedArchiver.archivedData(withRootObject: newPath)
UserDefaults.standard.set(movieData, forKey: "movie")
//print("movie url: ", newPath)
} catch {
print(error)
}
}
to retrieve the video:
let movieData = UserDefaults.standard.object(forKey: "movie") as? Data
let movieUrl = NSKeyedUnarchiver.unarchiveObject(with: data) as! URL
//search for current documents path
let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let videoUrl = URL(fileURLWithPath: docPath.appendingFormat("/backgroundVideo.mp4"))
let playerItem = AVPlayerItem(url: videoUrl as URL)
I am trying to play a video form my Server but when I try to do so I get a Crossed mark on pay button.
All other files like .ppt,.keynote etc work fine when I use them with my Server url and use a WKWebview to show them but .mp4 files are not working.
I tried 2 methods.
1) Playing directly using WKWebview.
2) Download the file and saving it in a local path and then using AVPlayer to play the file.
In both cases I get same crossed mark on the play button.
func playVideo(url:String){
var newUrl:String = url
if !( url.hasPrefix("http") || url.hasPrefix("https") ){
let host = kGetHostName()
newUrl = host + newUrl
}
do
{
let videoData = NSData(contentsOf: URL(string: newUrl)!)
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let path = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("myMove.mp4")
if videoData == nil{
print("No data in this")
return
}
videoData?.write(toFile: path.absoluteString, atomically: true)
let playeritem = AVPlayerItem(url: path)
let player = AVPlayer(playerItem: playeritem)
let controller = AVPlayerViewController()
controller.player = player
self.present(controller, animated: true) {
player.play()
}
} catch {
print(error)
}
And when trying with WKWebview
func loadWebView(url:String){
var newUrl:String = url
if !( url.hasPrefix("http") || url.hasPrefix("https") ){
let host = kGetHostName()
newUrl = host + newUrl
}
self.webView.load(URLRequest(url: URL(string: newUrl)!))
}
Both cases fail and get this. Is there any way I can play the video without changing my plist settings as I want to download and play ?
1.Screen Shot
2.Screen Shot
i'm playing an encrypted m3u8 file and i need to send a new "mykey" update value after certain time to the player.
let headers = ["Authorization": "mykey"]
let avAsset = AVURLAsset(url: videoURL, options: ["AVURLAssetHTTPHeaderFieldsKey": headers])
let avItem = AVPlayerItem(asset: avAsset)
let avPlayer = AVPlayer(playerItem: avItem)
how could i access to the AVURLAsset from the player later on to update my value?
I don't have find anything under...
self.avPlayer.items()[0].asset...
Just call the replaceCurrentItem(with:) function of AVPlayer, Documentation here
let newAvItem = AVPlayerItem(asset: newAvAsset)
avPlayer.replaceCurrentItem(with: newAvItem)
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()
}
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
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()
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()
}