一、背景引入:参数调节是干啥的?

上篇文章咱聊了相机开发的基础——拍照和录像。有兄弟问了:“我拍出来的照片咋这么暗?”“为啥对不上焦?”“颜色咋怪怪的?”

嘿,这些问题,都是参数没调好!

今儿个咱就聊聊相机参数调节这档子事儿。HarmonyOS 提供了 6 大参数调节能力:

  1. 对焦 - 让画面清晰
  2. 手电筒 - 补光照明
  3. 白平衡 - 调整颜色
  4. 微距 - 拍小物件
  5. 压力管控 - 防止手机发烫
  6. 相机控制器 - 美颜虚化(直播专用)

我的建议

  • 基础拍照 → 调对焦、白平衡就够了
  • 夜景拍照 → 加上手电筒
  • 拍花花草草 → 用微距
  • 直播/视频通话 → 相机控制器(美颜虚化)
  • 长时间录像 → 注意压力管控

二、对焦:让画面清晰起来

2.1 这玩意儿是干啥的?

对焦就是让相机对准你要拍的东西,让它变清晰。

三种对焦模式

  • 自动对焦 (FOCUS_MODE_AUTO) - 点哪对哪
  • 连续自动对焦 (FOCUS_MODE_CONTINUOUS_AUTO) - 一直自动对焦
  • 手动对焦 - 自己调(本文不讲)

2.2 开发步骤

步骤 1:导入接口

import { camera } from '@kit.CameraKit';
import { BusinessError } from '@kit.BasicServicesKit';

步骤 2:检查是否支持对焦模式

function isFocusModeSupported(photoSession: camera.PhotoSession): boolean {
  let status: boolean = false;
  
  try {
    // 检查是否支持自动对焦模式
    status = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_AUTO);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`The isFocusModeSupported call failed. error code: ${err.code}`);
  }
  
  return status;
}

注意

  • 需要在 Session 调用 commitConfig 完成配流之后调用
  • 不同设备支持的对焦模式可能不一样

步骤 3:设置对焦模式

function setFocusMode(photoSession: camera.PhotoSession): void {
  const focusPoint: camera.Point = {x: 1, y: 1};
  
  try {
    // 设置自动对焦模式
    photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_AUTO);
    
    // 设置对焦点(自动对焦模式下才有效)
    photoSession.setFocusPoint(focusPoint);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`The setFocusMode and setFocusPoint call failed. error code: ${err.code}`);
  }
}

说明

  • focusPoint 是对焦点坐标,范围是 0-1
  • {x: 0.5, y: 0.5} 表示画面中心
  • 只有自动对焦模式下,设置对焦点才有效

2.3 状态监听

监听对焦状态变化:

function onFocusStateChange(photoSession: camera.PhotoSession): void {
  photoSession.on('focusStateChange', (err: BusinessError, focusState: camera.FocusState) => {
    if (err !== undefined && err.code !== 0) {
      console.error(`focusStateChange error code: ${err.code}`);
      return;
    }
    
    console.info(`focusStateChange focusState: ${focusState}`);
    
    // 自动对焦成功后,可切换为连续自动对焦
    if (focusState === camera.FocusState.FOCUS_STATE_FOCUSED) {
      photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
    }
  });
}

对焦状态枚举

  • FOCUS_STATE_UNFOCUSED - 未对焦
  • FOCUS_STATE_FOCUSED - 已对焦
  • FOCUS_STATE_FOCUSED_LOCKED - 对焦锁定

2.4 避坑指南

坑 1:没检查支持就设置

// 错误示范
photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_AUTO);
// 结果:设备不支持,报错

正确姿势

// 先检查
if (photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_AUTO)) {
  // 再设置
  photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_AUTO);
}

坑 2:在 commitConfig 之前设置

// 错误时机
session.beginConfig();
session.setFocusMode(...);  // 太早了!
session.commitConfig();

正确时机

session.beginConfig();
session.addInput(...);
session.addOutput(...);
await session.commitConfig();  // 先提交
session.setFocusMode(...);     // 再设置

三、手电筒:黑夜中的光

3.1 这玩意儿是干啥的?

手电筒就是让设备的闪光灯常亮,用来补光。

使用场景

  • 夜景拍照
  • 当手电筒用
  • 视频通话补光

注意事项

  • 后置相机 + 闪光灯模式关闭 → 手电筒无法启用
  • 前置相机 → 手电筒可以正常启用
  • 从前置切换到后置 → 手电筒会自动关闭

3.2 开发步骤

步骤 1:检查是否支持手电筒

function isTorchSupported(cameraManager: camera.CameraManager): boolean {
  let torchSupport: boolean = false;
  
  try {
    torchSupport = cameraManager.isTorchSupported();
  } catch (error) {
    let err = error as BusinessError;
    console.error('Failed to torch. errorCode = ' + err.code);
  }
  
  console.info('Returned with the torch support status:' + torchSupport);
  return torchSupport;
}

步骤 2:检查是否支持指定的手电筒模式

function isTorchModeSupported(cameraManager: camera.CameraManager, torchMode: camera.TorchMode): boolean {
  let isTorchModeSupport: boolean = false;
  
  try {
    isTorchModeSupport = cameraManager.isTorchModeSupported(torchMode);
  } catch (error) {
    let err = error as BusinessError;
    console.error('Failed to set the torch mode. errorCode = ' + err.code);
  }
  
  return isTorchModeSupport;
}

手电筒模式枚举

  • TORCH_MODE_OFF - 关闭
  • TORCH_MODE_ON - 开启

步骤 3:设置手电筒模式

function setTorchModeSupported(cameraManager: camera.CameraManager, torchMode: camera.TorchMode): void {
  cameraManager.setTorchMode(torchMode);
  
  let isTorchMode = cameraManager.getTorchMode();
  console.info(`Returned with the torch mode supported mode: ${isTorchMode}`);
}

使用示例

// 打开手电筒
if (cameraManager.isTorchSupported()) {
  cameraManager.setTorchMode(camera.TorchMode.TORCH_MODE_ON);
}

// 关闭手电筒
cameraManager.setTorchMode(camera.TorchMode.TORCH_MODE_OFF);

3.3 状态监听

监听手电筒状态变化:

function onTorchStatusChange(cameraManager: camera.CameraManager): void {
  cameraManager.on('torchStatusChange', (err: BusinessError, torchStatusInfo: camera.TorchStatusInfo) => {
    if (err !== undefined && err.code !== 0) {
      console.error(`Callback Error, errorCode: ${err.code}`);
      return;
    }
    
    console.info(`onTorchStatusChange, isTorchAvailable: ${torchStatusInfo.isTorchAvailable}, 
                  isTorchActive: ${torchStatusInfo.isTorchActive}, 
                  level: ${torchStatusInfo.torchLevel}`);
  });
}

TorchStatusInfo 参数

  • isTorchAvailable - 手电筒是否可用
  • isTorchActive - 手电筒是否激活
  • torchLevel - 手电筒亮度级别

3.4 避坑指南

坑 1:前置相机切换后置,手电筒没关

// 错误示范
// 前置相机开启手电筒
cameraManager.setTorchMode(camera.TorchMode.TORCH_MODE_ON);

// 切换到后置相机
// 手电筒还开着,但后置可能不支持

正确姿势

// 切换相机前,先关闭手电筒
cameraManager.setTorchMode(camera.TorchMode.TORCH_MODE_OFF);

// 再切换相机
// ...切换相机的代码...

坑 2:闪光灯模式没关就开手电筒

// 错误示范
photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO);
cameraManager.setTorchMode(camera.TorchMode.TORCH_MODE_ON);
// 结果:手电筒开不了

正确姿势

// 先关闭闪光灯模式
photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_OFF);

// 再开手电筒
cameraManager.setTorchMode(camera.TorchMode.TORCH_MODE_ON);

四、白平衡:让颜色更真实

4.1 这玩意儿是干啥的?

白平衡是相机的色彩校正技术,通过设置白平衡,使照片产生不同的效果。

使用场景

  • 室内拍照偏黄 → 调白平衡
  • 阴天拍照偏冷 → 调白平衡
  • 想要特殊色调 → 调白平衡

支持的模式(API 20+):

  • WHITE_BALANCE_MODE_AUTO - 自动
  • WHITE_BALANCE_MODE_MANUAL - 手动
  • WHITE_BALANCE_MODE_CLOUDY - 阴天
  • WHITE_BALANCE_MODE_INCANDESCENT - 白炽光
  • WHITE_BALANCE_MODE_FLUORESCENT - 荧光
  • WHITE_BALANCE_MODE_DAYLIGHT - 日光

4.2 两种设置方法

方法一:设置白平衡模式

function isWhiteBalanceModeSupported(session: camera.PhotoSession | camera.VideoSession): boolean {
  let status: boolean = false;
  let whiteBalanceMode: camera.WhiteBalanceMode | undefined = undefined;
  
  try {
    let mode: camera.WhiteBalanceMode = camera.WhiteBalanceMode.DAYLIGHT;
    
    // 检查是否支持
    status = session.isWhiteBalanceModeSupported(mode);
    
    if (status) {
      // 设置白平衡模式
      session.setWhiteBalanceMode(mode);
    }
    
    // 查看当前已设置的白平衡模式
    whiteBalanceMode = session.getWhiteBalanceMode();
    
  } catch (error) {
    let err = error as BusinessError;
    console.error(`The isWhiteBalanceModeSupported call failed. error code: ${err.code}`);
  }
  
  return status;
}

方法二:设置白平衡值

function getWhiteBalanceRange(session: camera.PhotoSession | camera.VideoSession): Array<number> {
  let range: Array<number> = [];
  
  try {
    // 获取当前设备支持的白平衡值范围
    range = session.getWhiteBalanceRange();
    
    // 在范围内设置白平衡值
    let whiteBalance: number = 3000;
    if (whiteBalance >= range[0] && whiteBalance <= range[1]) {
      session.setWhiteBalance(whiteBalance);
    }
    
    // 查看当前已设置的白平衡值
    whiteBalance = session.getWhiteBalance();
    
  } catch (error) {
    let err = error as BusinessError;
    console.error(`The getWhiteBalanceRange call failed. error code: ${err.code}`);
  }
  
  return range;
}

注意

  • 当同时设置白平衡模式和设置白平衡值时,仅可生效一种
  • 默认白平衡模式优先生效

4.3 避坑指南

坑 1:超出范围设置白平衡值

// 错误示范
let range = session.getWhiteBalanceRange();  // [2000, 8000]
session.setWhiteBalance(10000);  // 超出范围了!

正确姿势

let range = session.getWhiteBalanceRange();  // [2000, 8000]
let whiteBalance = 5000;

// 先检查范围
if (whiteBalance >= range[0] && whiteBalance <= range[1]) {
  session.setWhiteBalance(whiteBalance);
}

五、微距:拍小物件神器

5.1 这玩意儿是干啥的?

微距能力是指通过光学设计与算法优化,实现近距离对焦并清晰捕捉微小物体细节的相机功能。

使用场景

  • 拍花朵
  • 拍昆虫
  • 拍珠宝
  • 拍电子产品细节

支持版本:API 19+

5.2 开发步骤

步骤 1:检查是否支持微距

let isSupported: boolean = photoSession.isMacroSupported();

步骤 2:开启或关闭微距

function EnableMacro(photoSession: camera.PhotoSession): void {
  let isSupported: boolean = photoSession.isMacroSupported();
  
  if (isSupported) {
    // 开启微距
    photoSession.enableMacro(true);
  }
}

5.3 状态监听(API 20+)

监听微距能力变化:

// 回调函数
function callback(err: BusinessError, macroStatus: boolean): void {
  if (err !== undefined && err.code !== 0) {
    console.error(`Callback Error, errorCode: ${err.code}`);
    return;
  }
  console.info(`Macro state: ${macroStatus}`);
}

// 注册监听
function registerMacroStatusChanged(photoSession: camera.PhotoSession): void {
  photoSession.on('macroStatusChanged', callback);
}

// 解注册
function unregisterMacroStatusChanged(photoSession: camera.PhotoSession): void {
  photoSession.off('macroStatusChanged');
}

5.4 避坑指南

坑 1:不支持微距的设备强行开启

// 错误示范
photoSession.enableMacro(true);  // 设备不支持,没反应

正确姿势

// 先检查
if (photoSession.isMacroSupported()) {
  // 再开启
  photoSession.enableMacro(true);
}

六、压力管控:防止手机发烫

6.1 这玩意儿是干啥的?

在长时间使用相机的场景(如直播业务)中,相机应用可以通过监听系统压力等级变化,动态调整画质(如帧率、分辨率等),平衡功耗、发热和系统负载,保证功能长时间可用。

使用场景

  • 直播
  • 长时间录像
  • 视频会议

支持版本:API 20+

6.2 状态监听

监听系统压力等级变化:

import { BusinessError } from '@kit.BasicServicesKit';
import { camera } from '@kit.CameraKit';

// 回调函数
function callback(err: BusinessError, systemPressureLevel: camera.SystemPressureLevel): void {
  if (err !== undefined && err.code !== 0) {
    console.error(`Callback Error, errorCode: ${err.code}`);
    return;
  }
  console.info(`systemPressureLevel: ${systemPressureLevel}`);
  
  // 根据压力等级调整画质
  switch (systemPressureLevel) {
    case camera.SystemPressureLevel.LEVEL_HIGH:
      // 压力高,降低帧率/分辨率
      reduceQuality();
      break;
    case camera.SystemPressureLevel.LEVEL_NORMAL:
      // 压力正常,恢复画质
      restoreQuality();
      break;
  }
}

// 注册监听
function registerSystemPressureLevelChangeCallback(photoSession: camera.PhotoSession): void {
  photoSession.on('systemPressureLevelChange', callback);
}

系统压力等级枚举

  • LEVEL_NORMAL - 正常
  • LEVEL_HIGH - 高

6.3 避坑指南

坑 1:收到高压不处理

// 错误示范
photoSession.on('systemPressureLevelChange', (err, level) => {
  console.info(`压力等级:${level}`);
  // 然后就没然后了...
});
// 结果:手机发烫,应用崩溃

正确姿势

photoSession.on('systemPressureLevelChange', (err, level) => {
  if (level === camera.SystemPressureLevel.LEVEL_HIGH) {
    // 降低帧率
    setFrameRate(15);
    // 降低分辨率
    setResolution('720p');
  }
});

七、相机控制器:直播美颜神器

7.1 这玩意儿是干啥的?

相机控制器为直播和视频通话场景设计,通过相机控制器,为应用在直播场景提供美颜、虚化等能力。

使用限制

  • 仅支持前置镜头
  • 仅支持录像模式
  • 最高支持 1080P 分辨率和 30fps 帧率

支持版本:API 20+

支持的效果

  • 美颜
  • 背景虚化

7.2 开发步骤

步骤 1:检查是否支持相机控制器

function isControlCenterSupported(videoSession: camera.VideoSession): boolean {
  let isSupported: boolean = videoSession.isControlCenterSupported();
  return isSupported;
}

步骤 2:查询支持的效果类型

function getSupportedEffectTypes(videoSession: camera.VideoSession): Array<camera.ControlCenterEffectType> {
  let effectTypes: Array<camera.ControlCenterEffectType> = [];
  effectTypes = videoSession.getSupportedEffectTypes();
  return effectTypes;
}

步骤 3:启用或关闭控制器

function enableControlCenter(videoSession: camera.VideoSession, enable: boolean): void {
  let isSupported: boolean = videoSession.isControlCenterSupported();
  
  if (isSupported) {
    videoSession.enableControlCenter(enable);
  }
}

使用示例

// 启用相机控制器
if (videoSession.isControlCenterSupported()) {
  videoSession.enableControlCenter(true);
  // 状态栏会新增视频效果图标
  // 用户可点击图标调节美颜和背景虚化
}

7.3 状态监听

监听控制器效果的使能状态:

// 回调函数
function callback(err: BusinessError, status: camera.ControlCenterStatusInfo): void {
  if (err !== undefined && err.code !== 0) {
    console.error(`Callback Error, errorCode: ${err.code}`);
    return;
  }
  console.info(`controlCenterEffectStatusChange: ${status}`);
}

// 注册监听
function registerControlCenterEffectStatusChangeCallback(videoSession: camera.VideoSession): void {
  videoSession.on('controlCenterEffectStatusChange', callback);
}

7.4 避坑指南

坑 1:后置镜头用相机控制器

// 错误示范
// 后置镜头
videoSession.enableControlCenter(true);
// 结果:没反应,不支持

正确姿势

// 先检查
if (videoSession.isControlCenterSupported()) {
  // 再启用
  videoSession.enableControlCenter(true);
}

坑 2:拍照模式用相机控制器

// 错误示范
let photoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO);
photoSession.enableControlCenter(true);  // 不支持!

正确姿势

// 相机控制器只支持录像模式
let videoSession = cameraManager.createSession(camera.SceneMode.NORMAL_VIDEO) as camera.VideoSession;
videoSession.enableControlCenter(true);

八、总结

好了,唠了这么多,总结一下:

6 大参数调节能力

功能 作用 支持版本 使用场景
对焦 让画面清晰 全版本 所有拍照场景
手电筒 补光照明 全版本 夜景、视频通话
白平衡 调整颜色 API 20+ 室内、阴天
微距 拍小物件 API 19+ 花朵、昆虫、珠宝
压力管控 防止发烫 API 20+ 直播、长时间录像
相机控制器 美颜虚化 API 20+ 直播、视频通话

有啥坑?

  1. 没检查支持就设置参数
  2. 在 commitConfig 之前设置参数
  3. 前置切换后置,手电筒没关
  4. 闪光灯模式没关就开手电筒
  5. 超出范围设置白平衡值
  6. 不支持微距的设备强行开启
  7. 收到高压不处理
  8. 后置镜头用相机控制器
  9. 拍照模式用相机控制器

我的建议

基础拍照

  • 调对焦就够了
  • 自动对焦 + 连续自动对焦切换

夜景拍照

  • 对焦 + 手电筒
  • 注意切换相机时关闭手电筒

拍小物件

  • 微距 + 对焦
  • 先检查是否支持微距

直播/视频通话

  • 相机控制器(美颜虚化)
  • 压力管控(防止发烫)
  • 只支持前置镜头 + 录像模式

长时间录像

  • 压力管控必须加
  • 根据压力等级动态调整画质

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐