在iOS開(kāi)發(fā)視頻播放畫(huà)中畫(huà)(PiP)最簡(jiǎn)單的方法是使用AVPlayerViewController實(shí)現(xiàn)現(xiàn)標(biāo)準(zhǔn)播放器,實(shí)際上使用AVPlayerViewController播放器時(shí)將自動(dòng)支持畫(huà)中畫(huà)(PiP)功能。
實(shí)現(xiàn)代碼
- 配置Audio Playback Behavior,需要設(shè)置App 的AVAudioSession的Category為playback模式
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback, options: [])
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("無(wú)法設(shè)置音頻會(huì)話類別: \(error)")
}
import UIKit
import AVKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .black
}
func initPlayer() {
let _videoURL = "***播放地址***"
let _player = AVPlayer(url:_videoURL)
let _playerVC = AVPlayerViewController()
_playerVC.delegate = self
if AVPictureInPictureController.isPictureInPictureSupported() {
_playerVC.allowsPictureInPicturePlayback = true
if #available(iOS 14.2, *) {
_playerVC.canStartPictureInPictureAutomaticallyFromInline = true
}
}
_playerVC.player = _player
self.present(playerViewController, animated: true) {
_player.play()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.initPlayer()
}
}
PiP代理方法
// 通知代理 AVPlayerViewController 即將開(kāi)始全屏顯示其內(nèi)容
func playerViewController(_ playerViewController: AVPlayerViewController, willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
print("")
}
// 通知代理 AVPlayerViewController 將停止全屏顯示其內(nèi)容
func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
print("")
}
// 即將啟動(dòng)畫(huà)中畫(huà)(Picture in Picture, PiP)模式時(shí)調(diào)用此方法
// 可以在此方法中設(shè)置或更新一些相關(guān)的 UI 元素或狀態(tài),以反映視頻即將進(jìn)入畫(huà)中畫(huà)模式。
func playerViewControllerWillStartPictureInPicture(_ playerViewController: AVPlayerViewController) {
print("")
}
// 已經(jīng)進(jìn)入畫(huà)中畫(huà)模式時(shí)調(diào)用此方法
// 用法:用于更新 UI 或進(jìn)行其他準(zhǔn)備工作,以支持畫(huà)中畫(huà)模式。
func playerViewControllerDidStartPictureInPicture(_ playerViewController: AVPlayerViewController) {
print("")
}
// 當(dāng)畫(huà)中畫(huà)模式啟動(dòng)失敗時(shí)調(diào)用此方法
// 用法:處理畫(huà)中畫(huà)模式啟動(dòng)失敗時(shí)的錯(cuò)誤。
func playerViewController(_ playerViewController: AVPlayerViewController, failedToStartPictureInPictureWithError error: Error) {
print("")
}
// 即將結(jié)束畫(huà)中畫(huà)模式時(shí)調(diào)用此方法
// 用法:在視頻退出畫(huà)中畫(huà)模式前進(jìn)行收尾工作,更新 UI 或做一些清理
func playerViewControllerWillStopPictureInPicture(_ playerViewController: AVPlayerViewController) {
print("")
}
// 已經(jīng)結(jié)束畫(huà)中畫(huà)模式時(shí)調(diào)用此方法
// 用法:用于恢復(fù)正常播放狀態(tài),或者處理畫(huà)中畫(huà)模式結(jié)束后的邏輯
func playerViewControllerDidStopPictureInPicture(_ playerViewController: AVPlayerViewController) {
print("PiPVC:playerViewControllerDidStopPictureInPicture")
}
// 返回 true 或 false,指示在啟動(dòng)畫(huà)中畫(huà)時(shí)播放器是否應(yīng)自動(dòng)關(guān)閉。
// 用法:如果希望在進(jìn)入畫(huà)中畫(huà)模式時(shí)關(guān)閉 AVPlayerViewController,則返回 true,否則返回 false。
func playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart(_ playerViewController: AVPlayerViewController) -> Bool {
return true
}
// 當(dāng)畫(huà)中畫(huà)模式結(jié)束時(shí),恢復(fù)用戶界面。如果 AVPlayerViewController 在啟動(dòng)畫(huà)中畫(huà)后關(guān)閉,該方法可用于恢復(fù) UI。
// 用法:用于確保在結(jié)束畫(huà)中畫(huà)后,用戶界面恢復(fù)到正確的狀態(tài)。確保調(diào)用 completionHandler 來(lái)表示恢復(fù)工作已經(jīng)完成。
func playerViewController(_ playerViewController: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
completionHandler(true)
}
PS1:從iOS 14開(kāi)始,畫(huà)中畫(huà)用戶界面提供了允許用戶在視頻中向前和向后跳轉(zhuǎn)的控件。默認(rèn)情況下,系統(tǒng)為iOS14或更高版本中鏈接的應(yīng)用程序啟用這些控件。如果您需要限制跳過(guò)內(nèi)容以獲得法律免責(zé)聲明或廣告,請(qǐng)?jiān)谝曨l的所需部分使用requiresLinearPlayback。一旦您可以再次允許seek,請(qǐng)將此屬性設(shè)置為false。
PS2:當(dāng)用戶在播放器界面中選擇PiP按鈕時(shí),PiP播放開(kāi)始。在iOS和iPadOS中,如果您的視頻以全屏模式播放,并且用戶退出應(yīng)用程序,則PiP播放會(huì)自動(dòng)開(kāi)始。當(dāng)視頻的寬度沒(méi)有填滿整個(gè)屏幕時(shí),請(qǐng)使用canStartPictureInPictureAutomaticyFromInline來(lái)指示視頻是主要焦點(diǎn)。在任何一種情況下,播放器窗口都會(huì)最小化為可移動(dòng)的浮動(dòng)窗口。
通常情況下,系統(tǒng)會(huì)自動(dòng)暫停視頻的場(chǎng)景下,因此您不需要根據(jù)激活狀態(tài)暫停視頻。