react-native-vision-camera 性能调优:帧率稳定 60fps、暗光照片更干净
【免费下载链接】react-native-vision-camera📸 A powerful, high-performance React Native Camera library.项目地址: https://gitcode.com/GitHub_Trending/re/react-native-vision-camera
打开相机页 3 秒还在转圈,预览只有 24fps 左右,暗光照片噪点糊成一片——在 react-native-vision-camera v5 里,这些问题大多不是设备不够强,而是约束没写对。
先把概念对上
v5 换了架构:不再有device.formats列表让你手动挑格式,而是由CameraSession根据你的"意图"自动协商出一套能跑通的配置。性能调优的重点,从"选对格式"变成了"把约束写对"。
| 对象 | 职责 | 依赖关系 |
|---|---|---|
CameraDevice | 逻辑摄像头设备 | 由getCameraDevice(...)从设备列表选出 |
CameraSession | 协商并管理整条管线 | 输入 = device + outputs + constraints |
CameraOutput | 一条数据流(预览/照片/视频/帧) | 挂到 session 上,各占一路管线 |
Constraint | 表达协商意图,如{ fps: 60 } | 由 session 解析为具体配置 |
CameraSessionConfig | 协商结果(实际 fps、像素格式等) | 通过onSessionConfigSelected回调返回 |
相机页打开慢:先让设备简单起来
限制 physicalDevices 到单镜头
三摄逻辑设备要同时初始化多颗物理镜头,isActive={true}后等第一帧的时间明显变长。只选广角时,启动路径最短:
import { useCameraDevices, getCameraDevice } from 'react-native-vision-camera' export function useBackCamera() { const devices = useCameraDevices() return getCameraDevice(devices, 'back', { physicalDevices: ['wide-angle'], }) }代价:失去超广角/长焦镜头之间的平滑变焦切换。只拍 1x 的场景完全无感,需要 0.5x~2x 变焦的才需要放开多镜头。
预览帧率怎么调:用约束表达意图
固定 fps,但想清楚分辨率代价
{ fps: 60 }会让协商器去找支持 60fps 的格式;同一颗镜头的 1200 万像素档通常只给 30fps,所以请求 60fps 可能被悄悄降级到 1080p:
<Camera device={device} outputs={[previewOutput, photoOutput]} constraints={[ { fps: 30 }, ]} isActive />30fps + 高分辨率是更稳的组合;只有确认当前分辨率档支持 60fps 时才写 60,否则约束会被回退。
预览与录像分开约束
同一个 session 里,预览和录像流可以各自约束:
const constraints = [ { fps: 60 }, { videoStabilizationMode: 'standard' }, ] satisfies Constraint[]预览要的是跟手,录像要的是稳定;如果预览发闷,把稳定档位从cinematic换成low-latency,代价是防抖强度下降。
用 onSessionConfigSelected 确认实际配置
约束是意图不是硬性要求,协商不满足时会选最接近的、不会报错,所以必须回看结果:
<Camera device={device} outputs={[previewOutput]} constraints={[{ fps: 60 }]} onSessionConfigSelected={(config) => { console.log('resolved fps:', config.selectedFPS, 'binned:', config.isBinned) }} isActive />config.selectedFPS才是实际协商出的帧率,和请求值对不上时,说明当前分辨率下这颗镜头根本给不到 60fps。
暗光照片发糊:binned 与 HDR 各管一件事
binned:进光量换细节
暗光糊,往往因为用的是全分辨率 unbinned 读取。让协商器选合并像素的格式:
const constraints = [ { binned: true }, ] satisfies Constraint[]binning 把相邻像素合成一个,单像素进光量翻倍,噪声明显下降;代价是空间细节不如全分辨率,白天拍特写时不要开。
photoHDR:只在大光比场景开
有强逆光或明暗反差大的场景,让照片输出开 HDR:
const constraints = [ { photoHDR: true }, ] satisfies Constraint[]代价:拍摄耗时更长(多帧合成),出片等待会变明显,适合作为可选开关而不是默认常开。
多路输出时内存与掉帧
只接当前页面真正用的 output
每个 output 都是独立管线,带宽、内存和功耗各占一份。只做拍照就只挂照片输出:
const photoOutput = usePhotoOutput() const previewOutput = usePreviewOutput() <Camera device={device} outputs={[previewOutput, photoOutput]} isActive />页面里没有录像需求时,别接CameraVideoOutput,哪怕"以后会用"。
isActive 是停会话不是拆管线
isActive={false}只停CameraSession,设备与 output 连接保留;回前台再 start 比整体重建快得多:
const [isActive, setIsActive] = useState(false) useEffect(() => { const sub = AppState.addEventListener('change', (s) => setIsActive(s === 'active')) return () => sub.remove() }, [])适用:App 频繁切后台的场景;注意 stop 后预览会黑屏,回前台需等第一帧。
配置速查表
| 场景 | 关键配置 | 预期收益 | 注意事项 |
|---|---|---|---|
| 预览流畅度 | { fps: 30 }+ 1080p 目标 | 帧率稳定 | 60fps 可能被协商回退,先确认分辨率档 |
| 暗光画质 | { binned: true } | 进光量翻倍、噪声下降 | 损失细节,白天特写别开 |
| 逆光大光比 | { photoHDR: true } | 高光阴影都保住 | 拍摄耗时增加,出片变慢 |
| 录像防抖 | { videoStabilizationMode: 'standard' } | 画面稳定 | 裁切视场、有缓冲延迟 |
| 预览防抖 | { previewStabilizationMode: 'low-latency' } | 预览不糊 | 稳定强度弱于 cinematic 档 |
| 启动速度 | physicalDevices: ['wide-angle'] | 出第一帧更快 | 失去多镜头平滑变焦 |
| 多路 output 竞争 | { resolutionBias: photoOutput }在前 | 照片分辨率优先 | 顺序即优先级,视频会被压低 |
踩过的坑
问:请求 60fps,实测只有 30fps?答:协商失败不报错,选最接近的即可。看onSessionConfigSelected里的selectedFPS,多半是分辨率太高,降一档或接受 30。
问:resolutionBias和photoHDR同时写,冲突了?答:约束是意图,协商器挑"最接近",不是全部满足。顺序表达优先级:把更重要的约束写在前面。
问:切后台回来,重开相机比重建慢?答:约束和连接都还在,stop 只是暂停会话。直接isActive切回 true,别销毁重建 output。
【免费下载链接】react-native-vision-camera📸 A powerful, high-performance React Native Camera library.项目地址: https://gitcode.com/GitHub_Trending/re/react-native-vision-camera
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考