Search code examples
iosswiftxcodeavfoundationavplayerlayer

AVPlayerLayer says always nil


I don't understand why it is not working. I pass a videoURL trough a segue to a another ViewController. This works fine.

In the other ViewController I want to play the video. But for some reason it is not working. I unwrap the URL with optional binding. But playerLayer does not accept the URL. It says always nil.

This is the URL: VideoURL Optional(file:///var/mobile/Containers/Data/Application/517BA864-F5CB-4E2C-BE54-D42555569266/Documents/3d.mov)

My code:

var player: AVPlayer?
var playerLayer: AVPlayerLayer?
var videoURL: URL?


    func playVideo() {

    if let _videoURL = videoURL {
        player = AVPlayer(url: _videoURL)

        playerLayer = AVPlayerLayer(layer: player!)

        playerLayer?.frame = contentView.layer.bounds

        playerLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill

        self.contentView.layer.addSublayer(playerLayer!)

        player?.play()
    }

Solution

  • Try creating an AVURLAsset and an AVPlayerItem. Then pass that AVPlayerItem into the AVPlayer rather than trying to use the URL init.

    I tested this with a sample video I downloaded from here. Note there is no sound in this video.

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
        private let videoUrl = Bundle.main.url(forResource: "file_example_MOV_1920_2_2MB", withExtension: "mov")!
        private var videoPlayer: AVPlayer?
        private var playerLayer: AVPlayerLayer?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            playVideo()
        }
    
        func playVideo() {
            let asset = AVURLAsset(url: videoUrl)
            let primaryPlayerItem = AVPlayerItem(asset: asset)
    
            let player = AVPlayer(playerItem: primaryPlayerItem)
    
            let videoLayer = AVPlayerLayer(player: player)
            videoLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
            videoLayer.frame = view.bounds
    
            view.layer.addSublayer(videoLayer)
            videoPlayer = player
            playerLayer = videoLayer
            videoPlayer?.play()
        }
    }