add AVPlayerViewController view to external window - ios

I want to programmatically add an AVPlayerViewController view to an external window from an iPad. The problem is that when adding it, the player view says "This video is playing on the TV"
example code:
let player = AVPlayer(url: someUrl)
//these two properties seem to have no effect
//player.usesExternalPlaybackWhileExternalScreenIsActive = true/false
//player.allowsExternalPlayback = true/false
let viewController = AVPlayerViewController()
viewController.player = player
viewController.view.frame = frame
externalWindow.addSubview(viewController.view)
player.play()
Is there a way to add the video view myself to the external window so I can decide the size?

If you want to control the size of the AVPlayerViewController you can use the layer or you can add it as a childViewController
Using Layer
let videoURL = URL(url to your file)
let player = AVPlayer(url: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
player.play()
In the above code the frame can be adjusted as per the requirement.
Using ChildViewController:
let videoURL = URL(fileURLWithPath: videoPath)
let player = AVPlayer(url: videoURL)
let playerViewController = AVPlayerViewController()
playerViewController.view.frame = CGRect(give the appropriate size)
playerViewController.player = player
self.addChildViewController(playerViewController)
self.view.addSubview(playerViewController.view)
playerViewController.didMove(toParentViewController: self)
Let me know if this helps!! or anything else is needed.

Related

Why does my AVPlayerViewController not show playback controls?

My AVPlayerViewController does not show the video controls even though .showsPlaybackControls is set to true. This started with iOS 16 and the weird thing is .showsPlaybackControls = false will dismiss the controls visible when they're visible through clicking on the video.
var playerController = AVPlayerViewController()
var playerItem = AVPlayerItem(asset: assetComp)
player = AVPlayer(playerItem: playerItem)
playerController.player = player
playerController.showsPlaybackControls = true
self.view.addSubview(playerController.view)
self.addChild(playerController)
player.play()

How to properly show multiple videos in the same avPlayerLayer

What I'm trying to achieve?
I'm showing users a subview with integrated page control. I want to show three different videos on the same subview.
How I implemented avPlayer?
First step:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
avPlayerLayer.frame = (WelcomeView?.video.layer.bounds)!
}
First video aligned perfectly in the middle of my view with this snippet of code:
WelcomeView?.frame.size.width = deviceScreen.frame.size.width
WelcomeView?.frame.size.height = deviceScreen.frame.size.height
WelcomeView?.video.layer.cornerRadius = 15
WelcomeView?.video.clipsToBounds = true
WelcomeView?.gradient.layer.cornerRadius = 25
WelcomeView?.gradient.clipsToBounds = true
WelcomeView?.label.addShadow()
let theURL = Bundle.main.url(forResource:"welcome1", withExtension: "MP4")
avPlayer = AVPlayer(url: theURL!)
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspect
avPlayer.volume = 0
avPlayer.actionAtItemEnd = .none
NotificationCenter.default.addObserver(self,
selector: #selector(playerItemDidReachEnd(notification:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: avPlayer.currentItem)
WelcomeView?.video.frame = (WelcomeView?.video.layer.bounds)!
WelcomeView?.video.layer.insertSublayer(self.avPlayerLayer, at: 0)
WelcomeView?.tapNext.addTarget(self, action: #selector(GalleryViewController.nextOutboarding(sender:)))
self.view.addSubview(WelcomeView!)
avPlayer.play()
Second step (when user clicks on the button next and when I'm trying to show different video on the same subview):
#objc func nextOutboarding(sender: UITapGestureRecognizer) {
WelcomeView?.pageControl.currentPage += 1
if WelcomeView?.pageControl.currentPage == 1 {
avPlayer.pause()
avPlayerLayer.removeFromSuperlayer()
let theURL = Bundle.main.url(forResource:"welcome2", withExtension: "MP4")
avPlayer = AVPlayer(url: theURL!)
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspect
avPlayer.volume = 0
avPlayer.actionAtItemEnd = .none
NotificationCenter.default.addObserver(self,
selector: #selector(playerItemDidReachEnd(notification:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: avPlayer.currentItem)
WelcomeView?.video.frame = (WelcomeView?.video.layer.bounds)!
WelcomeView?.video.layer.insertSublayer(self.avPlayerLayer, at: 0)
self.view.addSubview(WelcomeView!)
avPlayer.play()
}
}
My problem:
When I'm trying to show second video on the same avPlayerLayer - my video has different alignment (basically not in the middle anymore).
Any tips? Thank you.
First of all, create new AvPlayerItem.
var playerItem:AVPlayerItem?
Then use replaceCurrentItem function.
playerItem = AVPlayerItem(url: theURL!)
avPlayer.replaceCurrentItem(with: playerItem)
That's it. Now you can reuse existing avPlayer.
Instead of adding new subview with AVPlayerLayer every time user clicks next, you should reuse the AVPlayerLayer that you've already added to play the next video. In your code, you're trying to add the WelcomeView again as the subview but it's already is a subview and the previous layer has all the properties that you've set to it and you don't need to repeat that.
#objc func nextOutboarding(sender: UITapGestureRecognizer) {
WelcomeView?.pageControl.currentPage += 1
if WelcomeView?.pageControl.currentPage == 1 {
avPlayer.pause()
let theURL = Bundle.main.url(forResource:"welcome2", withExtension: "MP4")
avPlayer = AVPlayer(url: theURL!)
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayer.play()
}
}

How to play video in fullscreen size in portrait mode?

I want to play some video in splash screen in portrait mode - full screen.
Is that possible? please guide me through a proper solution.
I'm looking for swift solution
create a subclass of UIView, with a AVPlayer and a function createBackground:
import AVFoundation
class BackgroundVideo: UIView {
var player: AVPlayer?
func createBackground(name: String, type: String) { }
}
then your createBackground might be something like:
func createBackground(name: String, type: String) {
guard let path = Bundle.main.path(forResource: name, ofType: type) else { return }
player = AVPlayer(url: URL(fileURLWithPath: path))
player?.actionAtItemEnd = AVPlayerActionAtItemEnd.none;
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.frame
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
self.layer.insertSublayer(playerLayer, at: 0)
player?.seek(to: kCMTimeZero)
player?.play()
}
then you may add more stuff, such as observing notifications:
AVPlayerItemDidPlayToEndTime for implementing a video loop.
UIApplicationWillEnterForeground for controlling the video loop, after resuming from background.
finally you might attach this BackgroundView, wherever you need: fake splash screen, home screen, and so on...
SWIFT 3.0
You can not do that in default splash screen but you can do some workaround to acheive this.
First of all you should take first frame of your video which will be image.
You can do that using photoshop or by any other graphics tool.
Now you can set it to you default splash screen in UIImageView.
Now make a UIViewController and launch that as initial view controller.
And below is the code to play video
private func playFullScreenVideo() {
// drag your video file in project
// check if video file is available,if not return
guard let path = Bundle.main.path(forResource: "video", ofType:"mp4") else {
debugPrint("video.mp4 missing")
return
}
// create instance of videoPlayer with video path
let videoPlayer = AVPlayer(url: URL(fileURLWithPath: path))
// create instance of playerlayer with videoPlayer
let playerLayer = AVPlayerLayer(player: videoPlayer)
// set its videoGravity to AVLayerVideoGravityResizeAspectFill to make it full size
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
// add it to your view
playerLayer.frame = self.view.frame
playerView.layer.addSublayer(playerLayer)
// start playing video
videoPlayer?.play()
}
Let me know if having any trouble in this
Inside didFinishLaunch method of app delegate
let splashScreenVC = viewController(withIdentifier: "identifier", inStoryboard: "storyboard:) as? SplashViewController
window?.rootViewController = splashScreenVC
Inside the view controller SplashViewController, you can play video in viewDidLoad method.
func playVideo() {
guard let videoPath = Bundle.main.path(forResource: "Redtaxi-splash", ofType:"mov") else {
return
}
let videoURL = URL(fileURLWithPath: videoPath)
let player = AVPlayer(url: videoURL)
playerViewController = AVPlayerViewController()
playerViewController?.player = player
playerViewController?.showsPlaybackControls = false
playerViewController?.view.frame = view.frame
playerViewController?.view.backgroundColor = .white
playerViewController?.view.contentMode = .scaleAspectFill
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying(note:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem)
view.addSubview((playerViewController?.view)!)
playerViewController?.player?.play()
}

Video not opening when button is clicked in Swift 3/4?

I am trying to build an app where I have a button and when you click on a button it should open the video. But for some reason, the button is being tapped but not opening the video. Can any one check, what I have done wrong. The video is in my Folder Directory in Xcode.
Code:
var playerview = AVPlayer()
var playerviewcontroller = AVPlayerViewController()
#IBAction func playBtnTapped(_ sender: Any) {
//print("btn tapped")
let videoURL = URL(string: "Promo.mp4")
let player = AVPlayer(url: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
player.play()
}
I got it to solved by doing and using the AVPlayerViewController:
let videoURL = Bundle.main.url(forResource: "Promo", withExtension: ".mp4")
let player = AVPlayer(url: videoURL!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
}
Try this as url:
Bundle.main.url(forResource: "Promo", withExtension: ".mp4")

Play Local Video File

I have followed a tutorial and trying to get a video to pop up when I press a button. The video pops up but the actual video does not start playing and I just get this screen....
Blank Screen image
the code is as follows:
import UIKit
import AVFoundation
import AVKit
class ViewController: UIViewController {
var playerController = AVPlayerViewController()
var player:AVPlayer?
override func viewDidLoad() {
super.viewDidLoad()
let videoString:String? = Bundle.main.path(forResource: "motorbikes", ofType: ".m4v")
if let url = videoString {
let videoURL = NSURL(fileURLWithPath: url)
self.player = AVPlayer(url: videoURL as URL)
}
}
#IBAction func goButton(_ sender: Any) {
self.present(self.playerController, animated: true, completion: {
self.playerController.player?.play()
})
}
}
You have forgot to set playercontroller's player instance as phuc-nguyen said
or else you can make use of AVPlayerLayer to play the video without using AVPlayerViewController
let player = AVPlayer(url: URL(string: "path/myvideo.mp4")!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
player.play()
Using AVPlayerLayer you can customize the player like adding your own controls or views and it won't be a full screen view usually though.
But if you are not looking for any customization its good to stick with AVPlayerViewController it has all the controls baked in
Depends on your requirement

Resources