(七)深入了解AVFoundation-采集:采集系统架构与 AVCaptureSession 全面梳理

引言

在 iOS 开发中,AVFoundation 是构建音视频功能的强大底层框架。而在音视频功能中,“采集”往往是最基础也是最关键的一环。从摄像头捕捉图形、到麦克风获取声音,构建一条高效且稳定的采集链是开发高质量音视频应用的前提。

本系列将逐步深入 AVFoundation的采集机制,了解它的地方设计与实际使用。在本篇中,我们会聚集在采集系统的核心管理单元——AVCaptureSession,从整体架构出发,梳理采集链路的组成方式与搭建流程。

AVCaptureSession 的职责与系统架构

在 AVFoundation 中,AVCaptureSession 是整个采集系统的中心协调者。它的主要职责包括:

  1. 管理输入(Input)与输出(Output)设备:例如摄像头、麦克风作为输入,图像帧输出、音频数据输出作为输出。
  2. 协调数据流的流动:确保从设备捕获到的数据正确地传递到输出模块。
  3. 统一管理采集回话的生命周期:如开始采集startRunning()、停止采集stopRunning()、中断与恢复。
  4. 维护链接配置:控制比如视频方向、镜像、视频稳定等细节。

简而言之,AVCaptureSession 就像是一个数据总管,它把输入设备(比如摄像头、麦克风)和输出目标(比如屏幕预览、数据编码器)连接在一起,并统一管理整个采集链条的工作状态。

采集系统的基本架构可以理解成这样一个数据流动图。

简化来说就是:设备->输入->Session->输出->处理展示。

  • 一个 AVCaptureSession 可以同时管理多个输入输出(比如前后摄像头切换,或者同时采集视频与音频)。
  • 输入与输出设备必须通过 session.addInput() / session.addOutput() 正式添加到会话中,才会参与采集。
  • 建议在 专用串行 DispatchQueue 中配置 Session,避免 UI 卡顿。

输入 + 输出:构建采集模型的两大核心

在 AVFoundation 采集系统中,采集链条的两大基本构成单元就是:

  1. 输入(Input)
  2. 输出(Output)

理解输入输出的工作原理和使用方式,是搭建稳定采集系统的基础。

输入(Input):采集数据的源头

输入负责吧硬件设备(如摄像头、麦克风)链接到AVCaptureSession中。

在实际开发中,我们通常就是使用AVCaptureDeviceInput 来包装摄像头和麦克风。

以摄像头为例:

// 1. 获取摄像头设备
guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {fatalError("未找到后置摄像头")
}// 2. 将设备包装成输入
let cameraInput = try AVCaptureDeviceInput(device: camera)// 3. 添加到 Session
if session.canAddInput(cameraInput) {session.addInput(cameraInput)
}

注意事项:

  1. 添加输入前要用 canAddInput(_:) 检查是否可以添加。
  2. 注意捕获设备可能没有权限,需要提前请求授权。
  3. 创建 AVCaptureDeviceInput 可能抛异常,使用 try。

输出(Output):采集数据的去向

输出负责接收采集到的数据,并将其交给需要的地方处理,比如:

  • 显示预览画面
  • 实时处理图像
  • 保存到文件
  • 推流到服务器

输出的类型有很多种:

输出类别

相关类名

描述

图像数据输出

AVCaptureVideoDataOutput

原始视频帧数据回调

音频数据输出

AVCaptureAudioDataOutput

原始音频数据回调

拍照输出

AVCapturePhotoOutput

拍摄静态照片

录制文件输出

AVCaptureMovieFileOutput

录制成视频文件

元数据输出(如二维码)

AVCaptureMetadataOutput

检测并返回元数据(条形码、二维码)

输出基本使用流程(以视频数据输出为例)

// 1. 创建输出
let videoOutput = AVCaptureVideoDataOutput()// 2. 配置输出参数(如像素格式)
videoOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
]// 3. 设置代理回调队列
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "VideoOutputQueue"))// 4. 添加到 Session
if session.canAddOutput(videoOutput) {session.addOutput(videoOutput)
}

代理方法示例(捕获到每一帧数据):

extension YourClass: AVCaptureVideoDataOutputSampleBufferDelegate {func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {// 处理每一帧图像}
}

注意事项:

  • 回调通常发生在自定义的串行队列上,避免占用主线程。
  • 输出设备也需要使用 canAddOutput(_:) 检查后再添加。

输入(Input) 负责采集硬件数据,输出(Output)负责把采集到的数据交给你处理或者保存。

输入输出就像水管的两端,中间由 AVCaptureSession 统一协调和流转。

搭建完整采集链条

在前面了解了 AVCaptureSession 的基本架构,以及输入(Input)和输出(Output)之后,这一部分,我们直接从实际角度出发,梳理一次完整搭建采集链条的流程。

完整流程

搭建完整采集链条,核心步骤可以总结为:

  1. 创建 AVCaptureSession
  2. 选择并创建输入设备(Input)
  3. 选择并创建输出设备(Output)
  4. 添加输入与输出到 Session
  5. 配置连接参数(如摄像头方向、镜像等)
  6. 创建预览层(可选)
  7. 启动 Session

整体的伪代码流程如下:

// 1. 创建 Session
let session = AVCaptureSession()// 2. 配置 preset
session.sessionPreset = .high// 3. 创建输入(摄像头)
guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back),let cameraInput = try? AVCaptureDeviceInput(device: camera),session.canAddInput(cameraInput) else {return
}
session.addInput(cameraInput)// 4. 创建输出(视频数据输出)
let videoOutput = AVCaptureVideoDataOutput()
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "VideoOutputQueue"))
if session.canAddOutput(videoOutput) {session.addOutput(videoOutput)
}// 5. 配置连接(方向、镜像)
if let connection = videoOutput.connection(with: .video) {connection.videoOrientation = .portraitconnection.isVideoMirrored = false
}// 6. 创建预览层(可选)
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.videoGravity = .resizeAspectFill
previewLayer.frame = view.bounds
view.layer.addSublayer(previewLayer)// 7. 启动 Session
session.startRunning()

采集分辨率的控制开关

sessionPreset 负责定义采集的数据质量,比如分辨率、码率、帧率等。

常见的 preset 有:

Preset

说明

.high

高质量(设备自动适配)

.medium

中等质量,适配中速网络上传场景

.low

低质量,适合弱网传输

.hd1280x720

720p 高清

.hd1920x1080

1080p 高清

.photo

照片质量(高分辨率)

注意:

  • preset 需要在 startRunning() 之前设置。
  • preset 要与输入设备能力匹配,否则设置无效,比如某些前置摄像头不支持 4K 采集。
  • 可以使用 session.canSetSessionPreset(_:) 检查兼容性。

连接(AVCaptureConnection)管理

在 Session 里,输入与输出之间的通道,叫做 AVCaptureConnection。

连接对象允许我们进一步微调采集流的细节,比如:

  • 方向(Orientation)
  • 镜像(Mirrored)
  • 视频防抖(Video Stabilization)
  • 自动对焦/曝光/白平衡(某些连接可以关联控制)

一般情况下,我们需要手动设置采集方向为竖屏:

if let connection = videoOutput.connection(with: .video),connection.isVideoOrientationSupported {connection.videoOrientation = .portrait
}

很多 app 前置摄像头拍照是镜像模式,也可以通过 Connection 设置:

if camera.position == .front,let connection = videoOutput.connection(with: .video),connection.isVideoMirrored {connection.isVideoMirrored = true
}

线程注意点:采集是高度异步的

Session 的 startRunning 和 stopRunning 是同步调用,但异步完成,因此推荐在后台线程调用。

输出的数据回调 (captureOutput(_:didOutput:from:)) 是在你指定的 DispatchQueue里触发的,不是主线程。如果在回调里要更新 UI,需要回到主线程。

DispatchQueue.global().async {session.startRunning()
}// 回调中处理 UI
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {DispatchQueue.main.async {// 更新 UI,比如显示帧率}
}

结语

在本篇内容中,我们从整体视角出发,完整梳理了 AVCaptureSession 为核心的采集系统,包括它的职责、输入输出模型,以及如何搭建一条基本的采集链条。

同时也深入探讨了 preset 设置、连接管理 和 线程注意事项 等关键细节,帮助你在实际项目中少踩坑。

可以看到,AVFoundation 的采集体系虽然灵活强大,但也有一定的复杂度。理解 Session 是怎么组织 Input 和 Output 的,掌握 Connection 上的各种参数调优,才能真正驾驭底层采集系统。

接下来的博客我们将继续AVFoudation的采集篇章,我们将在这个基础上,进一步探索更多实战话题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/76747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QML ShaderEffect(着色器效果)组件

ShaderEffect 是 QML 中用于实现自定义着色器效果的组件,允许开发者使用 GLSL 着色器语言创建图形效果。 核心属性 基本属性 属性类型默认值说明fragmentShaderstring""片段着色器代码vertexShaderstring""顶点着色器代码blendingbooltrue是…

基于javaweb的SSM教材征订与发放管理系统设计与实现(源码+文档+部署讲解)

技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

大模型学习笔记------Llama 3模型架构之分组查询注意力(GQA)

大模型学习笔记------Llama 3模型架构之分组查询注意力(GQA) 1、分组查询注意力(GQA)的动机2、 多头注意力(Multi-Head Attention, MHA)3、 多查询注意力 (Multi-Query Attention,MQA)4、 分组查…

matlab 环形单层柱状图

matlab 环形单层柱状图 matlab 环形单层柱状图 matlab 环形单层柱状图 图片 图片 【图片来源粉丝】 我给他的思路是:直接使用风玫瑰图可以画出。 rose_bar 本次我的更新和这个有些不同!是环形柱状图,可调节细节多; 只需要函数…

Docker--Docker网络原理

虚拟网卡 虚拟网卡(Virtual Network Interface,简称vNIC) 是一种在软件层面模拟的网卡设备,不依赖于物理硬件,而是通过操作系统或虚拟化技术实现网络通信功能。它允许计算机在虚拟环境中模拟物理网卡的行为&#xff0…

linux基础14--dns和web+dns

DNS:域名系统(Domain Name System) DNS协议是用来将域名转换为IP地址或将IP地址转换为相应的域名 DNS使用TCP和UDP端口53,给用户提供解析时一般使用UDP53 对于每一级域名长度的限制是63个字符,域名总长度则不能超过2…

C++抽象基类定义与使用

在 C 中,抽象基类(Abstract Base Class, ABC) 是一种特殊的类,用于定义接口规范和约束派生类的行为。它通过纯虚函数(Pure Virtual Function)强制要求派生类实现特定功能,自身不能被实例化。以下…

用selenium4 webdriver + java 搭建并完成第一个自动化测试脚本

自动化测试任务: 百度搜索自己的姓名。点击第一个链接(或者第二个),在新的页面上,添加断言,验证你的名字是否存在。 实验资料百度网盘下载路径: 链接: https://pan.baidu.com/s/1nVlHX_ivres…

LLM大模型中的基础数学工具—— 约束优化

Q26: 推导拉格朗日乘子法 的 KKT 条件 拉格朗日乘子法与 KKT 条件是啥? 拉格朗日乘子法是解决约束优化问题的利器。比如,想最小化函数 ,同时满足约束 ,就构造拉格朗日函数 ( 是乘子)。KKT 条件是解这类问…

net+MySQL中小民营企业安全生产管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 近些年来,随着科技的飞速发展,互联网的普及逐渐延伸到各行各业中,给人们生活带来了十分的便利,中小民营企业安全生产管理系统利用计算机网络实现信息化管理,使企业的中小民营企业安全生产管理发展和服务水平有显…

论文阅读:2024 arxiv AI Safety in Generative AI Large Language Models: A Survey

总目录 大模型安全相关研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 AI Safety in Generative AI Large Language Models: A Survey 生成式人工智能大型语言模型中的人工智能安全性:一项调查 https://arxiv.org/pdf/2407.18369 https://www.doubao.com…

【MySQL数据库】表的约束

目录 1,空属性 2,默认值 3,列描述 4,zerofill 5,主键primary key 6,自增长auto_increment 7,唯一键unique 8,外键foreign key 在MySQL中,表的约束是指用于插入的…

基于javaweb的SpringBoot校园失物招领系统设计与实现(源码+文档+部署讲解)

技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

多模态大语言模型arxiv论文略读(二十六)

Holistic Autonomous Driving Understanding by Bird’s-Eye-View Injected Multi-Modal Large Models ➡️ 论文标题:Holistic Autonomous Driving Understanding by Bird’s-Eye-View Injected Multi-Modal Large Models ➡️ 论文作者:Xinpeng Ding,…

“星睿O6” AI PC开发套件评测 - 部署PVE搭建All in One NAS服务器

Radxa O6平台上部署PVE搭建All in One NAS服务器 Radxa O6是一款性能卓越的单板计算机,其强劲的硬件配置和多样化的接口设计,使其成为家庭和小型企业理想的All in One服务器解决方案。值得一提的是,O6原生配备了两个5G网口,便于直…

C++ linux打包运行方案(cmake)

文章目录 背景动态库打包方案动态库转静态库动态库打到软件包中 运行 背景 使用C编写的一个小项目,需要打包成ubuntu下的可执行文件,方便分发给其他ubuntu执行,因为docker镜像方案过于臃肿,所以需要把项目的动态库都打在软件包中…

Linux内核编译(Ubuntu)

实验内容:在系统中下载统一发行版本的版本号较高的内核,编译之后运行自己编译的内核,并使用uname-r命令查看是否运行成功。 实验步骤: 1.查看实验环境和内核版本 图1 实验环境 VMware中虚拟机Ubuntu(24.04&#xff…

EdgeGPT - 新版Bing聊天功能逆向工程

本文翻译整理自:https://github.com/acheong08/EdgeGPT 文章目录 一、关于 EdgeGPT相关链接资源关键功能特性 二、安装系统要求安装命令 三、认证配置获取Cookie步骤代码中使用Cookie 四、使用方法1、命令行方式2、Python API方式使用Chatbot类使用Query辅助类 3、…

三网通电玩城平台系统结构与源码工程详解(四):子游戏集成与服务器调度机制全解

本篇将深入讲解三网通电玩城平台中子游戏接入、前后端资源组织方式、服务器调度逻辑、并发接入方案等核心内容,重点覆盖“李逵劈鱼”、“水果玛丽”、“疯狂玛丽”等热门组件,辅以完整代码框架与部署逻辑。 一、子游戏资源目录结构与加载机制 平台采用标…

1.1 AI大模型与Agent的兴起及其对企业数字化转型的推动作用

随着人工智能技术的飞速发展,AI大模型和智能代理(Agent)的兴起正成为推动企业数字化转型的重要力量。从2017年GPT-1的首次亮相到2025年GPT-4和Qwen 2.5等多模态模型的成熟,AI大模型经历了显著的技术演进;与此同时&…