I have a UICollectionViewController with fullscreen cells that scroll horizontally. Within each cell is another collectionView that scrolls vertically. The header cell of the collectionView has an AVPlayer pulling a video from a URL. Currently only the audio plays but the video doesn't.
The below AVPlayer setup and observers are of the same code I've used numerous other times within the app outside of a UICollectionViewCell without problem. The player frame size checks out, and the audio plays and loops as expected, so the observers seem to be triggering properly.
Relevant code:
var post: Post! {
didSet {
videoURL = URL(string: post.videoURL)
setupVideoObservers()
}
}
var videoURL: URL! {
didSet {
videoPlayer = AVPlayer(url: videoURL!)
}
}
@objc dynamic var videoPlayer: AVPlayer!
var videoPlayerLayer: AVPlayerLayer!
let videoContainerView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
setupCell()
}
func setupCell() {
addSubview(videoContainerView)
videoContainerView.anchor(top: topAnchor,
right: rightAnchor,
bottom: bottomAnchor,
left: leftAnchor)
videoPlayerLayer = AVPlayerLayer(player: videoPlayer)
videoPlayerLayer.frame = frame
videoPlayerLayer.videoGravity = .resizeAspectFill
videoContainerView.layer.addSublayer(videoPlayerLayer)
}
func setupVideoObservers() {
addObserver(self, forKeyPath: "videoPlayer.currentItem.status", options: .new, context: nil)
NotificationCenter.default.addObserver(self, selector: #selector(playerReachedEndOfVideo(notification:)), name: .AVPlayerItemDidPlayToEndTime, object: videoPlayer.currentItem)
NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForegroundNotification), name: .UIApplicationWillEnterForeground, object: videoPlayer.currentItem)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "videoPlayer.currentItem.status" {
videoPlayer.play()
}
}
@objc func playerReachedEndOfVideo(notification: NSNotification) {
let seekTime = CMTime(seconds: 0, preferredTimescale: 1000)
videoPlayer.seek(to: seekTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
videoPlayer.play()
}
@objc func appWillEnterForegroundNotification() {
videoPlayer.play()
}
All the other SO solutions to problems of AVPlayer audio without video that I've come across haven't applied. If anyone has any insight it'd be greatly appreciated.
Thanks in advance.
I had a very similar issue. Try setting the frame of the AVPlayerLayer to a CGRect() of your desired size after you fill the contents. Also you may want to make a Dispatch.Queue Asynchronous call for your didSet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With