文章

iOS中画中画

iOS中画中画

​画中画是一种视频内容呈现方式,是指在一部视频全屏播出的同时,于画面的小面积区域上同时播出另一部视频,被广泛用于电视、视频录像、监控、演示设备等等。

​画中画(PiP, Picture-in-Picture)技术使用一大一小两个视频画面叠加的方式,同时呈现两个视频信号。常见于电视、监控设备。画中画视频的来源可以是不同的电视频道、视频放像机、监控摄像头、游戏机等等。

iOS中的应用

iOS 中的画中画(Picture in Picture, PiP)功能允许用户在使用其他应用的同时继续播放视频或音频。

主要特性包括:

  • 视频和音频在后台继续播放。

  • 系统支持用户同时操作其他应用。

下是如何在 iOS 中实现画中画功能的详细说明

  1. 新建Xcode工程,在工程的Signing & Capabilities中添加Background Modes, 如下选项

    设置

    设置

    设置

  2. 在viewController 里添加下面的代码

    1
    2
    3
    4
    5
    
     do {
          try AVAudioSession.sharedInstance().setCategory(.playback, options: .mixWithOthers)
      } catch {
          print(error)
      }
    

    iOS 的默认音频会话类别是 .soloAmbient,该类别会在应用切换到后台时暂停音频播放。这种默认行为适合大多数不涉及音频播放的应用,但对 PiP 或多媒体应用是不够的,不显式调用会造成pip失败。

    通过调用 setCategory(.playback),你告诉系统:

    • 应用需要后台音频支持。

    • 即使用户切换到其他应用,也要继续播放音频。

  3. AVPlayerViewController

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    private func playVideo(_ videoURL:URL) {
        let player = AVPlayer(url: videoURL)
        let playerViewController = AVPlayerViewController()
        playerViewController.player = player
       
        // 显示播放器
        present(playerViewController, animated: true) {
            player.play()
        }
    }
    

​ 播放视频时,右上角会有pip的快捷按钮

  1. AVPictureInPictureController

    AVPlayerLayer播放视频,主动使用AVPictureInPictureController来唤起pip

    首先初始化AVPlayerLayer 播放视频

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    // 创建 AVPlayerLayer 并添加到视图
    let asset = AVAsset.init(url: url)
    let playerItem = AVPlayerItem.init(asset: asset)
    player = AVPlayer(playerItem: playerItem)
       
    player.isMuted = true
    player.allowsExternalPlayback = true
       
    playerLayer = AVPlayerLayer(player: player)
    playerLayer.frame = .init(origin: .zero, size: .init(width: view.frame.width, height: 300))
    view.layer.addSublayer(playerLayer)
    player.play()
    

    之后手动唤起Pip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
guard AVPictureInPictureController.isPictureInPictureSupported(),
      let playerLayer = playerLayer else { return }

if pipController == nil {
    pipController = AVPictureInPictureController(playerLayer: playerLayer)
    pipController?.delegate = self
    if #available(iOS 14.2, *) {
        pipController?.canStartPictureInPictureAutomaticallyFromInline = true
    } else {
        // Fallback on earlier versions
    }
}
if pipController?.isPictureInPictureActive == true {
    pipController?.stopPictureInPicture()
} else {
    pipController?.startPictureInPicture()
}	

更多的功能

画中画这就讲完了么,当然不是了。还有点小技巧可以实现系统级的弹窗

首先我们来实现AVPictureInPictureControllerDelegate,在下面方法里添加代码。之后在开启画中画,我们自定义的view添加到了画中画的顶层。

1
2
3
4
5
6
7
8
9
func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
    print("画中画即将开始")
    if let window = UIApplication.shared.windows.first {
        let view = UIView()
        view.backgroundColor = .red
        window.addSubview(view)
        view.frame = window.bounds
    }
}

可以添加自定义view,那么添加手机系统级,桌面级的倒计时计时器,记牌器输出等。都可以实现。

是不是觉得播放控制按钮显示和自定义冲突了,在AVPictureInPictureController初始化以后添加一下代码即可隐藏播放控制。

1
pipController?.setValue(1, forKey: "controlsStyle")

虽然添加了自定义内容,但是会发现view大小没办法自定义控制。只是可以按照视频比例缩放,所以要想控制大小,需要制作尺寸合适的视频来显示内容。

总结

  • 了解了画中画在iOS中怎么实现
  • 通过主动控制画中画显示,添加自定义内容。我们可以做很多有意思的事。这个有意思的事在审核可以大概率会被拒绝。自己把握尺度
  • 画中画不可以自定义尺寸,尺寸和视频尺寸相关。如想要控制尺寸,要自己多次调试。

Demo

共有评论
本文由作者按照 CC BY 4.0 进行授权
你是本文第位读者

热门标签