How to play video file from documentdirectory using avplayer - ios

I am creating video player application in ios,if i store mp4 file in bundle resource or if i stream url it is working fine but if i store a file in document direcory and i am trying to play with avplayer it is not playing should i handle differently with offline file in document directory
code:
let fileManager = FileManager()
let destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appendingFormat("/myvideo.mp4"))
self.playVideo(filePath: destinationURLForFile.path)
func playVideo(filePath:String)
{
var playerItem = AVPlayerItem.init(url:URL.init(string: filePath)!)
var player = AVPlayer(playerItem: playerItem)
var playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.frame
self.view.layer.addSublayer(playerLayer)
player.play()
}

Try this, written in Swift 3.0,
let fm = FileManager.default
let docsurl = try! fm.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let path = docsurl.appendingPathComponent("myvideo.mp4")
playVideo(filePath: path)
func playVideo(filePath:String)
{
var playerItem = AVPlayerItem(url: URL(fileURLWithPath: filePath)
var player = AVPlayer(playerItem: playerItem)
var playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.frame
self.view.layer.addSublayer(playerLayer)
player.play()
}

swift 3/4 100%%%%%%% workable
Recorder open video camera
#IBAction func RecordAction(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera){
print("CameraAvailable")
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.mediaTypes = [kUTTypeMovie as String]
imagePicker.allowsEditing = false
imagePicker.showsCameraControls = true
self.present(imagePicker,animated: true, completion: nil)
}
else{
print("CameraNotAvailable")
}
}
save to document directory
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// recover video URL
let url = info[UIImagePickerControllerMediaURL] as? URL
// check if video is compatible with album
let compatible: Bool = UIVideoAtPathIsCompatibleWithSavedPhotosAlbum((url?.path)!)
// save
if compatible {
UISaveVideoAtPathToSavedPhotosAlbum((url?.path)!, self, nil, nil)
print("saved!!!! \(String(describing: url?.path))")
}
videopath = url //save url to send next function play video
dismiss(animated: true, completion: nil)
}
// error
func video(_ videoPath: String, didFinishSavingWithError error: Error?, contextInfo: UnsafeMutableRawPointer) {
}
play video from Document directory
#IBAction func playvideo(_ sender: Any)
{
let player = AVPlayer(url: videopath!) // video path coming from above function
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
}

I tried several methods including the above, but found that the documents path changes for the app each time it is launched, which changes the first part of the URL.
This helped me to get the current location of my file:
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let playerItem = AVPlayerItem(url: URL(fileURLWithPath: documentsPath.appendingFormat("/\(clipId).mp4")))
player = AVPlayer(playerItem: playerItem)

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

AVPlayer is not playing audio from Document directory using Swift3

I have an audio files, stored in Document directory. I want play it using AVPlayer but it is not playing. I am using Swift3.
var myurl : NSURL!
var audioPlayer = AVPlayer()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Getting sound from Document directory
let fileManager = FileManager.default
let docsurl = try! fileManager.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
myurl = docsurl.appendingPathComponent("/\(songName!)")
playSound(url: myurl! as NSURL)
}
// Playing Sound
func playSound(url:NSURL){
let asset = AVURLAsset(url: url as URL, options: nil)
let playerItem = AVPlayerItem(asset: asset)
self.audioPlayer.replaceCurrentItem(with: playerItem)
let durationInSeconds = CMTimeGetSeconds(asset.duration)
self.getSeconds = Int(durationInSeconds)
self.audioPlayer.play()
}
I am getting url from document directory, but it is not playing. Don't know why?
Thanks in Advance.
Put this code in AppDelegate.swift file in application:didFinishLaunchingWithOptions: method and see if you can hear the audio:
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
}catch {
print(error)
}

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

I can't play video saved in Directory path and AVPlayer in swift 2.3

I'm recording a video with AVFoundation, and I created a preview from the video, when I finish to record a video, the video is playing in the preview, but when I save the video using:
var fileName = "\(self.tField.text!).mp4"
fileName = fileName.stringByReplacingOccurrencesOfString(" ", withString: "_")
let path = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
//let originVideoFile = self.filePath
let destinationVideoFile = path.URLByAppendingPathComponent(fileName)
let data = NSData(contentsOfURL: self.filePath)
//try data!.writeToURL(destinationVideoFile!, options: [])
let fileManager = NSFileManager()
fileManager.createFileAtPath((destinationVideoFile?.path)!, contents: data, attributes: nil)
The video file is created but I don't have access to this file when I want re play the video, but the camera roll can play the video.
to get the "filePath" I'm using the delegate method of AVFoundation:
func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {
print("capture did finish")
print(captureOutput);
print(outputFileURL);
self.filePath = outputFileURL
performSegueWithIdentifier("previewVideo", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "previewVideo"{
let destination = segue.destinationViewController as! PreviewVC
destination.filePath = self.filePath
destination.videoDelegate = self.videoDelegate
}
}
and pass the data with "prepareForSegue"
I return a video object with the information needed, and when I want to re play a video, I using the method "didSelect" of the collectionview I create a "AVPlayer" and use the name of the file to found the path of the video, then the file exist but can't play
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
videoSingleObject = videoObjects[indexPath.item]
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.URLByAppendingPathComponent(videoSingleObject.nameOfFile)!.path!
let fileManager = NSFileManager.defaultManager()
if fileManager.fileExistsAtPath(filePath) {
print("FILE AVAILABLE")
UISaveVideoAtPathToSavedPhotosAlbum(filePath, nil, nil, nil)
print("PATH: \(filePath)")
let videoPath = NSURL(string: filePath)!
//filePathURL = videoPath
print(videoPath)
asset = AVAsset(URL: videoPath)
playerItem = AVPlayerItem(asset: asset)
print("DURATION: \(CMTimeGetSeconds(asset.duration))")
player = AVPlayer(playerItem: playerItem)
playerViewController.player = player
self.presentViewController(playerViewController, animated: true, completion: nil)
player.play()
}else {
print("THE DIRECTORY NOT EXIST")
}
}
but I use "UISaveVideoAtPathToSavedPhotosAlbum(filePath, nil, nil, nil)" to share the video in the cameraRoll, and in the cameraRoll the video is can play.
i found the error, the problem is the URL reference, i'm using a NSURL(string: filePath), i solved the problem using NSURL(fileURLwithPath: filePath)

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

Resources