使用AVPlayerViewController實(shí)現(xiàn)畫(huà)中畫(huà)(PiP)

在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)暫停視頻。

Adopting Picture in Picture in a Standard Player

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容