大多数浏览器和
Developer App 均支持流媒体播放。
-
iOS 多相机拍摄简介
现在可以通过 iOS 13 上的 AVCapture,从 iPhone XS、iPhone XS Max、iPhone XR 和最新的 iPad Pro 上的多个摄像头同时拍摄照片和视频。也可以配置设备上的多个麦克风来打造捕捉到的声音。了解如何利用这些强大的功能来为您的相机 app 增添富有创意的新功能,比如画中画和空间音频等。更深入地了解可能影响 app 设计的性能注意事项。
资源
相关视频
WWDC19
WWDC17
-
下载
(为iOS引入多镜头捕捉) 多镜头捕捉 或者像我们圈内一样喜欢把它叫做 MultiCam
MultiCam是呼声最高的一个 第三方功能 我们年复一年地听到关于它的消息 那么我们今天要讲的是 同时使用多镜头和多路麦克 同时捕捉视频、 音频、元数据、深度和照片
不过第三方并不是唯一一个 受益于此的 我们还收到了许多来自 第一方的客户们反复提出的需求 针对MultiCam捕捉 其中主要的因素是ARKit 如果你看了主题演讲 你一定听到了 对ARKit 3的介绍 这些API使用前置镜头 追踪面部和鼻子 并同时使用后置镜头追踪周边环境 这会帮助他们了解 要把虚拟角色放在场景中的哪个位置 通过了解你正在凝望什么
那么自AVFoundation的 首次出现起 我们就已经 在Mac上支持MultiCam了 可以一直追溯到Lion操作系统 但在iOS上 AVFoundation客户们 每次都只能有一个激活的镜头 并不是因为我们打算这样做 我们有许多很好的理由 第一个理由是硬件限制 我指的是镜头分担了电源的电量 它本身不能提供足够的电量 同时全量支持两个摄像头 第二个理由是 我们期待发布一个可靠的API 可以帮助你不让手机发烫 当多个摄像头同时消耗电源时 因此我们希望能确保 我们给你们提交的东西 可以帮助你 处理硬件、热量和带宽约束 这在我们的世界中是现实存在的 好的 在iOS 13中有个好消息 我们支持MultiCam捕捉了 并且我们在当前全部硬件上 都实现了这个功能 iPhone XS、XS Max XR和新出的iPad Pro 在全部平台上 前面提到的硬件限制已经解决了 谢天谢地
那么让我们直接来看有趣的部分吧 我们开发了一些新API 用于创建MultiCam会话
如你曾用AVFoundation 来进行镜头捕捉 你一定了解我们有四个主要的类 分别是输入、 输出、会话和连接
AVCaptureSession 是重中之重 它用于排列数据 它用于表明开始或停止运行
你把它添加到一个或多个输入中 AVCapture输入 其中一个这样的是 AVCaptureDeviceInput 它要么是摄像头要么是麦克的包装器
你还需要添加一个或多个 AVCapture输出 用于接收数据 否则那些生产出来的东西就无处安置
然后会话以你的名义 以兼容的媒体类型 在输入和输出之间自动创建连接 请注意 我展示的是iOS上的传统 AVCaptureSession 每个会话只允许一个镜头输入
iOS 13中的新功能是我们引入了 AVCaptureSession的一个子类 叫做AVCaptureMultiCamSession 允许你执行多个输入和输出
我们并没有抛弃 AVCaptureSession 它不会消失 当前的AVCaptureSession 仍然是优选类 当你执行单镜头捕捉时 原因是 MultiCamSession 作为一个强大的工具有一些限制 我稍后会讲到
好的 那么让我给你一个基本用例 针对新的 AVCaptureMultiCamSession 假如你想对MultiCamSession 添加两个设备 一个用作前置镜头 一台个用作后置镜头 并同时执行两个视频数据输出 一个设备收到后置镜头的视频流 而另一个收到前置镜头的视频流
那么假设如果你想执行实时预览 你可添加独立的VideoPreviewLayers 一个给前置镜头 一个给后置镜头
不过不要止步于此 你可以执行
同时元数据输出 如果你希望 同时执行条形码扫描或面部检测的话 你可以执行电影文件的多个输出 如果你想用一个设备记录前景 一个设备记录后景的话 你可以添加照片的多个输出 如果你想 从不同的摄像头 执行实时照片捕捉的话 那么正如你所看到的 这些图表开始看起来很复杂 大量输入和大量输出中 掺杂着大量箭头
那些小箭头叫做 AVCaptureConnections 它们定义了输入到输出的数据流 让我暂时关注一下设备输入 从而剖析一下连接
捕捉输入有AVCapture 输入端口 我喜欢把它看作是个小插座 每个媒体类型都有一个插座 可以容纳输入 如果端口上没有插入任何东西 那个端口就没有视频流 就像插座一样 你必须插点东西才能获得电流 为了找出每个特定的输入 有哪些可用的端口 你可以查询那个输入的端口属性 它会告诉你说“我有这些 AVCapture输入端口” 对于双摄像头来说 它们是以下这些的端口 一个捕捉视频 一个捕捉深度 一个捕捉元数据对象 比如二维码扫描和面部扫描 一个捕捉元数据项 元数据项可以被钩到电影文件输出上
现在无论何时当你使用 AVCaptureSession的添加输入方法 来向会话中添加输入 或使用它的添加输出方法 来向会话中添加输出时 会话都会查找兼容的媒体类型 和隐藏的表单连接 如果可以的话 因此我们在这里有一个 VideoDataOutput VideoDataOutput 收到视频并接受视频 并且我们有一个电插头可以产生视频 因此会自动进行连接 大多数人都习惯那样 处理 AVCaptureSession 如果你之前曾用过我们的类的话 MultiCamSession 完全不一样 那是因为输入和输出 现在多个输入可以配备多个输出 你很可能想要确保连接发生在 A到A和B到B 而不会在 你不希望它们交叉的地方发生交叉 因此当创建 MultiCamSession时 我们强烈要求你不要使用 隐藏的连接表单 而是使用这些特别目的的添加工具 添加不带任何连接的输入 或添加不带任何连接的输出 同样地 你可以用于视频预览层的那些 就是setSessionWithNoConnections 当你使用它们时 它们基本上只会告诉会话说 “这是输入 这是输出 你现在知道它们了 但请不要碰它们 我稍后会手动添加 我所想要添加的连接” 添加方式就是自己创建 AVCaptureConnection 并告诉它“我希望你把这个 或这些端口连接到这个输出上” 然后告诉会话说“请添加这个连接” 然后一切就绪
我太啰嗦了 演示比口头说说要好的多 因此我想让Nik Gelo上台 他同样来自摄像头软件组 将给大家 演示AVMultiCamPIP Nik?
谢谢Brad AVMultiCamPIP 是一款app 用于演示 同时来自前后镜头的视频流 在这里我们有两个视频预览 一个显示的是前置镜头 一个显示的是后置镜头 当我双击屏幕时 我可以切换让哪个镜头呈现全屏 哪个镜头呈现PIP
现在我们可以在这里看到Brad 正在Apple Park里 在我向他提问之前 我会按下底部的录制按钮 稍后再观看这段采访 嘿Brad 那么告诉我 Apple Park怎么样? Nik Apple Park一片嘈杂 你可以看到在倒影池前边 正在举办各种活动 我听到了水流的哗哗声 听起来我随时都会被淋湿 我听到我后边有野兽的声音 像是鸭子之类的东西 老实说我非常担忧我在这里的生活 嗯 Brad 那听起来太恐怖了 希望你保持安全 好的 谢谢 录好了 那么现在 我们完成了对电影的录制 让我们看看我们刚刚录下了什么
这是电影 正如你所看到的 当我在两个镜头之间切换时 就跟我们使用app时一样 这就是AVMultiCamPIP 舞台交还给Brad
谢谢Nik 演示很棒
好的 那么让我们看看 在AVMultiCamPIP后台发生了什么 那么我们有两个设备输入 一个是前置镜头的输入 一个是后置镜头的输入 不带任何连接 就像我刚才所提到的那样 我们还有两个视频数据输出 前后镜头各一个 还有两个VideoPreviewLayers 现在要把它们放在屏幕上 只需要把那些 VideoPreviewLayers排序 把一个放在另一个的上层 并且有一个尺寸较小 当Nik双击它们时 我们要简单地重定位它们 并颠倒Z排序 在Metal Shader Compositor代码中 有一些神奇的事情 它合成了那两个 VideoDataOutputs 从而把较小的PIP 安排到一个框架内 因此它是把它们 合成到单一视频缓冲器中 然后把它们发送给 AVAssetWriter 在AVAssetWriter中 它们被记录到电影的一个视频轨道中 你现在可以使用这段示例代码了 它与研讨会相关联 你可以查看并开始做 自己的MultiCam捕捉了
好的 是时候谈谈限制了 虽然AVMultiCamSession 是一个强大的工具 但它并不能实现一切功能 让我来告诉你它不能做什么
首先你不能假装一个镜头是两个镜头 AVCaptureDeviceInput API会让你 创建为比如说后置镜头创建多个实例 如果你想的话 你可以做十个 但如果你尝试把全部实例添加到一个 MultiCamSession中 它会说“哼哼” 并且会引发异常 在会话中 请对每个镜头仅做一个输入 同时你也不可以克隆镜头 来获得两个同样类型的输出 比如把一个镜头的信号 拆分为两个视频数据输出 当然了 你可以添加多个镜头 并把每一个都连接到一个 VideoDataOutput 但你不能散开 不能一对多
反之也不可以 AVCapture在iOS上 的输出不支持媒体混合 因此所有数据输出 只能处理一个单一的输入 你不可以 比如说 尝试把两个镜头源 挤压为一个单一数据输出 它不知道如何处理第二个视频 因为它不知道如何混合它们 当然 你可以使用 独立的视频数据输出 然后在你自己的代码中 合成那些缓冲器 比如我们在MultiCamPIP中 使用的Metal Shader Compositor 不管怎样做都可以 只要考虑到会话创建就好 不要尝试把多镜头 挤压到一个单一输出中
好的 提一下预设
传统的AVCaptureSession 对于会话预设的概念是 给整个会话规定一个 一般性的服务质量 它应用于那个会话内的 全部输入和输出 比如当你把 sessionPreset设为高时 会话配置设备的分辨率和帧频 以及全部输出 从而使它们提交 一个高频时的视频体验 比如1080p30
预设对于MultiCamSession来说 是个问题 再想想一些诸如此类的东西
MultiCamSession 配置是混合配置 具有多样化 整个都是高品质意味着什么呢? 你可能想在图表的不同分支上 执行不同的服务品质 比如在前置镜头上 你可能只想执行 一个低分辨率预览 比如640乘480 而同时在后置镜头上执行 非常高品质的预览 比如1080p60 嗯 很明显 我们没有针对 这些混合状况的预设 我们决定在MultiCamSession中 让事情变得简单一些 它不支持预设 它支持一个也只支持一个预设 就是输入优先 那么那意味着当你添加输入和输出时 它不会处理输入和输出 你必须自己配置活动格式
好的 再谈谈消耗函数 我在开始就提到过我们花了很多时间 来做这个MultiCam支持 因为我们希望提交一个 非常可靠的API 可以帮助你解决在运行多摄像头 和点亮手机上每一个区块 所付出的各种代价
那么这很老套 但却是事实 天下没有免费的午餐 那么在研讨会的这个部分 我是你的前辈 我要跟你们做一次 长辈对后辈的经验传授
在接下来的经验传授中 我会解释信用卡是如何运作的 以及你要如何对你的钱负责 并用你的方式生活 以及比如这种东西
那么生活的现实就是我们在iOS上 拥有有限的硬件带宽 然而我们有多个摄像头 因此我们有多个传感器 但我们只有一个ISP 或图像信号处理器 因此流过这些传感器的全部像素 都要由一个ISP来处理 它限制了每个给定的时钟频率 可以运行多少像素 因此限制了 一次可以运行多少像素 硬件增加消耗正如你所期待的那样 是视频分辨率 较高的分辨率意味着可以填充 更多的像素 最大帧频 如果像素提交的速度更快 那么时钟频率的像素就越多
还有第三个 你可能听说过或也可能没听说过 叫做传感器装箱
传感器装箱指的是在相邻像素中 合并信息的一种方式 用于减少带宽 那么比如说这里有一张图片 我们执行一次二乘二装箱 它会拥有四个像素方格 并把它们合并为一个方格 从而尺寸上就缩减了4x 它为你减少了噪音 它为你减少了带宽 它为每个像素提供4x强度 那么传感器装箱还有许多好处 负面消息是图像品质稍差 那么对角线可能看起来 有点像阶梯式 但它做出了补偿 就是装箱格式的功率超级低 事实上无论何时 当你使用ARKit的摄像头时 你就正在使用装箱格式 因为装箱格式是ARKit专用的 从而节省功率去实现 你想要实现的其它有意思的AR功能
好的 我们该如何解释消耗 或者说我们该如何报告消耗呢? MultiCamSession 会在你配置会话时 结算硬件消耗 因此每一次当你修改了什么东西时 它会持续追踪它 就像填满一辆购物车 或逛在线商店一样 把东西都放在购物车上 然后再付款 你知道何时会接近预算的极限 并且你可以比如说把东西丢掉 然后放进新东西或去掉那些旧东西 你在付款之前能看到费用 这对于MultiCamSession来说 也一样 我们有一个新属性叫做 hardwareCost 当你创建一个全新的会话时 hardwareCost从零开始
并随着你添加更多的功能、 更多的输入、更多的输出而增加 只要处于1.0以下就没什么问题 1.0以下一切都运行无误
只要你达到1.0及以上 你就有麻烦了 那是因为ISP带宽限制很严格 它不像你可以 你知道的 每隔一帧提交一次 不 这是一个 要么全部要么全无的提案 你要么能实现或要么不能实现 因此如果你超过了1.0 并且你尝试运行 AVCaptureMultiCamSession 它会说“哼哼” 它会给你一个通知 关于运行时间报错的通知 表明不得不停止的原因 是因为硬件消耗超出
现在你很可能正在思考 “我该如何缩减那个消耗呢?” 最显而易见的方式就是 选择较低的分辨率 另一种方式就是 如果你想保持同样的分辨率 如果在同一个分辨率上有装箱格式 那就选那个 虽然品质有点儿低 但功率也低
接下来你可能会想降低帧频会有帮助
但并不会 原因是 AVCaptureDevice 允许你在运行时修改帧频 并且我认为是自iOS 4起 就开始允许你这样做了 那么你可能会说 “把活动格式设为60” 你仍然需要付出120的消耗 而不是60的消耗 因为在运行时的任意一点上 你可能会把帧频增加到120 我们必须考虑到最糟糕的情况 但有个好消息 我们在AVCaptureDeviceInput上 提供一个覆盖属性 通过设置它 你可以把高帧频格式转换成 低帧频格式 通过承诺 你不会超过某个指定帧频来实现
这是API中的混淆点 我们不会把帧频看作是比率 我们把它们看作是持续时间 因此要设置帧频 你要设置持续时间为1 这对于帧频来说一样 如果你想把60 FPS格式 变成30 FPS格式 通过做一个CMTime实现 1比30 其中1是持续时间 然后把deviceInput的videoMinFram DurationOverride设为30 FPS 恭喜你 你已经把60 FPS格式 转成30 FPS格式 你只付出了 30 FPS格式的硬件消耗
我还要提一下 在AVMultiCamPIP app中有一个很棒的功能 演示了如何反复地缩减消耗 它是个递归函数 它会选择对它来说最重要的东西 并限制那些比较不重要的东西 直到低于硬件消耗为止 接下来是系统压力消耗 这是我们发现的第二个消耗 相信也你清楚地知道 手机是非常强大的计算器 它是一个小的、面临热挑战的设备 并在在iOS 11中我们引入了 摄像系统压力状态 帮助你监控摄像头的当前状况
设想系统压力包含 系统温度 全部OS热峰值功率 都会要求系统温度
那与电池有关 它目前有多少余额呢? 它是否可以足够迅速地 升高它的电压 以满足运行需求呢 无论你现在想要做什么 还有红外线探照灯温度 在支持TrueDepth摄像头 的设备上 我们有红外摄像头以及RGB摄像头 嗯 那会产生它自己的热量 那也给系统压力状态 造成了一部分负担
其中五个自始至终 从“标准”变成 “关机” 当系统压力状态是标准时 你的状态不错 你可以做一切你想做的事 当它是合理时 你还可以继续 做几乎一切你想做的事 但如果它是严重时 你开始进入这样一种情况 系统即将减慢速度 意味着GPU循环数量变少了 可能会降低品质 如果是危险状态 会有一大堆节制 如果是关机 我们就再也不能运行摄像头了 害怕会伤害硬件 在关机情况下我们将自动中断 你的会话 停止它 并告诉你由于系统压力状态不好 而导致中断 然后我们等待设备 完全恢复到标准状态 然后才会让你再次运行摄像头
那么这是iOS 11 在iOS 13中 我们提供一种可以提前了解 系统压力消耗的方法 OK? 我们不仅告诉你当前所发生的 可能会受到重启摄像头之前 产生冲突的事实的影响 我们现在有一种方式 可以告诉你摄像头消耗 以及系统压力是多少 不依赖任何其它因素 因此增加消耗的东西 与硬件消耗增加一样 还有许多其它的东西 比如视频图像稳定性 或光学图像稳定性 这些全都需要消耗电源 我们有一个 Smart HDR功能等等 这里所列出的一切 都会增加整个系统的压力消耗
MultiCamSession可提前计算该分值 就像它对硬件所做的那样 并且它会考虑到它所了解的因素 因此如果你要同时执行一些 原生的GPU处理 分值将不会包含它 它只包含你通过摄像头所做的事
这是如何使用它
通过查询系统压力消耗 你可以了解在一个否则静态系统中 还能正常运行多久 因此如果它小于1.0 你可以无限期运行 你是一个很酷的客户 如果它在1和2之间 你应该最多可以运行15分钟 如果在2和3之间 最多10分钟 如果高于3 你可能只能运行很短的时间 事实上 即使你超过3 我们仍然会允许你运行摄像头 但你必须了解它不会保持太长时间 一旦它上升到危险或关机层级 会话将被中断 我们要拯救硬件 即使你不想 但 嘿 这很棒 如果你可以在30秒的运行时间内 完成你想要完成的事情的话 但要付出非常非常高的系统压力消耗 务必要这样做
现在该如何在运行时 减少系统压力呢? 我不是指会话的配置 我说的是一旦你已经开始运行 并且你注意到你已经开始增加 系统压力的情况 最迅速、最简单的方法就是 降低帧频 那会立即减轻系统压力 同时 如果你正在做一些 我们不知道的事 比如 耗费GPU或CPU的操作 你可以有所节制 还有最后一招 你可以尝试 禁用你正在使用的一个 或多个摄像头 AVMultiCamSession 有一个很灵巧的小功能 当运行时 你可以禁用其中一个摄像头 而不影响另一个摄像头的预览 我们不会把所有摄像头都关掉 因此如果你正在运行前后摄像头 你注意到你即将超出预算 并且很快会进入危险状态 你可以选择关闭前置摄像头 后置摄像头将继续预览 它不会丢失它的焦点、曝光或白平衡 并且当你关闭你想禁用的摄像头上的 最后一个活跃的输入端口时 通过把它输入端口的启动属性 设为假来实现 我们将终止摄像头的视频流 并节约大量电源 为系统提供一次冷却的机会
好的 那么我刚讲了 两个非常重要的消耗 硬件消耗和系统压力消耗 还有一些 我们没有报告出来的其它消耗 如果你不希望欺骗自己相信 没有其它可以增加消耗的功能 当然会有其它消耗 比如内存 但在iOS 13中我们人为地限制 设备组合 我们允许你运行 我们认为可以正常运行 并且不会让你陷入麻烦中的组合
因此我们对所支持的 设备组合的数量有限制 我列出了在iPhone XS上 所支持的组合 这有点儿像视力表 我不期待你能记住它 你稍后可以暂停视频 但有六个所支持的配置 并且你要记住的简单规则就是 你不可以同时运行两个物理摄像头 你可能会问比如 Brad 配置一个怎么样? 只有一个复选框 因为它是双摄像头 并且双摄像头是一种软件摄像头 它实际上包含广角和远距镜头 因此它是两个物理摄像头
如何了解是否支持 MultiCam呢? 正如我所说过的那样 只有较先进的硬件才支持它 因此你需要查看 MultiCamSession 是否允许你在你所拥有的设备上 运行多个摄像头 有一个类方法叫做 isMultiCamSupported 你可以立刻决定是或否 然后进一步当你想决定 我是否可以一起运行这个设备组合时 你可以对你感兴趣的设备创建一个 AVCaptureDeviceDiscoverySession 然后请求它的新属性 supportedMultiCamDeviceSets 这将生成大量无序集合 那会告诉你可以同时使用哪些组合 接下来是我们人为限制 你可以运行的格式 我刚查看的在iPhone XS中 所支持的格式 与后置摄像头有关的有40多种格式 因此可以选择的格式有很多很多 但我们限制 有MultiCamSession 的视频格式 因为这些是我们可以随心所欲地 在终端设备上同时运行的格式 这有点儿像视力表 但我希望你们注意一下组 第一组是装箱格式 还记得吗?低功率 是的 这是我们的朋友 在传感器上 你得到了那个2乘2的装箱 因此你收获了非常低的功率 低于60 FPS时全部这些都可用 你可以从640乘480 一直到1920乘1440之间选择
下一组是 1920乘1080 30 FPS 这是一种非装箱格式 与你对常规传统会话 选择高预设时的格式一样 它对MultiCam可用 最后一组是1920乘1440 非装箱格式 30 FPS 这是一个很好的图片格式的替换格式 我们并不是在所有摄像头上 都支持1200万像素 那对于手机来说是一件糟糕的事 但我们允许你以30 FPS执行 1920乘1440 请注意 它仍然允许你执行 1200万像素高分辨率拍照 因此这是一个很好的代理 当你想通过多摄像头同时摄像时
现在你要如何了解某格式是否支持 MultiCam呢? 你只需要问它就可以了 因此当在格式之间迭代时 你可以说 “是否支持MultiCam?” 如果它支持 你就可以使用它 在这里的代码中 我在一台设备上进行格式迭代 并选择下一个支持 MultiCam的最低的分辨率 然后把它设置为我的活动格式
我们进行人为限制的还有最后一点 因为我们需要报告消耗 由MultiCamSession 报告消耗 在iOS上我们明确不支持 app中多摄像头的多重会话 并且同时我们也不支持 多个应用中的多摄像头 请注意iOS上的支持 仍然限制于一次一个会话 但当然了 你可以同时运行多个摄像头
那么我的经验传授结束了 好的 写不错的代码 11点前要回家 如果你的计划有变 给我打电话
好的 好的 现在让我们返回到 有意思的部分
同步视频流
我提到了软件摄像头 一个软件摄像头有两个镜头 我们在iPhone 7 Plus上引入了它 现在它也在iPhone XS 和XS Max上使用 TrueDepth摄像头 也是另外一种软件摄像头 因为它由 一个红外摄像头 和一个RGB摄像头组成 这就能利用这两者的不同之处 实现深度
我们从未 给摄像头的这些特殊类型命名 但我们现在要这样做 在iOS 13中我们把它们叫做 虚拟摄像头 DualCam就是其中一种 它一次呈现一个视频流 并根据你的缩放系数转换 如果你接近2x 它会转换成远距摄像头 而不是广角摄像头 它还能针对深度出奇招 因为它有两个图像 可以用于生成它们之间的不同点 但从你的角度来说 你依然只能一次获得一个视频流
因为它们现在有名字了 它们还可 作为API的属性 你可以查询它 因此当你查看摄像头设备时 你可以用编程方式查找 这是否是一个虚拟设备? 如果它是 你可以问它 “嗯 哪个是你的物理设备?” 在API中我们把这个叫做它的 constituentDevices
同步视频流就是 获取虚拟设备的 constituentDevices 并同步运行它们 换句话说就是 我们首次允许你同时拍摄 来自广角摄像头 和远距摄像头的同步视频
你要继续在虚拟设备上设置属性 而不是在constituentDevices上
那里有一些规则 当你运行虚拟设备时 constituentDevices 不允许你乱糟糟地运行 它们有相同的活动分辨率 它们有相同的帧频 从硬件层级上来说 它们是同步的 那意味着传感器 会同步读取那些视频流 因此视频流的中间行 一定对应着同样的时钟时间 那意味着它们的中心帧相匹配 它还意味着曝光、 白平衡和聚焦是相继发生的 非常棒 看起来几乎是同一个摄像头 只是碰巧是两个不同的视野
最好演示一下 而不是说说而已 让我们做一个演示 这个叫做AVDualCam
好了
好的 AVDualCam会让你了解 虚拟摄像头会看到那些东西 通过给你展示一个两个摄像头 同步运行的显示屏
它这样做是为了给你展示 摄像头所拍摄的不同场景 好的 在这里我们有 同步运行的双摄像头的广角摄像头 和远距摄像头所拍摄的视频流 左侧是广角摄像头拍摄的 右侧是远距摄像头拍摄的 不相信我吗? 在这里我要把我的手指放到一侧
然后再把我的手指放到另一侧 看到了吗? 它们是不同的摄像头
我对广角摄像头所做的事就是放大它 从而让它与远距摄像头的视野一样 但你可以注意到 它们完美地同步运行着 没什么问题 场消隐也没有什么古怪 它们的曝光和聚焦同时发生了改变
我们可以再把它变得更有意思点儿 我们把肩并肩视图 变为分屏视图 现在看起来有点儿困难 但左侧是广角摄像头的拍摄内容 右侧是远距摄像头的拍摄内容 那么我只展示了每帧的一半
现在如果我轻触三次 我会打开一个测距仪 可以让我修改 两个图像的深度汇聚平面 这个app知道如何注册 两个图像的相关性 因此它允许我修改深度汇聚平面 就像你的双眼一样 当你盯着一些非常近 或非常远的东西看时 你正在修改汇聚的深度平面 那么比如说近距离地看我的手 我可以发现哪里是适合的深度汇聚 好了 现在适合一只手了 但却不适合我后边的那辆汽车 因此我继续向远处移动
好了 但这不适合它后面的汽车 因此现在我可以把那家伙拉回来
那么这就是来自双摄像头的 同步双摄像头视频流
这个图表显示了 AVDualCam的图表
它没有使用两个独立的设备输入 而是一个 因此它使用的是 双摄像头的单一设备输入 但它以同步方式 把广角帧和远距帧转成了两个 VideoDataOutputs 你会注意到底部有一个小对象 叫做AVCaptureOutputSynchronizer 我不想混淆你们的视听 它所做的并不是我所谈到的硬件同步 它只是会话底部的一个对象 如果你想 它可以在一个单一回调中 为你提供多次回调 因此不要对广角和远距摄像头 使用单独的 VideoDataOutput回调 你可以在底部执行 DataOutputSynchronizer 并通过一个单一的回调 同时获得来自两个摄像头的图像 那样就非常方便了 它下边有一个Metal Shader Filter Compositor 它也很神奇 正如我所说的那样 它知道如何 把两个来源的图像混合在一起 并决定预览中的哪里 是渲染这些图像的正确位置 并且它还把它们发送到 AVAssetWriter 以记录到一个视频轨道中
现在回顾一下之前的图表
我展示了 AVCaptureDeviceInput的全貌图 尤其是双摄像头的输入 双摄像头输入的端口属性揭露了 你能在那儿看到哪个端口 有人看到那儿有两个视频端口吗?
我没看到两个视频端口 因此如何从我们在这里看到的那些 输入端口中区分开广角和远距呢? 那一个视频端口 是设法为我们提供两个吗? 不 它没有给我们提供广角或远距 它为我们提供的是双摄像头决定的 适合指定缩放系数的端口
这不会帮助我们同时获得两个视频流 因此我们要如何做呢?
嗯 让我来告诉你 但这是个秘密 所以你必须保证 不告诉其他人 好吗? 虚拟设备有秘密端口 OK?
你之前不知道的秘密端口 现在变得可用了 但你没有把它们 从端口的数组中区分出来 你通过了解要请求什么来获得它们 因此你不仅会得到 端口的每个可能的类型的数组 包括不能用于单一摄像头会话的端口 你都可以通过名称进行请求 因此在这里我们有 dualCameraInput 我正在通过sourceDeviceType WideAngleCamera来请求它的端口 以及源设备类型 TelephotoCamera 它告诉我说“啊哈 我知道那些秘密端口 我现在就提供给你” 一旦你得到那些输入端口 你就可以把它们钩在一个连接上 与你创建自己的手动连接时一样 然后你就可以在广角或远距 或广角和远距视频流之间切换
在AVDualCam演示中 我可以用正确的视角 修改广角和远距摄像头的 深度汇聚平面 你也看到了 那不只是移动和晃动 它沿着我希望它汇聚的平面上移动 就沿着基线所在的平面 我之所以能这样做是因为 AVFoundation 为我们提供了一些单应性辅助 单应性是指 如果你不熟悉这个术语的话 它与同一平面上的两个图像相关 它们是计算机视觉的基础 它们对于以下任务来说很常见 比如图像校正、图像注册
现在相机内联对于iOS来说 不是什么新技术 我们在iOS 11中就引入了它们 它们给我呈现一个3乘3的矩阵 描述了摄像头的几何学性能 也就是它的焦距和光学中心 看这里使用了针孔摄像头 你可以看到 它进入到针孔摄像头的哪个位置 并击中传感器 那是光学传感器 而把两者之间的距离作为焦距
现在你可以选择按帧接收内联 通过给AVCaptureConnection 发消息说 你希望内部提交 一旦完成 那么你所收到的每个 视频数据输出缓冲器 都带有这个 CameraIntrinsicMatrix 它还是一个NSData 包裹的是一个3乘3的浮点型矩阵 是一个SIMD类型 当你获得广角视频流时 你会得到广角摄像头的视频流矩阵 当你获得远距视频流时 你会得到远距摄像头的视频流矩阵
现在iOS 13中有个新功能 我们提供设备层级的摄像头外联 外联是一个旋转矩阵和一个平移矢量 就像是被一起填到一个矩阵中 它描述了摄像头 相对于参照摄像头的姿势 这会为你提供帮助 如果你想关联两个摄像头 所在的位置的斜度 以及它们之间的距离 那么AVDualCam使用外联 来了解如何对齐 广角和远距摄像头的视频流 相互协调 从而可以进行正常拍摄
它们是内联和外联上 非常非常简短的刷新工具 那么在两年前的第507号研讨会上 我对它们做了非常详细的介绍 因此我请你回顾那场研讨会 如果你的胃很强大的话
好的 关于MultiCam捕捉的 最后一个话题是多路麦克捕捉
好的 让我们回顾一下使用传统 AVCaptureSession 时的麦克捕捉的默认行为
麦克跟随摄像头 这是我能想到的最简单的描述了 因此如果会话中连接着前置摄像头 那么麦克将自动选择 与前置摄像头所指向的方向 一样的麦克 对于后置摄像头也一样 因此它是一个漂亮的心形图 它拒绝来自外部的你不想要的音频 那样你就可以跟随你的主体 前或后 如果你有只有音频的会话 我们不太确定该把音频指向哪个方向 因此我们只给你提供一个全方位字段 作为一个强大的功能 你可以禁用全部功能 通过声明“别动AVCaptureSession 我想使用我自己的AVCaptureSession 并配置自己的音频” 并且我们会遵守承诺
那么是时候告诉你们另一个小秘密了
根本就没有什么前置麦克 我刚才完全是在骗你 事实上iPhone 包含许多麦克 设备不同麦克的数量也不同 最近几代iPhone 恰巧有四个麦克 iPad有五个麦克 并且它们的位置不一样 在最近几代iPhone上 恰巧有两个麦克直接指向屏幕底部 顶部有两个麦克分别指向两侧 它们都是全方位麦克 现在顶部麦克会产生一些 听觉上的分离 因为它们之间有设备充当挡板 但它仍然不能为你提供一个 你想要的方向图 那么你具体到如何获得 接近前或后麦克的效果呢?
你要做的叫做麦克波束形成 这是处理原生音频信号 并让它们具备方向性的一种方式 Core Audio 会以你的名义替你实现 在这里我们有两个蓝色点 代表iPhone上两侧的两个麦克 圆形大概就是 它们所听到的音频图 请记住 它们都是全方位麦克 如果我们去掉这两个信号 我们就会形成八字形图 那很酷 那并不是我们想要的 但它的确很酷 如果我们想进一步塑造它 我们可以给我们想要保留的麦克 添加一些增益 在去掉它们之前 现在我们得到了一个小吃豆人 很好 现在我们拒绝了 我们不希望保留的那一个麦克 但很遗憾 我们也把信号削弱了 因此它比我们想的要安静多了
但如果我们做了那些之后 又给那个信号应用了一些增益 我们会得到一个很漂亮的大吃豆人 并且现在我们得到了 我们想要的那个漂亮的心形图 我们拒绝了我们不想要的那个摄像头 现在这个极其简化了 其中进行着大量筛选 从而确保不会增益白噪声 但从根本上来说那就是所发生的事 到目前为止 一次只支持一个麦克波束形成 但Core Audio的 那些好伙计们 针对这个MultiCam功能 做了一些很伟大的事 在iOS 13中我们现在同时支持 多个波束形成
那么返回到老版 AVCaptureSession 当你获得麦克设备输入时 你发现它的音频端口 那个端口有许多种音频 可能是前、后或全方位音频 取决于会话所找到的摄像头 但当你使用 MultiCamSession时 行为非常严格 你找到的第一个音频端口 总是全方位的端口 然后你会发现我提到的那些秘密端口 得到了专门的后方波束 或专门的前方波束 实现方式是使用同样的
设备输入端口接收器 这一次通过 指定你所感兴趣的方位实现 因此你可以请求前方或后方位置 那会为你提供你所感兴趣的端口 并且你将获得很好的后或前波束形成
这是前波束形成
这是后波束形成
现在返回到Nik的 MultiCamPIP演示中 我们只关注了视频 我们展示了技术先进的部分功能 现在我要返回去并告诉你 我们在音频处理上做了哪些努力 我们总是运行
一台单一设备输入 带有两个波束形成 一个是前方波束形成 一个是后方波束形成 我们对它们执行 两个不同的音频数据输出 这张幻灯片应该说 AudioDataOutputs 然后在运行时从两者之间选择一个 那么根据两者谁更大 我们可以切换为前或后麦克 并为你提供我们所期待的波形形成
关于多路麦克捕捉有一些规则 需要了解 波形形成只能对内置麦克有效 如果你有外置麦克 USB麦克 我们不知道它是个什么东西 我们不知道如何用它形成波束
如果你恰巧插入其它东西 包括AirPods 我们当然会捕捉音频 但我们不知道如何形成波束 因此我们只给那个麦克 传输你所连接的全部输入 从而确保你不会丢失信号
今天对于多摄像头捕捉的演讲 就到此结束了 让我们快速总结一下
MultiCam捕捉会话是在 iOS上同时运行多摄像头的新方式
它是个强大的工具 但有一些限制 了解一下这些限制
当你编程时要考虑好 如何处理硬件和系统压力消耗
如果你想执行同步视频流 使用那些有必不可少的 设备端口的虚拟设备 最后如果你想执行多路麦克捕捉 请注意你可以使用前、 后或全方位波束形成 谢谢大家
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。