Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVPlayer in UICollectionViewCell plays sound but doesn't show video

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.

like image 270
MT1asli8ghwoi Avatar asked Dec 01 '25 06:12

MT1asli8ghwoi


1 Answers

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.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!