【问题标题】:AVPictureInPictureController doesn't automatically start picture-in-picture when backgrounding the appAVPictureInPictureController 在后台应用程序时不会自动启动画中画
【发布时间】:2020-12-23 15:44:56
【问题描述】:

在为运行 iOS 14(测试版 7)的 iPhone 使用 AVPlayer + AVPlayerLayer + AVPictureInPictureController 创建自定义视频播放器时,当应用进入从 UIButton 操作调用 player.start() 之后的背景。

使用AVPlayerViewController 无法重现此问题,这似乎表明 iOS 14 上的AVPictureInPictureController 通常存在问题,但我想知道是否有其他人遇到过此问题并知道任何解决方法。我也在rdar://8620271@ 下向 Apple 提交了这个问题

示例代码。

import UIKit
import AVFoundation
import AVKit

class ViewController: UIViewController {
    private let player = AVPlayer(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")!)
    private var pictureInPictureController: AVPictureInPictureController!
    private var playerView: PlayerView!
    private var playButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        playerView = PlayerView(frame: CGRect(x: 0, y: 44, width: view.bounds.width, height: 200))
        playerView.backgroundColor = .black
        playerView.playerLayer.player = player
        view.addSubview(playerView)

        playButton = UIButton(frame: CGRect(x: view.bounds.midX - 50, y: playerView.frame.maxY + 20, width: 100, height: 22))
        playButton.setTitleColor(.blue, for: .normal)
        playButton.setTitle("Play", for: .normal)
        playButton.addTarget(self, action: #selector(play), for: .touchUpInside)
        view.addSubview(playButton)

        pictureInPictureController = AVPictureInPictureController(playerLayer: playerView.playerLayer)

        do {
            let audioSession = AVAudioSession.sharedInstance()
            try audioSession.setCategory(.playback)
            try audioSession.setMode(.moviePlayback)
            try audioSession.setActive(true)
        } catch let e {
            print(e.localizedDescription)
        }
    }

    @objc func play() {
        player.play()
    }
}

class PlayerView: UIView {
    override class var layerClass: AnyClass {
        return AVPlayerLayer.self
    }

    var playerLayer: AVPlayerLayer! {
        return layer as? AVPlayerLayer
    }
}

【问题讨论】:

    标签: ios avkit ios14


    【解决方案1】:

    问题的根本原因是双重的:

    1. AVAudioSession.sharedInstance().setActive(true) 必须在 AVPictureInPictureController 初始化之前调用。

    2. AVPlayerLayer 的帧大小必须具有不大于 16/9 的纵横比(作为单独的错误提交,rdar//8689203

    3. 对于 iPad,视频的宽度必须与设备相同(在任何给定方向上)。没有单独的 rdar,因为 Apple 已经承认了另一个错误。

    (上面的例子中没有第二个问题)

    Apple 已经承认了这些错误,并向我报告他们已经/将要修复(雷达实际上导致回复的罕见情况!)

    【讨论】:

    • 关于如何检查 avplayerlayer 的帧大小的任何提示?还是不行。
    【解决方案2】:

    从 iOS 14.2 开始,Apple 公开了一个 api,用于在应用进入后台时启动 PIP:

    if #available(iOS 14.2, *) {
       pictureInPictureController.canStartPictureInPictureAutomaticallyFromInline = true
    }
    

    此外,值得注意的是,Apple 禁止在没有用户手动点击按钮的情况下启动画中画。这将导致应用程序被拒绝。 最好的办法是使用上述 Apple 的 API 来避免被拒绝。

    【讨论】:

      最近更新 更多