3. 移动端采集架构
移动端音视频采集并不是“打开摄像头就能推流”这么简单。它是一条从硬件到应用层的完整链路:摄像头/麦克风传感器 → 系统采集框架 → 应用层 API → 编码器。理解这条链路,才能正确配置参数、处理权限和应对前后台切换。
一、采集链路与系统框架
在 Android 上,摄像头数据通过 Camera2(或 CameraX)API 获取,麦克风通过 AudioRecord 获取;在 iOS 上,摄像头和麦克风统一由 AVFoundation 框架管理,核心类是 AVCaptureSession。无论哪个平台,采集链路都可以抽象为四层:
- 硬件层:CMOS 传感器、MEMS 麦克风,输出原始信号。
- 系统框架层:Android 的 CameraService/AudioFlinger,iOS 的 AVFoundation,负责设备枚举、格式协商、缓冲区管理。
- 应用 API 层:Camera2/CameraX、AudioRecord、AVCaptureDevice/AVCaptureSession,开发者直接调用的接口。
- 数据处理层:将采集到的 YUV/RAW 帧和 PCM 音频送入编码器(如 MediaCodec、VideoToolbox)。
下图展示了移动端采集架构的核心数据流与关键控制点:
二、摄像头与麦克风 API 选型
Android 平台目前推荐使用 CameraX,它对 Camera2 做了封装,自动处理设备兼容性和生命周期,适合大多数直播、短视频场景。若需要精细控制曝光、对焦、多摄切换,则使用 Camera2。音频方面,AudioRecord 提供原始 PCM 数据,适合需要自定义前处理(如降噪、回声消除)的场景;若只需简单录音,MediaRecorder 更便捷但灵活性低。
iOS 平台统一使用 AVFoundation。核心流程是:创建 AVCaptureSession → 添加 AVCaptureDeviceInput(视频和音频各一个)→ 添加 AVCaptureVideoDataOutput / AVCaptureAudioDataOutput → 在代理回调中获取 CMSampleBuffer。AVCaptureSession 的 startRunning 和 stopRunning 是阻塞操作,必须放在串行队列中执行,否则会卡住主线程。
三、采集参数配置
视频采集参数主要包括分辨率、帧率、像素格式和方向。以 720p@30fps 为例,在 CameraX 中配置如下:
// CameraX 预览 + 采集配置示例
val preview = Preview.Builder()
.setTargetResolution(Size(1280, 720))
.setTargetRotation(Surface.ROTATION_0)
.build()
val imageAnalysis = ImageAnalysis.Builder()
.setTargetResolution(Size(1280, 720))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
.build()
// 帧率控制通过 Camera2Interop 扩展
val builder = Camera2Interop.Extender(imageAnalysis)
builder.setCaptureRequestOption(
CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
Range(30, 30)
)
音频参数方面,直播场景常用 44100Hz 采样率、单声道、16bit 量化。若对音质要求高(如音乐直播),可提升至 48000Hz 立体声。注意:采样率越高,单位时间数据量越大,44100Hz 单声道 16bit 每秒约 88.2KB,而 48000Hz 立体声 16bit 每秒约 192KB,带宽和编码压力相差一倍以上。
四、权限管理
移动端采集涉及两个危险权限:CAMERA 和 RECORD_AUDIO。两者都必须在运行时动态申请,且用户可能拒绝或只授予部分权限。正确的处理流程是:
- 在 AndroidManifest.xml / Info.plist 中声明权限。
- 启动采集前检查权限状态,未授权则发起请求。
- 用户拒绝后,展示解释性 UI,说明为什么需要该权限。
- 用户勾选“不再询问”后,引导跳转系统设置页手动开启。
- 权限被撤销时(如用户在设置中关闭),监听回调并停止采集、释放资源。
iOS 上还需注意:首次调用 AVCaptureDevice.requestAccess 时系统弹窗只出现一次,之后必须通过 AVAuthorizationStatus 判断并引导用户去“设置 → 隐私 → 相机/麦克风”中修改。
五、前后台切换处理
这是移动端采集最容易出问题的环节。当 App 退到后台,系统可能回收摄像头资源,或者直接终止采集会话。如果不做处理,回到前台后会出现黑屏、采集失败或崩溃。
Android 上的处理策略:在 onPause 中调用 cameraProvider.unbindAll() 释放摄像头,停止 AudioRecord;在 onResume 中重新绑定用例、重新启动采集。注意 CameraX 的 bindToLifecycle 会自动跟随 LifecycleOwner,但音频采集需要手动管理。
iOS 上的处理策略:监听 UIApplication.didEnterBackgroundNotification 和 willEnterForegroundNotification。进入后台时调用 captureSession.stopRunning(),回到前台时重新 startRunning()。如果 App 需要在后台继续采集音频(如录音场景),需在 Info.plist 中声明 UIBackgroundModes 为 audio,并配置 AVAudioSession 的 category 为 playAndRecord。
六、采集状态检查清单
在实际工程中,可以用以下清单快速排查采集问题:
| 检查项 | 正常表现 | 异常处理 |
|---|---|---|
| 权限状态 | CAMERA 和 RECORD_AUDIO 均为已授权 | 引导用户去设置页开启 |
| 设备可用性 | 摄像头未被其他 App 占用 | 提示“摄像头被占用”,延迟重试 |
| 采集帧率 | 稳定在配置值 ±2fps | 降低分辨率或关闭美颜等前处理 |
| 音频数据 | PCM 缓冲区持续有数据写入 | 检查 AudioRecord 状态和缓冲区大小 |
| 前后台恢复 | 回到前台 1 秒内恢复预览 | 重建采集会话,重新绑定用例 |