问题描述
在运行iOS 14(测试版7)的iPhone上使用AVPlayer
+ AVPlayerLayer
+ AVPictureInPictureController
创建自定义视频播放器时,视频不会自动输入画中画从UIButton动作调用player.start()
后,应用进入后台模式。
使用AVPlayerViewController
并不能重现该问题,这似乎通常表明iOS 14上的AVPictureInPictureController
有问题,但是我想知道是否还有其他人遇到了这个问题并知道解决方法。我还在rdar://8620271
示例代码。
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
}
}
解决方法
问题的根本原因最终是双重的:
-
在初始化
-
AVPictureInPictureController
。 -
AVPlayerLayer
的帧大小必须具有不大于16/9的宽高比(作为单独的错误rdar//8689203
提交) -
对于iPad,视频的宽度必须与设备相同(在任何给定的方向上)。没有单独的雷达,因为苹果已经承认了另一个错误。
AVAudioSession.sharedInstance().setActive(true)
之前,必须先调用(上面的示例中没有第二个问题)
,从 iOS 14.2 开始,Apple 公开了一个 api,用于在应用进入后台时启动 PIP:
if #available(iOS 14.2,*) {
pictureInPictureController.canStartPictureInPictureAutomaticallyFromInline = true
}
另外,值得注意的是,Apple 禁止在没有用户手动点击按钮的情况下启动画中画。这将导致应用程序被拒绝。 最好的办法是使用上面提到的 Apple 的 API 以避免被拒绝。