iOS中画中画
画中画是一种视频内容呈现方式,是指在一部视频全屏播出的同时,于画面的小面积区域上同时播出另一部视频,被广泛用于电视、视频录像、监控、演示设备等等。
画中画(PiP, Picture-in-Picture)技术使用一大一小两个视频画面叠加的方式,同时呈现两个视频信号。常见于电视、监控设备。画中画视频的来源可以是不同的电视频道、视频放像机、监控摄像头、游戏机等等。
iOS中的应用
iOS 中的画中画(Picture in Picture, PiP)功能允许用户在使用其他应用的同时继续播放视频或音频。
主要特性包括:
-
视频和音频在后台继续播放。
-
系统支持用户同时操作其他应用。
下是如何在 iOS 中实现画中画功能的详细说明
-
新建Xcode工程,在工程的Signing & Capabilities中添加Background Modes, 如下选项
-
在viewController 里添加下面的代码
1 2 3 4 5
do { try AVAudioSession.sharedInstance().setCategory(.playback, options: .mixWithOthers) } catch { print(error) }
iOS 的默认音频会话类别是
.soloAmbient
,该类别会在应用切换到后台时暂停音频播放。这种默认行为适合大多数不涉及音频播放的应用,但对 PiP 或多媒体应用是不够的,不显式调用会造成pip失败。通过调用
setCategory(.playback)
,你告诉系统:-
应用需要后台音频支持。
-
即使用户切换到其他应用,也要继续播放音频。
-
-
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的快捷按钮
-
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中怎么实现
- 通过主动控制画中画显示,添加自定义内容。我们可以做很多有意思的事。这个有意思的事在审核可以大概率会被拒绝。自己把握尺度
- 画中画不可以自定义尺寸,尺寸和视频尺寸相关。如想要控制尺寸,要自己多次调试。