AVPlayer layer not showing video content sometimes but plays audio.
This happens some times not each time
Here is my lines of code :
override func viewDidLoad() {
super.viewDidLoad()
self.tempVideoPath = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("tmpMov.mov")
self.player = AVPlayer(url: self.tempVideoPath!)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.playerLayer = AVPlayerLayer(player: self.player)
self.playerLayer?.frame = self.videoPlayer.bounds
self.playerLayer?.backgroundColor = UIColor.yellow.cgColor
self.videoPlayer.layer.addSublayer(playerLayer!)
print("player = \(playerLayer?.bounds)")
}
Help me to solve this issue.
the problem with you code is that the bounds of videoPlayer can change.
So you need to add the following code to your view controller to change AVPlayerLayer's frame accordingly:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
playerLayer?.frame = view.bounds
}
Hope it helps.
Although the videoplayer has been initialized correctly or created from storyboard, it seems that the layer is non-existent and creates this annoying problem.
At the beginning of your viewDidAppear first, try to create the layer , than add to it>
let layer = CALayer()
self.videoPlayer.layer = layer
//self.playerView.wantsLayer = true // this line is only for osx
Related
resizeAspect as the video gravity only works properly for me, when using an iPhone X.
For some reasons, the black aspect bar gets only added to the top and not to the bottom. This is how it looks like when I'm not using an iPhone X (the image is white)
This is how it should look like:
As you can see, on the iPhone X, everything looks clean and balanced as expected.
This is how I play the video:
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer.frame = PreviewLayer.bounds
avPlayerLayer.videoGravity = .resizeAspect //Will automatically add black bars
PreviewLayer.layer.insertSublayer(avPlayerLayer, at: 0)
let playerItem = AVPlayerItem(url: video)
avPlayer?.replaceCurrentItem(with: playerItem)
avPlayer?.play()
Try this steps
1- Check bottom constraint connect with safe are
2- Try this code
import UIKit
import AVKit
class ViewController: UIViewController {
#IBOutlet weak var playerView: UIView!
private var player: AVPlayer!
override func viewDidLoad() {
super.viewDidLoad()
playVideo(from: "Intro.mp4")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func playVideo(from file:String) {
let file = file.components(separatedBy: ".")
guard let path = Bundle.main.path(forResource: file[0], ofType:file[1]) else {
debugPrint( "\(file.joined(separator: ".")) not found")
return
}
player = AVPlayer(url: URL(fileURLWithPath: path))
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { _ in
self.player?.seek(to: kCMTimeZero)
self.player?.play()
}
let playerLayer = AVPlayerLayer(player: player)
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspect
playerLayer.frame = playerView.layer.bounds
playerView.layer.insertSublayer(playerLayer, at: 0)
player.play()
}
}
Result on iphone X
Result on iphone 7
Note : if you need video full view on all devices try to link Bottom
constraint and Top constraint with superview not with safe area
Make your videoLayer View a subview of:
class VideoContainerView: UIView {
var playerLayer: CALayer?
override func layoutSublayers(of layer: CALayer) {
super.layoutSublayers(of: layer)
playerLayer?.frame = self.bounds
}
}
and add:
self.VideoShareLayer.playerLayer = avPlayerLayer;
before inserting the layer.
I am trying to display a video inside a cell. Instead, it just comes up as a black box. It is possible it is not initializing the player. I do, however see the black box so I know it is initializing the VideoPlayerView. When I print the frame of the playerLayer it prints (0.0, 0.0, 0.0, 0.0), possibly due to how I am initializing the view. Is there any way to extend the playerlayer to the edges of the view without using frame?
class VideoPlayerView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.black
let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(url: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.bounds
//print(playerLayer.frame)
self.layer.addSublayer(playerLayer)
player.play()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Thanks!
I've tried this a couple of different ways and ended up using a custom UIView class approach (like you did) but a few differences. For example, your class could look like this:
class PlayerView: UIView {
var player: AVPlayer? {
get {
return playerLayer.player
}
set {
playerLayer.player = newValue
}
}
var playerLayer: AVPlayerLayer {
return layer as! AVPlayerLayer
}
// Override UIView property
override static var layerClass: AnyClass {
return AVPlayerLayer.self
}
}
Then, you add a UIView in IB, set the class to PlayerView (instead of default UIView), add your constraints like normal and drag an outlet to your controller like any other control. To use it, you do the following:
playerView.player = AVPlayer(url: url)
playerView.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
Then trigger the Play command however your application needs it.
You could create this view dynamically using the same method but I tend to use IB most of the time.
Hope this helps!
You can set constraints to playerLayer, for example:
let width = UIScreen.main.bounds.width
let height = 300
let playerLayer = AVPlayerLayer(player: player)
playerLayer.translatesAutoresizingMaskIntoConstraints = false
playerLayer.widthAnchor.constraint(equalToConstant: width).isActive = true
playerLayer.heightAnchor.constraint(equalToConstant: height).isActive = true
I figured out that all you need to do is add this code:
Turns out when you resize it doesn't automatically resize layer sizes.
override func layoutSublayers(of layer: CALayer) {
super.layoutSublayers(of: layer)
playerLayer?.frame = self.bounds
}
i want create a login page for my app, in this case i want to use a video for background of login page, like vine,spotify,uber,...
i play video without problem and add some button and lable in storyboard to my view controllerŲ after run app i can not see objects of view controller
i just see video and objects hide behind of video background how can fix this problem,,,
thanks for helping
this is my code for playing video,,,
lazy var playerLayer:AVPlayerLayer = {
let player = AVPlayer(URL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("BWWalkthrough", ofType: "mp4")!))
player.muted = true
player.allowsExternalPlayback = false
player.appliesMediaSelectionCriteriaAutomatically = false
var error:NSError?
// This is needed so it would not cut off users audio (if listening to music etc.
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
} catch var error1 as NSError {
error = error1
} catch {
fatalError()
}
if error != nil {
print(error)
}
var playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.frame
playerLayer.videoGravity = "AVLayerVideoGravityResizeAspectFill"
playerLayer.backgroundColor = UIColor.blackColor().CGColor
player.play()
NSNotificationCenter.defaultCenter().addObserver(self, selector:"playerDidReachEnd", name:AVPlayerItemDidPlayToEndTimeNotification, object:nil)
return playerLayer
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.layer.addSublayer(self.playerLayer)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
override func willAnimateRotationToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
playerLayer.frame = self.view.frame
}
func playerDidReachEnd(){
self.playerLayer.player!.seekToTime(kCMTimeZero)
self.playerLayer.player!.play()
}
You need to add your playerLayer below all the views created when your storyboard loads. Replacing
self.view.layer.addSublayer(self.playerLayer)
with
self.view.layer.insertSublayer(self.playerLayer, atIndex:0)
should do the job, unless there are any subviews of the view controller view that you actually want to be behind the video layer.
so I have the following code working great! for anyone wanting to get a video working in SWIFT. The issue is, after the video finishes it remains on the video. Even when pressing Done nothing happens...
How can I close the video back to one of the existing View Controllers?
class ViewController: UIViewController {
var moviePlayer : MPMoviePlayerController?
override func viewDidLoad() {
super.viewDidLoad()
playVideo()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func playVideo() {
//Get the Video Path
//You need to put this in Project->Target->copy bundle resource for this to work
let videoPath = NSBundle.mainBundle().pathForResource("Quizzes", ofType:"mov")
//Make a URL from your path
let url = NSURL.fileURLWithPath(videoPath!)
//Initalize the movie player
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
//Make the player scale the entire view
player.view.frame = self.view.bounds
player.scalingMode = .AspectFill
//Add it as a subView to your currentView
self.view.addSubview(player.view)
//Play the video
player.prepareToPlay()
}
else {
print("Movie player couldn't be initialized")
}
}
You have added it as subview
self.view.addSubview(player.view)
You also need to remove it where is that code?
Please use removeFromSuperview when done playing.
I have a local .mp4 video that I would like to add as a background video. I've created a function:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("dronefootagecompressed", ofType:"mp4")
let url = NSURL.fileURLWithPath(path!)
self.moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = self.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.Fill
player.fullscreen = true
player.controlStyle = MPMovieControlStyle.None
player.movieSourceType = MPMovieSourceType.File
player.repeatMode = MPMovieRepeatMode.One
player.play()
self.view.addSubview(player.view)
}
}
which is then called in viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
playVideo()
}
The video is showing up, but it seems like it's covering everything else (text labels, titles, everything), or so I assume it is. Can I make the video be in the background (if that even is the issue)?
Thanks.
EDIT:
When I call playVideo() in viewDidAppear, the video shows up for about 2 seconds before going to a black background. The buttons are still visible. Is the video not loading properly?
i think putting it in viewDidAppear() method will solve the thing