Swift: измените размер AVPlayerLayer, чтобы он соответствовал границам его родительского контейнера.

У меня есть локальное видео, воспроизводимое с использованием AVPlayer и AVPlayerLayer (Swift, iOS 8.2), и мне нужно изменить размер AVPlayerLayer (introPlayerLayer) при изменении размера его родительского вида (introView), в том числе при изменении ориентации. Пока ничего из того, что я пробовал, не работает, а playerLayer имеет неправильный размер и положение.

AVPlayer настраивается с использованием локального видео в формате mp4, а AVPlayerLayer инициализируется с помощью этого проигрывателя. Затем слой добавляется в качестве подслоя к родительскому виду.

Вот мой код:

func playIntro() {
    let path = NSBundle.mainBundle().pathForResource("intro", ofType: "mp4")
    let url  = NSURL.fileURLWithPath(path!)
    let introPlayer           = AVPlayer(URL: url)
    introPlayer.allowsExternalPlayback = false

    var introPlayerLayer = AVPlayerLayer(player: introPlayer)
    introView.layer.addSublayer(introPlayerLayer)
    introPlayerLayer.frame = introView.bounds

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", name: AVPlayerItemDidPlayToEndTimeNotification, object: introPlayer.currentItem)

    introView.hidden = false
    introPlayer.play()
}

Должен ли я добавлять AVPlayerLayer в качестве подслоя UIView или должен создавать подкласс родительского контейнера (UIView), как показано в разделе «Вид игрока» на https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback. HTML. Если да, то как мне написать этот подкласс PlayerView (показан в Objective-C) в Swift? Заранее благодарим вас за любую помощь.


person Connor Laurel    schedule 12.03.2015    source источник
comment
@DeVladinci - Спасибо!   -  person Dalmazio    schedule 21.08.2015


Ответы (3)


Свифт 3.

private func playVideo() {
        guard let path = Bundle.main.path(forResource: "video", ofType:"mp4") else {
            debugPrint("video.m4v not found")
            return
        }
        let player = AVPlayer(url: URL(fileURLWithPath: path))
        var playerLayer: AVPlayerLayer?
        playerLayer = AVPlayerLayer(player: player)
        playerLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        playerLayer!.frame = self.view.frame
        self.view!.layer.addSublayer(playerLayer!)
        player.play()

    }
person Cristian Cardoso    schedule 09.06.2017
comment
Даже не показывает мой плеер при использовании подвида, а не основного вида. - person Jeremy Hicks; 06.12.2018
comment
Хороший ответ. Спасибо. - person KSR; 22.07.2019

Я смог сделать то, что вы пытаетесь сделать, я думаю, в моем собственном проекте. Это без подклассов. Вот мой код:

override func viewWillLayoutSubviews() {
   previewScene()
}

func previewScene() {
    var firstAsset: AVAsset!, secondAsset: AVAsset!, thirdAsset: AVAsset!


     firstAsset = MediaController.sharedMediaController.s3Shot1
     secondAsset = MediaController.sharedMediaController.s3Shot2
     thirdAsset  = MediaController.sharedMediaController.s3Shot3


    if firstAsset != nil && secondAsset != nil && thirdAsset != nil {
        let assets = [firstAsset, secondAsset, thirdAsset]
        var shots = [AVPlayerItem]()

        for item in assets {
            let shot = AVPlayerItem(asset: item)
            shots.append(shot)
        }

        self.videoPlayer = AVQueuePlayer(items: shots)
        self.playerLayer = AVPlayerLayer(player: self.videoPlayer)
        self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
         AVPlayerItemDidPlayToEndTimeNotification, object: self.videoPlayer.items().last)
        self.videoPreviewLayer.layer.addSublayer(playerLayer)
        self.playerLayer.frame = self.videoPreviewLayer.bounds

    }

}
person Eric Mentele    schedule 14.11.2015
comment
videoPreviewLayer — это прямоугольное представление внутри моего контроллера представления. - person Eric Mentele; 15.11.2015
comment
@IBOutlet слабый var videoPreviewLayer: UIView! - person Eric Mentele; 15.11.2015
comment
Можете предложить мне здесь: stackoverflow.com/questions/54745359/ - person Anand Gautam; 18.02.2019

introView.layer.masksToBounds = true

также может быть полезно

person FromTheStix    schedule 09.06.2016
comment
Не могли бы вы вообще расширить этот ответ? stackoverflow.com/help/how-to-answer - person Rich Benner; 09.06.2016
comment
@RichBenner У меня возникла проблема с тем, чтобы мой видеослой оставался в пределах родительского слоя. Я использовал self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill, чтобы заполнить рамку, но также нуждался в masksToBounds = true, чтобы держать ее в границах родительского слоя. Я не опытный iOS-разработчик, но мне это помогло. - person FromTheStix; 10.06.2016