ios swift画中画技术尝试
继上篇:iOS swift 后台运行应用尝试失败-CSDN博客
为什么想到画中画,起初是看到后台模式里有一个picture in picture,去了解了后发现这个就是小窗口视频播放,方便用户执行多任务。看小窗口视频的同时,可以作其他的事情。
画中画功能在20世纪80年代开始在电视机中应用,使得用户可以在一个屏幕上同时观看两个频道的内容。
这个技术在安卓里已经非常普遍了。各种视频内容网站都有类似功能。
而苹果支持画中画是在ios14已经开始支持。目前在使用的大多数机型,比如iphone 8p,升级系统后可到ios16.7,都能支持画中画技术。
后台任务苹果管理太严格,不好搞,那么使用画中画这种技术,直接做成多任务,这样也是另一条可以尝试的路径。
1、标准PIP使用
首先,标准写法是采用AVPlayer,输入url需要是MP4等视频文件,如果是加密后的网址,无法播放,比如b站的网址。
创建AVPlayer,使用AVPlayerLayer来初始化AVPictureInPictrueController。
// 创建 AVPlayer 对象let videoURL = URL(string: "https://media.w3.org/2010/05/sintel/trailer.mp4")!player = AVPlayer(url: videoURL)// 创建 AVPlayerLayer 并添加到视图层上playerLayer = AVPlayerLayer(player: player)playerLayer.frame = view.boundsview.layer.addSublayer(playerLayer)// 设置画中画控制器pipController = AVPictureInPictureController(playerLayer: playerLayer)pipController.delegate = selfplayer.play() // 直接播放
按home键退出,就会自动启动小窗口继续播放视频。
这里有一个坑,需要初始化音频,否则播放mp4无声音,且画中画也不会触发。
do {// 设置AVAudioSession为后台模式try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)try AVAudioSession.sharedInstance().setActive(true)} catch {print("无法设置AVAudioSession: \(error)")}
视频画中画,iphone 8p_哔哩哔哩_bilibili
2、摄像头预览
摄像头捕捉并预览,这个算法也很容易找到,使用AVCaptureSession
func setupCamera(forgroundFlag: Bool, view: UIView) {farView = viewflag = forgroundFlagcaptureSession = AVCaptureSession()captureSession?.beginConfiguration()captureSession?.sessionPreset = .highguard let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front) else {print("No front camera available")return}guard let input = try? AVCaptureDeviceInput(device: captureDevice) else {print("Unable to access front camera")return}captureSession!.addInput(input)videoOutput = AVCaptureVideoDataOutput()videoOutput?.automaticallyConfiguresOutputBufferDimensions = truevideoOutput!.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))captureSession!.addOutput(videoOutput!)if (forgroundFlag) {videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)guard let preLayer = videoPreviewLayer else { return }preLayer.frame = view.frameview.layer.addSublayer(preLayer)// 设置 UILabel 的属性label = UILabel()label!.text = "Hello, Swift!" // 设置文本内容label!.textColor = UIColor.systemBlue // 设置文本颜色label!.font = UIFont.systemFont(ofSize: 20) // 设置字体和大小label!.textAlignment = .left // 设置文本对齐方式label!.numberOfLines = 0 // 设置行数,0表示自动换行// 设置 UILabel 的位置和大小label!.frame = CGRect(x: 8, y: 20, width: 200, height: 30)}captureSession?.commitConfiguration()}
AVCaptureSession输出的是AVCaptureVideoPreviewLayer,这个layer无法直接用来初始化AVPictureInPictrueController。
3、摄像头输出PIP
swift代码在标准案例上实现都很简洁,但要自定义实现一些功能时,就会发现材料很难找。
比如怎样把摄像头预览与PIP结合。
深度搜索AI给出了一个结果,看上去好像可以,实践下来编辑都不能通过。但是它给出了一个提示,就是AVSampleBufferDisplayLayer。
这里吐槽下AI,最喜欢把不可用的东西包装成很好看的样子,在技术搜索方面,某些时候还不如原始的搜索引擎来得方便。
搜索AVCaptureVideoPreviewLayer转为AVSampleBufferDisplayLayer,也有方法,但是算法看上去稍显复杂。
官方文档Adopting Picture in Picture in a Custom Player | Apple Developer Documentation里也提到了可以使用AVSampleBufferDisplayLayer来初始化PIPController。
网上另一篇文章,说在捕获处理接口里,还有一个视频数据
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)
CMSampleBuffer可以直接转为AVSampleBufferDisplayLayer,使用enqueu接口,如下:
func setupSampleBufferDisplayLayer() {sampleBufferDisplayLayer = AVSampleBufferDisplayLayer()sampleBufferDisplayLayer.frame = view.boundssampleBufferDisplayLayer.videoGravity = .resizeAspectview.layer.addSublayer(sampleBufferDisplayLayer)}func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
。。。。。。 if (sampleBufferDisplayLayer.status == AVQueuedSampleBufferRenderingStatus.failed) {sampleBufferDisplayLayer.flush() // 异常处理}sampleBufferDisplayLayer.enqueue(sampleBuffer)
。。。。。。
这样整个流程就能打通了。
通过AVSampleBufferDisplayLayer,可以用任何视频流来初始化AVPictureInPictureController。
private func setupPiPController() {guard AVPictureInPictureController.isPictureInPictureSupported() else {print("Picture in Picture is not supported on this device")return}print("support pip!!!")if pipController == nil {pipController = AVPictureInPictureController(contentSource: .init(sampleBufferDisplayLayer: sampleBufferDisplayLayer, playbackDelegate: self))}if let pipController = pipController {pipController.delegate = selfif pipController.isPictureInPicturePossible {pipController.startPictureInPicture()}}}
4、摄像头多任务需要硬件支持
前面生成的工程,在iphone 8p上测试效果如下,进入画中画模式时,在1s以内视频捕获就停止了。
摄像头画中画,iphone 8p_哔哩哔哩_bilibili
原因在于苹果对摄像头硬件管理非常严格,摄像头开小窗口,那么用户就可能用摄像头打开另一个任务,意味着摄像头需要支持多任务。
参考官方说明:



增加代码检查如下:
func setupCamera(forgroundFlag: Bool, view: UIView) {
。。。。。。 guard let tempcap = captureSession else { return }if (tempcap.isMultitaskingCameraAccessSupported) {print("camera supp multitask")// Enable use of the camera in multitasking modes.captureSession?.isMultitaskingCameraAccessEnabled = true} else {print("camera not supp multitask")}captureSession?.commitConfiguration()}
从调试打印来看,iphone 8p的摄像头不支持多任务。
根据AI查询结果,可能需要iphone 12以上的机型才能支持摄像头多任务。

对于AI返回结果比较存疑,因为多次返回的结果可能会不一样。比如iphone XR,有的说支持,有的说不支持。
参考另外的官方文章,视频通话、直播画中画都是一样的。
Adopting Picture in Picture for video calls | Apple Developer Documentation
因为本人手上只有iphone 8p,没有其他新机型,所以后面的调试验证没法继续下去了。在没有订单推动情况下,也不会投入了。
如果有相关项目需求的,可以找我咨询合作。
相关文章:
ios swift画中画技术尝试
继上篇:iOS swift 后台运行应用尝试失败-CSDN博客 为什么想到画中画,起初是看到后台模式里有一个picture in picture,去了解了后发现这个就是小窗口视频播放,方便用户执行多任务。看小窗口视频的同时,可以作其他的事情…...
MyBatis 写法
MyBatis 高效使用技巧 常见 MyBatis 使用技巧,这些技巧有助于简化数据库操作,提高开发效率,并增强系统的性能。 1. 动态 SQL 动态 SQL 让开发者能够依据参数灵活地构建 SQL 语句,避免了手动拼接字符串带来的复杂性和错误风险。…...
Three城市引擎地图插件Geo-3d
一、简介 基于Three开发,为Three 3D场景提供GIS能力和城市底座渲染能力。支持Web墨卡托、WGS84、GCJ02等坐标系,支持坐标转换,支持影像、地形、geojson建筑、道路,植被等渲染。支持自定义主题。 二、效果 三、代码 //插件初始化…...
【贪心算法】洛谷P1106 - 删数问题
2025 - 01 - 22 - 第 46 篇 【洛谷】贪心算法题单 - 【贪心算法】 - 【学习笔记】 作者(Author): 郑龙浩 / 仟濹(CSND账号名) 目录 文章目录 目录P1106 删数问题题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路代码 P1106 删数问题 题目描述 键盘输入一个高…...
WPS计算机二级•幻灯片的页面布局
听说这是目录哦 设置PPT页面尺寸🖼️PPT母版怎么用🎨巧用PPT母版统一修改 字体颜色与背景🎡如何快速更改应用 幻灯片中的不同母版👑能量站😚 设置PPT页面尺寸🖼️ 在制作PPT时,我们需要先选定一…...
从入门到精通:HttpClient深度剖析与实战指南
一、引言 1.1 背景引入 在当今数字化时代,网络编程已成为软件开发中不可或缺的一部分。而 HTTP 通信作为网络编程的核心,承担着客户端与服务器之间数据传输的重任。无论是 Web 应用、移动应用,还是分布式系统,HTTP 协议都扮演着…...
IoTDB 2025 春节值班与祝福
2025 春节快乐 瑞蛇迎吉庆,祥光映华年,2025 春节已近在眼前。社区祝福 IoTDB 的所有关注者、支持者、使用者 2025 新年快乐,“蛇”来运转! IoTDB 团队的春节放假时间为 2025 年 1 月 27 日至 2 月 4 日,1 月 25 日、26…...
Java 大视界 -- Java 大数据中的隐私增强技术全景解析(64)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
【2024年华为OD机试】 (A卷,100分)- 整理扑克牌(JavaScriptJava PythonC/C++)
一、问题描述 题目描述 给定一组数字,表示扑克牌的牌面数字,忽略扑克牌的花色,请按如下规则对这一组扑克牌进行整理: 步骤1:分组形成组合牌 炸弹:当牌面数字相同张数大于等于4时。葫芦:3张相同牌面数字 + 2张相同牌面数字,且3张牌与2张牌不相同。三张:3张相同牌面数…...
周末总结(2024/01/25)
工作 人际关系核心实践: 要学会随时回应别人的善意,执行时间控制在5分钟以内 坚持每天早会打招呼 遇到接不住的话题时拉低自己,抬高别人(无阴阳气息) 朋友圈点赞控制在5min以内,职场社交不要放在5min以外 职场的人际关系在面对利…...
Apache Flink 概述学习笔记
一、引言 在大数据处理领域,Apache Flink 是一个极具影响力的开源流批一体化计算框架,它以其独特的架构和强大的功能,为大规模数据处理提供了高效、灵活的解决方案。 二、基本概念 Flink 是什么:Flink 是一个分布式流批处理框架…...
双足机器人开源项目
双足机器人(也称为人形机器人或仿人机器人)是一个复杂的领域,涉及机械设计、电子工程、控制理论、计算机视觉等多个学科。对于想要探索或开发双足机器人的开发者来说,有许多开源项目可以提供帮助。这些项目通常包括硬件设计文件、…...
Linux 部署 Java 项目:Tomcat、Redis、MySQL 教程
在 Linux 服务器上部署 Java 项目通常需要配置应用服务器(如 Tomcat)、数据库(如 MySQL)和缓存服务器(如 Redis)。本文将详细介绍如何在 Linux 环境中部署一个 Java 项目,涵盖 Tomcat、Redis 和…...
Django 多环境配置实战指南
在现代 Web 开发中,一个项目通常需要在多个环境中运行,例如开发环境、测试环境和生产环境。每个环境的配置可能不同,比如数据库连接、调试模式、密钥等。为了确保项目在不同环境中的灵活性和安全性,我们需要合理地管理多环境配置。 本文将详细介绍如何在 Django 项目中实现…...
【C++高并发服务器WebServer】-6:信号
本文目录 信号的概念1.1 core文件1.2 kill命令1.3 alarm函数1.4 setitimer调用1.5 signal捕捉信号1.6 信号集1.7 内核实现信号捕捉的过程1.8 sigaction1.9 sigchld 信号的概念 信号是 Linux 进程间通信的最古老的方式之一,是事件发生时对进程的通知机制,…...
HBase的原理
一、什么是HBase HBase是一个分布式,版本化,面向列的数据库,依赖Hadoop和Zookeeper (1)HBase的优点 提供高可靠性、高性能、列存储、可伸缩、实时读写的数据库系统 (2) HBase 表的特性 Region包含多行 列族包含多…...
[b01lers2020]Life on Mars1
打开题目页面如下 看了旁边的链接,也没有什么注入点,是正常的科普 利用burp suite抓包,发现传参 访问一下 http://5edaec92-dd87-4fec-b0e3-501ff24d3650.node5.buuoj.cn:81/query?searchtharsis_rise 接下来进行sql注入 方法一…...
Go学习:常量
变量:程序运行期间,可以改变的量,变量声明需要使用 var 常量:程序运行期间,不可以改变的量,常量声明需要使用 const 目录 1. 常量不允许修改 2. 常量赋值不使用 : 3. 常量能够自动推导类型 1. 常量不允许…...
Python 爬虫——爬取Web页面图片
从网页页面上批量下载jpg格式图片,并按照数字递增命名保存到指定的文件夹。 Web地址:http://p.weather.com.cn/2017/06/2720826.shtml#p1 import urllib import urllib.request import re #正则表达式#解析页面 def load_page(url):requesturllib.reque…...
微信小程序1.1 微信小程序介绍
1.1 微信小程序介绍 内容提要 1.1 什么是微信小程序 1.2 微信小程序的功能 1.3 微信小程序使用场景 1.4 微信小程序能取代App吗 1.5 微信小程序的发展历程 1.6微信小程序带来的机会...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...
pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...
Springboot 高校报修与互助平台小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,高校报修与互助平台小程序被用户普遍使用,为…...
