Hi all i am trying to play a video from s3 using Avplayer. Now if i play the video, the video starts playback after the whole video is buffered. so I added player.automaticallyWaitsToMinimizeStalling = false, but now the video automatically pauses
import UIKit
import AVFoundation
import AVKit
class ViewController: UIViewController {
var player: AVPlayer!
var item : AVPlayerItem!
override func viewDidLoad() {
super.viewDidLoad()
item = AVPlayerItem(url: URL(string: "https://cent-churchconnect.s3-ap-southeast-2.amazonaws.com/cent-churchconnect/testAdmin/eb8cc8b5-80e0-468a-a2c9-979cf1b5ac76_toystory.mp4")!)
player = AVPlayer(playerItem: item)
let controller = AVPlayerViewController()
present(controller, animated: true) { _ in }
controller.player = player
addChildViewController(controller)
view.addSubview(controller.view)
controller.view.frame = CGRect(x: 0, y: 50, width: self.view.frame.size.width, height: 300)
controller.player = player
controller.showsPlaybackControls = true
if #available(iOS 10.0, *) {
player.automaticallyWaitsToMinimizeStalling = false
player.play()
} else {
// Fallback on earlier versions
}
}
}
I had the same issue below steps worked for me,
Try to use method func playImmediately(atRate:) and make sure the property player.automaticallyWaitsToMinimizeStalling = false is set properly.
Use method func playImmediately(atRate:) instead of func play()
I used the cocoa pod https://github.com/piemonte/Player.
You can use the delegate methods to control the playback.
Related
Thread 1: "Application tried to present modally a view controller <AVPlayerViewController: 0x15f83ee00> that has a parent view controller <ValorantAgentsApp.AbilitiesDetailsViewController: 0x15e918670>."
I get error when tried to play video in my app. My application crashes when it comes to the screen where I will play a video. I don't have a problem when I play the video with by pressing a button. But when I want to play as the screen loads, I get a crash.
import UIKit
import AVKit
import AVFoundation
import MediaPlayer
import MobileCoreServices
class AbilitiesDetailsViewController: UIViewController, AVPlayerViewControllerDelegate {
#IBOutlet var skillDetailsLabel: UILabel!
#IBOutlet var skillNameLabel: UILabel!
#IBOutlet var heroIconImageView: UIImageView!
var agentAbilitiesVideoURL = ""
var choosenAgentSkillName = ""
var choosenAbilitiesImages : UIImage?
override func viewDidLoad() {
skillNameLabel.text = choosenAgentSkillName
heroIconImageView.image = choosenAbilitiesImages
super.viewDidLoad()
playAbilitiesVideos()
}
func playAbilitiesVideos() {
let player = AVPlayer(url: URL(string: agentAbilitiesVideoURL)!)
let controller = AVPlayerViewController()
present(controller, animated: true) { }
controller.player = player
addChild(controller)
view.addSubview(controller.view)
controller.view.frame = CGRect(x: 50 , y: 50, width: 300, height: 300)
controller.player = player
controller.showsPlaybackControls = true
player.isClosedCaptionDisplayEnabled = false
player.play()
}
/*
#IBAction func playVideoUsingURL(_ sender: Any) {
playGlobalVideo()
}
func playGlobalVideo() {
guard let videoURL = URL(string: agentAbilitiesVideoURL) else {
return
}
let player = AVPlayer(url: videoURL)
let vc = AVPlayerViewController()
vc.player = player
present(vc, animated: true) {
player.play()
}
}
*/
}
This is my third screen and view controller.
either do:
view.addSubview(controller.view)
OR
present(controller, animated: true) { }
not both
The code I was using to embed a local video in a UIView isn't working on IOS 12. The audio is playing but I get a black screen.
from apple developer site:
Do not subclass AVPlayerViewController. Overriding this class’s methods is unsupported and results in undefined behavior.
the code works fine on IOS 11, any idea what do I need to change in the code?
thanks
import UIKit
import AVFoundation
import AVKit
class ViewController: UIViewController {
var avPlayer: AVPlayer!
override func viewDidLoad() {
super.viewDidLoad()
let filepath: String? = Bundle.main.path(forResource: "qidong", ofType: "mp4")
let fileURL = URL.init(fileURLWithPath: filepath!)
avPlayer = AVPlayer(url: fileURL)
let avPlayerController = AVPlayerViewController()
avPlayerController.player = avPlayer
avPlayerController.view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
avPlayerController.showsPlaybackControls = false
avPlayerController.player?.play()
self.view.addSubview(avPlayerController.view)
}
}
You need to add the AVPlayerViewController as a child view controller so something like this:
import UIKit
import AVFoundation
import AVKit
class ViewController: UIViewController {
var avPlayer: AVPlayer!
override func viewDidLoad() {
super.viewDidLoad()
let filepath: String? = Bundle.main.path(forResource: "qidong", ofType: "mp4")
let fileURL = URL.init(fileURLWithPath: filepath!)
avPlayer = AVPlayer(url: fileURL)
let avPlayerController = AVPlayerViewController()
avPlayerController.player = avPlayer
avPlayerController.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
avPlayerController.showsPlaybackControls = false
avPlayerController.player?.play()
self.addChild(avPlayerController)
self.view.addSubview(avPlayerController.view)
avPlayerController.didMove(toParent: self)
}
If you are not doing that then the AVPlayerViewController is probably getting released early.
Another minor issue but don't use the size of the UIScreen but the frame of the view controllers view instead (or even better do something like use auto layout).
I want to play background video on login screen on swift 3.0. But when I run program, video do not working as full screen. It is workingHow can I fix this ? Here is the storyboard picture.
enter code here
import UIKit
import AVFoundation
class ViewController: UIViewController {
var Player: AVPlayer!
var PlayerLayer: AVPlayerLayer!
var frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let URL:NSURL = NSURL(string: "https://firebasestorage.googleapis.com/v0/b/pattyapp-34c16.appspot.com/o/dog1.mp4?alt=media&token=98ab3c41-c645-4535-a70b-41511b5df602")!
Player = AVPlayer.init(url: URL as URL)
PlayerLayer = AVPlayerLayer(player: Player)
PlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect
PlayerLayer.frame.size = frame.size
Player.actionAtItemEnd = AVPlayerActionAtItemEnd.none
Player.isMuted = true
Player.play()
view.layer.insertSublayer(PlayerLayer, at: 0)
NotificationCenter.default.addObserver(self, selector: #selector(playerItemReachEnd(notification:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: Player.currentItem)
}
func playerItemReachEnd(notification: NSNotification) {
Player.seek(to: kCMTimeZero)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Play video into background you can use the following list of 3rd party library to resolve your problem.
VideoSplashKit
HAPlayerView
Video You are trying to play has dimensions different from layer size. I'd recommend You to try
PlayerLayer.videoGravity = AVLayerVideoGravityResize
or
PlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
I have programmatically added an AVPlayerViewController to a UIViewController. I am able to receive the notification when the player is finished playing (playerDidFinishPlaying). I would also like to know if a user has touched the screen while the video is playing and I have not found any related notifications.
The solution is to create a Base class of AVPlayerViewController and override touchesBegan(_:with:) method:
Swift 2:
Custom Base Class:
class CustomAVPlayerViewController: AVPlayerViewController {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("touchesBegan")
}
}
ViewController:
let videoURL = NSURL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(URL: videoURL!)
let playerViewController = CustomAVPlayerViewController()
playerViewController.player = player
self.presentViewController(playerViewController, animated: true) {
playerViewController.player!.play()
}
Swift 3:
Custom Base Class:
class CustomAVPlayerViewController: AVPlayerViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touchesBegan")
}
}
View Controller:
let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(url: videoURL!)
let playerViewController = CustomAVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
Don't forget to import AVKit and import AVFoundation.
Each time you tap on the playerViewController, "touchesBegan" will be printed.
I had this same problem. The contentOverlayView is only available in tvos, so that was not an option.
I ended up adding a UIView over the UIImageView that I added the AVPlayer to. I set the background color to clear on the UIView, so it's not visible, but can receive gestures. This provides a target for the tap gesture recognizer.
I resolve the same. Subclassing AVPlayerViewController will work on iOS 11.4.1 but not on iOS 12 an above. So the solution for this is add subview on playerviewcontroller contentoverlayview and then on that subview you can add any gesture or button for detecting the touch. Here is the code snippet for the same::
// This notification is added for continuous playing of the video you can remove this in case you need video is played only once.
private func playVideo() {
guard let path = Bundle.main.path(forResource: "BG01", ofType:"mp4") else {
debugPrint("video.m4v not found")
return
}
self.player = AVPlayer(url: URL(fileURLWithPath: path))
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: .main) { [weak self] _ in
self?.player?.seek(to: kCMTimeZero)
self?.player?.play()
}
let playerController : AVPlayerViewController? = AVPlayerViewController()
let btn : UIButton = UIButton()
btn.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
btn.addTarget(self, action: #selector(touchDetect), for: .touchUpInside)
btn.backgroundColor = UIColor.clear
playerController?.contentOverlayView?.addSubview(btn)
// playerController?.homeVCProtocolDelegate = self as HomeVCProtocol
playerController?.player = player
playerController?.showsPlaybackControls = false
self.player?.play()
present(playerController!, animated: false) {
self.player?.play()
}
}
#objc func touchDetect()
{
// Here you will get the call
}
I have a video I'm trying to play using MPMoviePlayerController and it loads fine, but cuts out after 5 seconds. I found this post, but it isn't really applicable for swift.
MPMoviePlayerController stops playing the video after 5s
Here is my code.
import MediaPlayer
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var moviePlayer: MPMoviePlayerController?
let url = NSURL(string: "http://path/to/video.m3u8")
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
player.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
player.view.sizeToFit()
player.scalingMode = MPMovieScalingMode.None
player.movieSourceType = MPMovieSourceType.Streaming
//player.repeatMode = MPMovieRepeatMode.One
player.play()
self.view.addSubview(player.view)
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "metadataUpdated",
name: MPMoviePlayerTimedMetadataUpdatedNotification,
object: nil)
}
}
Could your moviePlayer be going out of scope? Have you tried making it a member variable?
moviePlayer is a local variable of viewDidLoad, so once that function finishes, I don't see any reason why your player would not be deallocated.
If you instead make it a variable of the class, its lifetime will be extended to match your class's lifetime.
something like
class ViewController: UIViewController {
var player: MPMoviePlayerController?
override func viewDidLoad() {
// ...
self.player = MPMoviePlayerController(contentURL: url) // won't go out of scope at end of viewDidLoad()
// ...
}