AVPlayer full screen issue only for iPhone x - ios

I created a splash video using Av player view controller. its is coming properly for all the devices except I Phone X. I tried changing video gravity frame and everything but it won't work. any Idea about this? here is the sample code :
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()

I fixed this by giving the video gravity for the player view controller :
playerViewController.videoGravity = .resizeAspectFill
this will fix the issue by using the video gravity as aspect fill for the avplayer view controller. here is the documentation for video gravity:
The video gravity determines how the video content is scaled or stretched within the player layer’s bounds.

Swift 4
playerViewController.videoGravity = AVLayerVideoGravity.resizeAspectFill.rawValue

Related

Set opacity of AVPlayerLayer

I have seen quite a few posts of people wanting to play videos with transparent backgrounds. That is not what I am trying to accomplish here.
I am trying to set the opacity of the whole layer. Below is how I am setting the opacity of an image layer. I have tried the same approach to set opacity for the video layer but nothing happened when I attempted to fade
#IBAction func imageFadeAction(_ sender: Any) {
let rounded = Int(round(imageFader.value))
imageLabel.text = "\(rounded.description)%"
let fade = imageFader.value / 100
SecondScreen.main?.backgroundImage.alpha = CGFloat(fade)
SecondScreen.main?.viewDidLoad()
}
This is how I am playing the video and generating the layer
func playVideo() {
let videoURL = SecondScreen.videoPath
self.player = AVPlayer(url: videoURL!)
self.avpController = AVPlayerLayer(player: player)
avpController.frame = self.view.bounds
self.view.layer.addSublayer(avpController)
player.play()
}
Can anyone tell me if its possible or point me in the right direction
To answer my own question, Use a container view. play your video in a separate ViewController and embed it in the container view. THEN you can set the opacity of the container view.
I don't know if this is the correct way to do it, but it works for me and what I needed. If someone has a better answer please feel free to share
You can set its opacity to 0. something like this:
guard let path = Bundle.main.path(forResource: "SomeVideo", ofType: ".Someformat") else {
return nil
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerLayer = AVPlayerLayer(player: player)
playerLayer.opacity = 0
.
.
.

Stretch AVPlayerLayer to fit into iPhone X format

I have an app where I play a video in the background in a certain view.
This video is always supposed to play fullscreen. I recently asked a question about stretching this video to fill up an iPhone plus model (make AVPlayer fill the entire screen) However, I just tested on an iPhone X, and the following happens:
I made the background of the view containing the AVPlayerLayer purple, just to clarify. As you can see, the video plays in the top of the screen (appx. 80pt), then there's the complete video, and then there's nothingness. How is this possible if my view does actually cover the entire screen?
This is how the video is made:
#objc fileprivate func playVideo() {
log.debug("playVideo")
let file = self.videoName.components(separatedBy: ".")
guard let path = Bundle.main.path(forResource: file[0], ofType:file[1]) else {
debugPrint( "\(file.joined(separator: ".")) not found")
return
}
self.player = AVPlayer(url: URL(fileURLWithPath: path))
let playerLayer = AVPlayerLayer(player: self.player)
playerLayer.frame = self.bounds
self.layer.addSublayer(playerLayer)
self.play()
if (self.loop) {
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { _ in
self.restart()
}
}
self.backgroundColor = .purple
NotificationCenter.default.addObserver(
self,
selector: #selector(self.restart),
name: Notification.Name("playVideos"),
object: nil)
}
This method is called after layoutSubviews().
How do I make the video stretch fully (with some overflow on the sides to make it visible of course)? Thanks :-).

Play several videos using AVPlayer in a view

I have an UIView which contains some some texts and views. in each view I need to play a video with AVPlayer , but my problem is only the first view shows the video :
Here is my code :
func playVideo(name:String , onView:UIView) {
let path = Bundle.main.path(forResource: name, ofType: "mp4")
let videoURL = URL(fileURLWithPath: path!)
let player = AVPlayer(url: videoURL)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = onView.frame
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
onView.layer.addSublayer(playerLayer)
player.play()
}
Using the function :
override func viewDidLoad() {
super.viewDidLoad()
//ScrollView
scrollView.contentSize = menuView.frame.size
scrollView.addSubview(menuView)
//Play videos
playVideo(name: "pizza", onView: videoView1)
playVideo(name: "salad", onView: videoView2)
playVideo(name: "fries", onView: videoView3)
}
when I run the app video only play in videoView1 , any suggestion why this happens ?
I also put my code in viewWillAppear , viewDidLayoutSubviews
According to Apple doc:
class AVPlayer
Note
AVPlayer is intended for playing a single media asset at a time.
I just found an alternative solution , I replaced UIView with UIContainerView and then link them with Embed to other view controller and play video in each view controller. Now it works perfectly as I expected.

AVPlayerLayer shows black screen but sound is working

Im trying to display a local recorded video in a AVPlayerLayer which works sometimes. I can hear the audio from the recorded video but can't see the video. Sometimes both video and audio is working, sometimes only audio.
I've tried both with a AVPlayerLayer and AVPlayerViewController but the same issue occurs in both cases. So it's not because of the frames being wrong.
Example code AVPlayerViewController:
let player = AVPlayer(url: url)
let playerController = AVPlayerViewController()
playerController.player = player
self.present(playerController, animated: true) {
player.play()
}
Example code AVPlayerLayer:
let asset = AVAsset(url: url)
let item = AVPlayerItem(asset: asset)
self.player = AVPlayer(playerItem: item)
self.player?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions(), context: nil)
self.playerLayer = AVPlayerLayer(player: self.player!)
self.playerLayer?.frame = imageView.bounds
imageView.layer.addSublayer(self.playerLayer!)
Edit 1:
When observing the status of the player, error is nil and the status is readyToPlay
Edit 2:
Works fine if the URL is remote.
Edit 3:
Seems to work if I wait a couple of seconds after the video has completed the export. Could it be something to have with the file not 100% written to the filesystem?
Edit 4:
Video of the problem, in this case it played the 3rd time.
Here's how I set a AVPlayerLayer with the video working (I think what you're missing is the videoGravity parameter).
let bundle = Bundle.main
let moviePath = bundle.path(forResource: "myVideo", ofType: "mp4")
let moviePlayer = AVPlayer(url: URL(fileURLWithPath: moviePath!))
playerLayer = AVPlayerLayer(player: moviePlayer)
playerLayer.frame = movieView.bounds
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect
movieView.layer.addSublayer(playerLayer)
playerLayer.player?.play()
It's the frame height or width is equal to zero
i have the same issues as you did. the reason is in iOS 10.xx , if you export video with animationTool .
You will meet the trouble like that .
try to fix them by remove this code .
something like that
mainComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentlayer)
Hope to help you
What caused this issue for me was I was changing assets to play a new video. The problem was I was reinitializing the same AVPlayer and setting setting it to the playerLayer which was previously set
Incorrect
player = AVPlayer()
playerLayer = AVPlayerLayer(player: player)
// ...
player?.replaceCurrentItem(with: playerItem)
Correct
if player == nil {
player = AVPlayer()
playerLayer = AVPlayerLayer(player: player)
// ...
}
player?.replaceCurrentItem(with: playerItem)
Or better yet I should've just called this by itself
player?.replaceCurrentItem(with: playerItem)

AVPlayer automatically zoom in video in IOS + Swift

I've used AVPlayer and AVPlayerViewController.
let playerController = AVPlayerViewController()
var player = AVPlayer()
self.player = AVPlayer(URL: NSURL(fileURLWithPath:videoPath))
self.playerController.player = self.player
self.playerController.showsPlaybackControls = false
self.addChildViewController(self.playerController)
self.view.addSubview(self.playerController.view)
self.playerController.view.frame = ...
I can play video with controls but when video finish I have to hide controls.
I found the event if video finished and at that time I hide the control
func playerDidFinishPlaying(note: NSNotification) {
self.playerController.showsPlaybackControls = false
}
Problem: If user zoom out video and video finished then hide control so Is there any possibilty to back to original frame
Thank you so much in adv.

Resources