AVPlayer works on simulator but crashes on real device - swift

AVPlayer is working fine in simulator but crashes on device.totally stuck please help out.
override func viewDidAppear(animated: Bool) {
let fileURL = NSURL(string: NSUserDefaults.standardUserDefaults().objectForKey("introVideoURl") as! String)
playVideo(fileURL!) // crashing line
}
func playVideo(url: NSURL) throws-> AnyObject{
let player = AVPlayer(URL: url)
playerController.player = player
self.addChildViewController(playerController)
self.view.addSubview(playerController.view)
playerController.view.frame = self.view.frame
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(introVideoController.playerDidFinishPlaying(_:)),
name: AVPlayerItemDidPlayToEndTimeNotification, object: player.currentItem)
player.play()
return true
}

Related

Swift: Parse does not load a video from URL

I am trying to stream a video from backend to my device.I have a video url from backend but screen displays nothing. However, youtube url it works. Can anyone guide me why this video is not playing and how can it be played? I am using pod 'YouTubePlayer' to play the video.
let cell: VideoTableViewCell = tableView.dequeueReusableCell(withIdentifier: "VideoTableViewCell") as! VideoTableViewCell
var query = PFQuery(className:"Videos")
query.getObjectInBackground(withId: "83kli72i62") { (parseObject, error) -> Void in
let videoFile = parseObject!["Question"] as! PFFileObject
self.videoUrl = videoFile.url
let url = NSURL(string: self.videoUrl! )
cell.playerView.loadVideoURL(url as! URL)
}
i have an app that is pulling videos from firebase and playing them with the avplayer, check out my code below and see how it works
class IsoLateralLowRowViewController: UIViewController {
#IBOutlet weak var playv: UIButton!
let avPlayerViewController = AVPlayerViewController()
var avPlayer:AVPlayer?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addBackground()
let movieUrl:NSURL? = NSURL(string: "https://firebasestorage.googleapis.com/v0/b/messenger-test-d225b.appspot.com/o/test%2FTestVideo.mov?alt=media&token=bd4ccba3-b446-43bc-809e-b1152aa3c2ff")
if let url = movieUrl {
self.avPlayer = AVPlayer(url: url as URL)
self.avPlayerViewController.player = self.avPlayer
}
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: avPlayerViewController.player?.currentItem)
self.present(self.avPlayerViewController, animated: true) { () -> Void in
self.avPlayerViewController.player?.play() // Do any additional setup after loading the view.
}
}
#objc func playerDidFinishPlaying(note: NSNotification) {
self.avPlayerViewController.dismiss(animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

How to make a video loop in Xcode swift 5?

I am trying to get a video background in my app and I have written the following code. It runs one time and then stops. How do I make the video repeat forever? Thanks in advance.
#IBOutlet weak var videoLayer: UIView!
override func viewDidLoad() {
super.viewDidLoad()
playBackgroundVideo()
}
func playBackgroundVideo(){
guard let path = Bundle.main.path(forResource: "City", ofType: "MOV") else {
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
playerLayer.videoGravity = .resizeAspectFill
self.videoLayer.layer.addSublayer(playerLayer)
player.play()
}
#objc func playerItemDidReachEnd(notification: Notification) {
let p: AVPlayerItem = notification.object as! AVPlayerItem
p.seek(to: .zero)
}
}
Try adding a notification listener to trigger the playerItemDidReachEnd code.
You do this by involving a NotificationCenter.default.addObserver in your setup.
Did not test your code, but you want a setup like this example:
#IBOutlet weak var videoLayer: UIView!
var player: AVPlayer!
override func viewDidLoad()
{
super.viewDidLoad()
playBackgroundVideo()
}
func playBackgroundVideo()
{
guard let path = Bundle.main.path(forResource: "City", ofType: "MOV") else{ return }
player = AVPlayer(url: URL(fileURLWithPath: path))
let playerLayer = AVPlayerLayer(player: player)
//# add a Listener
NotificationCenter.default.addObserver( self,
selector: #selector(playerItemDidReachEnd),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: nil)
playerLayer.frame = self.view.bounds
playerLayer.videoGravity = .resizeAspectFill
self.videoLayer.layer.addSublayer(playerLayer)
player.play()
}
#objc func playerItemDidReachEnd(notification: Notification)
{
player.seek(to: CMTime.zero)
player.play()
}

AVPlayer ,black screen after video is over

i have black screen after video is over, but i would like to be redirect to another storyboard when video is over.
Could somebody help me with this.
Thanks you
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
playVideo()
}
private func playVideo() {
guard let path = Bundle.main.path(forResource: "Kristinka", ofType:"m4v") else {
debugPrint("video.m4v not found")
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.showsPlaybackControls = false
playerController.player = player
present(playerController, animated: true) {
player.play()
}
}
}
You need to detect when the item you're playing has reached the end. To do that, you can add an observer. For example:
func finishedVideo(_ notification: NSNotification) {
print("Animation did finish")
}
private func playVideo() {
guard let path = Bundle.main.path(forResource: "Kristinka", ofType:"m4v") else {
debugPrint("video.m4v not found")
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.showsPlaybackControls = false
playerController.player = player
present(playerController, animated: true) {
NotificationCenter.default.addObserver(self,
selector: #selector(finishedVideo(_:)),
name: .AVPlayerItemDidPlayToEndTime,
object: player?.currentItem)
player.play()
}
}
And I dug this code up on this very related question. There's a lot of related/duplicate answers if you do a search.

Play audio again after finished with AVPlayer swift

How to play again the same audio after finished? Now I use this code with AVPlayer:
fileprivate func play () {
guard let url = URL(string: record.recordUrl) else { return }
let playItem = AVPlayerItem(url: url)
player.replaceCurrentItem(with: playItem)
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playItem)
player.play()
}
#objc func playerDidFinishPlaying(note: NSNotification) {
print("Player finished")
currentTimeSlider.setValue(0, animated: true)
currentTimeLabel.text = "00:00"
}
#objc func playerDidFinishPlaying(note: NSNotification) {
print("Player finished")
currentTimeSlider.setValue(0, animated: true)
currentTimeLabel.text = "00:00"
//Swift 4
player.seek(to: .zero, toleranceBefore: .zero, toleranceAfter: .zero)
//Swift 2 & 3 (I believe for 2 & 3)
//player.seek(to: kCMTimeZero, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
//Play
player.play()
}
I added the seek back to the beginning (the tolerance makes sure it is exactly at zero, and not around zero with some margin of error).
Also added the feature to play when done.

Avqueueplayer in For loop

I want to add the following method in for loop.
func playQuequeSounds(time:String){
let song1 = AVPlayerItem(URL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("estimatedTime", ofType: "mp3", inDirectory: "Audiofiles")!))
let song2 = AVPlayerItem(URL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(time, ofType: "mp3", inDirectory: "Audiofiles")!))
let song3 = AVPlayerItem(URL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("minutes", ofType: "mp3", inDirectory: "Audiofiles")!))
self.queueplayer = AVQueuePlayer(items: [song1,song2,song3])
self.queueplayer.actionAtItemEnd = AVPlayerActionAtItemEnd.Advance
self.queueplayer.play()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", name: AVPlayerItemDidPlayToEndTimeNotification , object: song3)
}
i add the above method in viewWillApear
override func viewWillAppear(animated: Bool) {
voiceRouteTableView.reloadData()
NSNotificationCenter.defaultCenter().removeObserver(self)
for i in 0...voicesRoutes.count{
flag=false
self.playQuequeSounds(String(i+1))
while flag==false{
}
}
sleep(2)
}
The problem is that the loop runs very quicky and doesn't wait the avqueueplayer to finish the play. Add notification and change the code into the loop for waiting until the follow method call but the same problem.
func playerDidFinishPlaying(note: NSNotification) {
flag=true
}