在使应用程序背景化时,AVPictureInPictureController不会自动启动画中画

问题描述

在运行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
    }
}

解决方法

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

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

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

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

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

,

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

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

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