AVPlayerViewController在全屏返回后停止播放

9
我有一个AVPlayerViewController,我使用AVPlayer和一些AVPlayerItem进行初始化(iOS 10,Xcode 8,Objective C)。AVPlayerViewController在某个子视图中“内联”显示,并且原生播放控件完美地工作。
当我按原生全屏按钮时,它也可以正常工作并切换到全屏模式(左上角有完成按钮)。
我的问题是当我按完成按钮从全屏返回时,播放器会因某种原因停止播放,重置自己,并且如果我检查.currentItem,则看到它为nil。
这里发生了什么?为什么AVPlayerViewController不能在从/到全屏切换之间维护其AVPlayerItem?

1
这里发生了什么?好问题。但是您根本没有展示任何代码,所以谁知道呢?您所描述的行为通常不会发生;例如,下载并运行此示例项目:https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/bk2ch15p660EmbeddedAVKit 当您播放电影并扩展到全屏然后点击"完成"时,我们暂停,就这样;您可以从那个点恢复。没有什么被"重置"。所以_你_一定做了一些重置AVPlayer的事情。但是您没有提供任何线索。 - matt
你说得对,我应该发布一些代码。我将发布我的解决方案,并附上一些代码。 - mllm
4个回答

14

由于目前AVPlayerViewController的行为是在退出全屏时暂停,因此我们可以通过实现代理,在退出全屏时调用play()

class VideoView {

    private var playerViewController: AVPlayerViewController?

    func something() {

        playerViewController = AVPlayerViewController()

        // Other setups

        playerViewController?.delegate = self
    }
}

extension VideoView: AVPlayerViewControllerDelegate {

    func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {

        // The system pauses when returning from full screen, we need to 'resume' manually.
        coordinator.animate(alongsideTransition: nil) { transitionContext in
            self.playerViewController?.player.play()
        }
    }
}

2
对于那些查找此问题和答案的人,请注意它还可以稍微改进,因为上述解决方案将始终在退出全屏时播放视频,即使它被暂停。我通过扩展AVPlayerViewController,重写viewWillAppear(它会在将要结束全屏前发生)并设置一个“pausedTemporarily”布尔值objc_getAssociatedObject,如果视频正在播放(基于timeControlStatus),则添加到扩展中来实现这一点。然后,在willEndFullScreen中添加一个pausedTemporarily检查,然后清除该值。效果很好! - TahoeWolverine
1
苹果公司的 AVPlayerViewController 文档[明确说明](https://developer.apple.com/documentation/avkit/avplayerviewcontroller#overview)不应该被子类化,因此我不确定这是否是未来 iOS 版本的可靠修复方法。 - NRitH
2
@NRitH 在这个例子中没有子类化(除非我漏看了什么)。 class VideoView 没有继承任何东西,扩展只是在扩展 VideoView。当然,我很想看到一个更简洁的解决方案。我正在实现一个委托,仅此而已。 - bauerMusic
抱歉,@bauerMusic——我是在回复@TahoeWolverine有关扩展AVPlayerViewController的评论。 - NRitH

2
跟上面答案https://dev59.com/SJ3ha4cB1Zd3GeqPXqdE#58818395和评论AVPlayerViewController stops after returning from full screen所述,如果想知道AVPlayerViewController是否正在播放,可以使用这个扩展。
extension AVPlayer {
    var isPlaying: Bool {
        rate != 0 && error == nil
    }
}

 @objc func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        let isPlaying = self.playerViewController.player?.isPlaying ?? false
        // The system pauses when returning from full screen, we need to 'resume' manually.
        coordinator.animate(alongsideTransition: nil) { _ in
            if isPlaying {
                self.playerViewController.player?.play()
            }
        }
    }

0

参考@matt的建议,我发现我的做法不同之处在于设置了AVPlayerViewControllerplayer属性,但没有设置AVPlayerItem,只是在之后设置它(依赖于replaceCurrentItemWithPlayerItem())。

换句话说 - 根据我的经验,您应该使用URL或任何AVPlayerItem初始化AVPlayerViewControllerAVPlayer,然后将AVPlayerViewController添加为子视图控制器。

不使用自动布局的代码:

if let playerView = self.playerView {
    let playerItem = AVPlayerItem(url: self.url)
    let player = AVPlayer(playerItem: playerItem)

    let playerVc = AVPlayerViewController()
    playerVc.player = player

    self.addChildViewController(playerVc)
    playerVc.view.frame = playerView.bounds
    playerView.addSubview(playerVc.view)
    playerVc.didMove(toParentViewController: self)

    player.play()
}

3
你好,@mllm,我也遇到了同样的问题。我正在使用和你相同的代码。 但是当我切换到全屏模式时,视频能够保持播放/暂停模式进入全屏。但是当退出全屏模式时,视频总是会在按下退出按钮时暂停在相同的时间点。 - Vivek Shah
该问题与当用户退出全屏模式时自动暂停有关... - Mohammad Reza Koohkan

-1

以上解决方案将始终在退出全屏后播放视频,即使它已暂停。

添加以下内容以修复:

func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    let 获取播放状态 = self.parent.player.isPlaying
    
       // The system pauses when returning from full screen, we need to 'resume' manually.
       coordinator.animate(alongsideTransition: nil) { transitionContext in
           if 获取播放状态 {
               self.parent.player.play()
           }
       }
   }

而且

extension AVPlayer {
    var isPlaying: Bool {
        return rate != 0 && error == nil
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接