17. 低端机专项优化:降低预览分辨率、关闭美颜/滤镜、减少帧率
说实话,做相机优化最头疼的不是旗舰机,而是那些低端机。我早期接手过一个项目,在骁龙4系平台上跑相机,预览卡成PPT,用户反馈说“拍照像在放幻灯片”。嗯,这其实不是代码写得烂,而是低端机的硬件资源就那么点,你得学会“省着用”。
这一章,我们就来聊聊低端机上的三板斧:降低预览分辨率、关闭美颜/滤镜、减少帧率。这三招用好了,低端机也能流畅跑起来。
17.1 为什么低端机需要专项优化?
低端机的SoC性能有限,ISP(图像信号处理器)能力也弱。你想想看,旗舰机可以轻松处理4K 60fps的预览流,但低端机连1080P 30fps都跑得吃力。原因很简单:
- 内存带宽不足:高分辨率预览需要大量内存读写,低端机的内存带宽往往只有旗舰机的1/3甚至更低。
- GPU/ISP负载高:美颜、滤镜这些算法需要额外的计算资源,低端机扛不住。
- CPU频率低:多线程调度能力弱,高帧率预览会导致CPU满载,进而引发发热降频。
我在项目中遇到过一台测试机,打开相机后CPU温度直接飙到85度,然后系统强制降频,预览帧率掉到10fps以下。说白了,这就是资源不够用,你得主动“降级”。
17.2 降低预览分辨率
这是最直接、最有效的优化手段。预览分辨率降低后,每一帧的数据量减少,ISP的处理压力、内存带宽占用、CPU负载都会同步下降。
17.2.1 如何选择合适的分辨率?
我个人习惯的做法是:根据设备的内存和CPU型号,动态选择预览分辨率。不要一刀切地固定为某个值,而是做一个分级策略。
| 设备等级 | 推荐预览分辨率 | 说明 |
|---|---|---|
| 旗舰机(骁龙8系) | 1920x1080 或 2560x1440 | 可以开启高帧率模式 |
| 中端机(骁龙6/7系) | 1280x720 | 平衡画质与性能 |
| 低端机(骁龙4系/联发科低端) | 640x480 或 800x600 | 优先保证流畅度 |
代码实现上,我们可以在打开相机前先查询设备支持的预览尺寸列表,然后根据策略选择最接近目标分辨率的尺寸。
// 示例:根据设备等级选择预览分辨率
private Size selectPreviewSize(List<Size> supportedSizes, int deviceLevel) {
Size targetSize;
switch (deviceLevel) {
case DEVICE_LOW_END:
targetSize = new Size(640, 480);
break;
case DEVICE_MID_END:
targetSize = new Size(1280, 720);
break;
case DEVICE_HIGH_END:
default:
targetSize = new Size(1920, 1080);
break;
}
// 从支持的尺寸列表中找最接近的
return findClosestSize(supportedSizes, targetSize);
}
17.3 关闭美颜/滤镜
美颜和滤镜是低端机的“性能杀手”。我见过一个案例,某低端机开启美颜后,预览帧率从25fps直接掉到12fps。为什么?因为美颜算法需要做人脸检测、皮肤平滑、磨皮等操作,这些计算量在低端机上非常昂贵。
17.3.1 策略:默认关闭,按需开启
我的建议是:在低端机上,默认关闭所有美颜和滤镜效果。如果用户想用,可以手动开启,但要在界面上提示“开启后可能影响流畅度”。
代码层面,我们可以通过一个开关来控制:
// 低端机默认关闭美颜
if (deviceLevel == DEVICE_LOW_END) {
beautyEffectEnabled = false;
filterEffectEnabled = false;
// 通知UI层隐藏美颜开关或显示提示
showPerformanceWarning();
}
17.4 减少帧率
高帧率预览(比如60fps)在低端机上基本是奢望。你想想看,每一帧都要经过ISP处理、GPU渲染、SurfaceFlinger合成,帧率越高,CPU和GPU的负载就越大。低端机扛不住,就会频繁掉帧,反而让用户感觉更卡。
17.4.1 目标帧率设定
我个人习惯的做法是:低端机设定为24fps或25fps。这个帧率对人眼来说已经足够流畅(电影也就是24fps),但CPU负载比30fps降低了约20%。
实现方式有两种:
- 方法一:通过Camera2 API的
setRepeatingBurst设置固定的帧率范围。 - 方法二:在预览回调中做帧率控制,比如每40ms才处理一帧。
// 方法一:通过Camera2 API设置帧率范围
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range<Integer>(24, 24));
// 方法二:在预览回调中做帧率限制
private long lastFrameTime = 0;
private static final long FRAME_INTERVAL_MS = 42; // 约24fps
public void onPreviewFrame(byte[] data, Camera camera) {
long now = System.currentTimeMillis();
if (now - lastFrameTime < FRAME_INTERVAL_MS) {
return; // 丢弃这一帧
}
lastFrameTime = now;
// 处理帧数据
}
17.5 知识体系总览
下面这张图总结了低端机专项优化的核心逻辑和决策流程,你可以对照着看:
从图中可以看到,核心就是先判断设备等级,如果是低端机,就依次执行三个优化动作。这三个动作是递进关系:先降分辨率,再关美颜,最后降帧率。如果只做其中一项,效果可能不够明显。
17.6 避坑指南
最后,分享几个我踩过的坑:
- 不要直接硬编码分辨率:不同低端机支持的预览尺寸不一样,一定要先查询
StreamConfigurationMap.getOutputSizes(),再从中选择。 - 关闭美颜要彻底:有些美颜SDK即使关闭了,后台还在跑人脸检测。我遇到过这种情况,后来在关闭时直接释放了SDK的实例才解决。
- 帧率降低后要注意AE/AWB的稳定性:帧率太低会导致自动曝光和自动白平衡的收敛变慢。我建议在低帧率模式下,适当增大AE的收敛步长。
嗯,低端机优化其实没那么神秘。说白了就是“舍得放弃”——放弃一些画质,换来流畅的体验。用户不会在意预览分辨率是720P还是480P,但一定会在意相机卡不卡。