Swift实现Picture in Picture(画中画)

2024-04-08  本文已影响0人  Hengry

在 Swift 中实现 Picture in Picture(画中画)功能,你可以使用 AVKit 框架提供的 AVPictureInPictureController 类。这个类允许你在 iOS 设备上播放视频并支持画中画模式。

下面是一个简单的示例代码,演示如何在 Swift 中使用 AVPictureInPictureController 实现 Picture in Picture 功能:

import AVKit

class ViewController: UIViewController, AVPictureInPictureControllerDelegate {

    var playerViewController: AVPlayerViewController!
    var player: AVPlayer!
    var pipController: AVPictureInPictureController!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 创建 AVPlayer 对象
        let videoURL = URL(string: "YOUR_VIDEO_URL")
        player = AVPlayer(url: videoURL!)

        // 创建 AVPlayerViewController 并设置 player
        playerViewController = AVPlayerViewController()
        playerViewController.player = player

        // 设置 Picture in Picture 控制器并设置代理
        pipController = AVPictureInPictureController(playerLayer: playerViewController.playerLayer)
        pipController.delegate = self

        // 添加 AVPlayerViewController 到当前视图控制器
        addChild(playerViewController)
        view.addSubview(playerViewController.view)
        playerViewController.view.frame = view.bounds
        playerViewController.didMove(toParent: self)

        // 开始播放视频
        player.play()
    }

    // 实现 AVPictureInPictureControllerDelegate 代理方法
    func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
        // Picture in Picture 模式已经开始
        print("Picture in Picture 模式已经开始")
    }

    func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
        // Picture in Picture 模式已经结束
        print("Picture in Picture 模式已经结束")
    }

    // 添加按钮或手势来启动 Picture in Picture 模式
    @IBAction func startPictureInPicture(_ sender: Any) {
        if pipController.isPictureInPicturePossible {
            pipController.startPictureInPicture()
        }
    }
}

在这个示例中,我们首先创建了一个 AVPlayer 对象来播放视频,并将其设置给一个 AVPlayerViewController 对象。然后,我们创建了一个 AVPictureInPictureController 对象,并将 AVPlayerViewController 的 playerLayer 设置给它。最后,我们实现了 AVPictureInPictureControllerDelegate 协议,并在代理方法中处理 Picture in Picture 模式的开始和结束。

请确保替换示例代码中的 "YOUR_VIDEO_URL" 为你自己的视频 URL。此外,你可以通过添加按钮或手势来启动 Picture in Picture 模式,以便用户可以在需要时手动启动。

下面是一个示例代码,演示了如何在 Swift 中使用 AVPlayer 和 AVPlayerLayer 实现视频播放,并结合画中画功能:

import UIKit
import AVKit

class ViewController: UIViewController {
    
    var player: AVPlayer!
    var playerLayer: AVPlayerLayer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置音频会话
        do {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
            try AVAudioSession.sharedInstance().setActive(true)
        } catch {
            print("Failed to configure audio session:", error)
        }
        
        // 创建 AVPlayer 对象
        guard let videoURL = Bundle.main.url(forResource: "video", withExtension: "mp4") else { return }
        player = AVPlayer(url: videoURL)
        
        // 创建 AVPlayerLayer 并添加到视图层上
        playerLayer = AVPlayerLayer(player: player)
        playerLayer.frame = view.bounds
        view.layer.addSublayer(playerLayer)
    }
    
    // 播放按钮点击事件
    @IBAction func playButtonTapped(_ sender: Any) {
        player.play()
    }
    
    // 进入画中画模式按钮点击事件
    @IBAction func pipButtonTapped(_ sender: Any) {
        let pipController = AVPictureInPictureController(playerLayer: playerLayer)
        if pipController.isPictureInPicturePossible {
            pipController.startPictureInPicture()
        }
    }
}

这个示例代码中,假设你的项目中有一个名为 video.mp4 的视频文件,代码会使用 AVPlayer 和 AVPlayerLayer 来播放该视频。当用户点击播放按钮时,视频会在当前视图中播放;当用户点击进入画中画模式按钮时,视频会自动进入画中画模式,继续在一个小窗口中播放。

要实现自定义播放器并支持画中画功能,你需要遵循以下步骤:

下面是一个示例代码,演示了如何实现自定义播放器并支持画中画功能:

import UIKit
import AVKit

class CustomPlayerViewController: UIViewController, AVPictureInPictureControllerDelegate {
    
    var player: AVPlayer!
    var playerLayer: AVPlayerLayer!
    var pipController: AVPictureInPictureController!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 创建 AVPlayer 对象
        guard let videoURL = Bundle.main.url(forResource: "video", withExtension: "mp4") else { return }
        player = AVPlayer(url: videoURL)
        
        // 创建 AVPlayerLayer 并添加到视图层上
        playerLayer = AVPlayerLayer(player: player)
        playerLayer.frame = view.bounds
        view.layer.addSublayer(playerLayer)
        
        // 设置画中画控制器
        pipController = AVPictureInPictureController(playerLayer: playerLayer)
        pipController.delegate = self
        
        // 添加画中画按钮
        let pipButton = UIButton(type: .system)
        pipButton.setTitle("画中画", for: .normal)
        pipButton.addTarget(self, action: #selector(pipButtonTapped), for: .touchUpInside)
        view.addSubview(pipButton)
        pipButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            pipButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            pipButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20)
        ])
    }
    
    @objc func pipButtonTapped() {
        if pipController.isPictureInPicturePossible {
            pipController.startPictureInPicture()
        }
    }
    
    // 实现 AVPictureInPictureControllerDelegate 协议方法
    func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
        print("画中画模式已经开始")
    }
    
    func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
        print("画中画模式已经结束")
    }
}

在这个示例中,我们创建了一个自定义播放器视图控制器 CustomPlayerViewController,其中包含一个自定义播放器和一个画中画按钮。当用户点击画中画按钮时,会启动画中画模式。我们还实现了 AVPictureInPictureControllerDelegate 协议来处理画中画模式的状态变化。最后,我们将 AVPlayerLayer 添加到 AVPictureInPictureController 中,以便支持画中画功能。

腾讯直播拉流播放器V2TXLivePlayer支持画中画

/**
 * 开启画中画功能,仅支持直播和快直播播放
 *
 * @param enable      YES: 开启画中画功能; NO: 关闭画中画功能。【默认值】: NO。
 * @return 返回值 {@link V2TXLiveCode}。
 *         - V2TXLIVE_OK: 成功。
 */
- (V2TXLiveCode)enablePictureInPicture:(BOOL)enable;
// 开启画中画功能
let resCode = player.enablePicture(inPicture: true)
ZYLogUtil.zy_debug("画中画 resCode:\(resCode.rawValue)")

开启后台画中画权限,即可实现

        // 设置音频会话
        do {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
            try AVAudioSession.sharedInstance().setActive(true)
        } catch {
            print("Failed to configure audio session:", error)
        }
image.png IMG_0196.PNG
上一篇下一篇

猜你喜欢

热点阅读