HarmonyOS技术精讲-Camera Kit(相机服务)第1篇:Camera Kit概览与核心概念
HarmonyOS技术精讲-Camera Kit相机服务第1篇Camera Kit概览与核心概念一、开篇Camera Kit到底解决了什么问题HarmonyOS NEXT的相机开发里很多开发者第一次接触Camera Kit时会遇到一个尴尬的情况官方文档的示例代码能跑起来但一旦需要在同一个界面里同时处理预览、拍照、录像、人脸检测就会发现状态管理变得非常混乱。核心问题在于Camera Kit不是一个简单的相机功能调用而是一套完整的设备-会话-输出流架构。如果你不理解这个三层模型再多代码也跑不稳。先明确几个基本认知Camera Kit不是帮你调用系统相机的捷径而是给你完全控制相机硬件的能力它适合需要自定义相机界面的场景比如扫码、美颜相机、专业模式相机不适合的场景只是需要拍照后选照片应该用Gallery Kit而不是Camera Kit二、核心架构设备、会话、输出流Camera Kit的工作流程可以抽象为三个层次层次角色对应API相机设备层物理摄像头CameraDevice、CameraManager相机会话层配置和协调CaptureSession输出流层数据输出PhotoOutput、VideoOutput、PreviewOutput和Android的Camera2非常类似但HarmonyOS对生命周期管理做了更严格的绑定。2.1 相机设备相机设备代表物理摄像头。CameraManager负责管理设备列表你需要通过它获取可用的摄像头通常是后置和前置。// 获取相机管理器letcameraManagercamera.getCameraManager(photoContext);// 获取设备列表letcameras:Arraycamera.CameraDevicecameraManager.getSupportedCameras();// 选择后置摄像头letbackCameracameras.find((device){returndevice.cameraPositioncamera.CameraPosition.CAMERA_POSITION_BACK;});这里有一个经常被忽略的点getSupportedCameras返回的列表在不同设备上顺序不同。不要假设索引0就是后置摄像头必须用filter或find。2.2 相机会话会话是Camera Kit最难的部分因为它负责协调输入和输出。一个会话必须同时包含输入相机设备和至少一个输出预览、拍照、录像等。// 创建会话letcaptureSessioncameraManager.createCaptureSession();// 创建输入流letcameraInputcameraManager.createCameraInput(backCamera);// 开启输入流相机开始工作awaitcameraInput.open();// 添加输入到会话captureSession.addInput(cameraInput);// 创建输出流并添加letpreviewOutput...;// 预览输出captureSession.addOutput(previewOutput);letphotoOutput...;// 拍照输出captureSession.addOutput(photoOutput);// 开始会话awaitcaptureSession.start();这里的关键限制会话必须同时管理多个输出流但输出流之间是竞争关系的。比如设置不同的分辨率参数或同时调用拍照和录像可能会直接抛出异常。2.3 输出流输出流是最容易出问题的地方。Camera Kit提供了三种标准输出流PreviewOutput预览画面显示在Surface上PhotoOutput拍照图片VideoOutput录像视频流创建预览输出流的正确方式// 需要先创建SurfaceletsurfaceIdawaitcreatePreviewSurface();// 具体实现见下文letpreviewOutputcameraManager.createPreviewOutput(surfaceId);很多人直接照搬官方示例但不知道Surface必须和相机参数匹配。比如预览分辨率是1920x1080但Surface创建时设错了大小预览出来就是黑的或者扭曲的。三、底层机制ISP和HDI这两个概念对理解Camera Kit性能至关重要。ISP (Image Signal Processor)图像信号处理器负责将RAW数据转换为最终图像。Camera Kit允许你设置ISP参数比如降噪级别但API有限。HDI (Hardware Device Interface)硬件设备接口层是Camera Kit和硬件之间的抽象层。HDI负责底层的驱动程序封装开发者不需要直接接触但它决定了你在哪里能获取到原生缓冲区哪里只能用封装好的API。实际开发中ISP参数会影响性能。例如开启大量降噪会导致拍照延迟高这在扫码场景下直接导致体验崩塌。四、工作流程示意为了帮你快速理解这里用伪代码梳理典型流程1. 获取CameraManager全局只有一个 2. 通过CameraManager获取可用相机列表 3. 选择相机创建CameraInput 4. 创建CaptureSession 5. 配置会话添加输入、添加输出流 6. 启动会话 7. 运行时修改参数变焦、曝光等 8. 停止会话 9. 释放资源这个顺序不能错。某些步骤的先后顺序是硬性要求比如必须在start之前添加输入输出。五、常见问题与踩坑问题1会话创建失败报错“Invalid session configuration”现象调用captureSession.start()时抛出异常。原因会话配置不完整。常见场景你只添加了PreviewOutput就急着启动但PhotoOutput和VideoOutput没有同时添加。或者你添加了输出流但没把对应的Surface准备好。解决方案在调用start之前确保所有输出流都已addOutput并且Surface已创建完成。推荐用一个状态变量跟踪StatesessionReady:booleanfalse;// 在确认所有配置完成后再标记this.sessionReadytrue;然后在build()中根据sessionReady决定是否渲染预览。问题2预览画面方向不正确现象画面旋转90度或倒置。原因手机方向变化时相机传感器方向没同步。Camera Kit默认使用传感器物理方向但UI可能旋转了。解决方案监听系统方向变化调用captureSession.setDisplayOrientation(rotation)或者设置PreviewOutput的rotation参数。注意这个设置必须在start之前或之后立即设置在流运行过程中修改不一定生效。问题3权限申请后仍然无法获取相机现象申请了ohos.permission.CAMERA但getSupportedCameras返回空列表。原因权限需要运行时动态申请且用户拒绝后不会再次弹窗。同时某些设备如平板可能没有后置摄像头或者是模拟器环境不支持。解决方案在onPageShow()中检查权限拒绝后引导用户手动开启。同时处理网络请求中潜在的设备列表为空的情况。六、几个真正容易忽略的问题6.1 生命周期绑定Camera Kit的生命周期必须和页面生命周期强绑定。如果页面销毁时不释放相机会话下次进入页面时相机设备可能被其他进程占用。aboutToDisappear(){if(this.captureSession){this.captureSession.release();this.captureSessionnull;}if(this.cameraInput){this.cameraInput.close();this.cameraInputnull;}}这里要注意顺序先释放会话再关闭输入。6.2 输出流Surface阻塞PreviewOutput需要绑定到XComponent或者其他Surface组件。如果页面布局复杂Surface创建可能会被UI线程阻塞导致预览黑屏。应对策略提前创建Surface或者用异步方式创建。不要等用户点击按钮后才创建Surface。6.3 闪退问题Camera Kit有个很奇怪的行为当你快速切换前后摄像头时如果上一个相机还在onCameraStatus回调中新的操作会导致闪退。官方对此没有明确说明实际项目中建议加锁或者延迟切换。七、最佳实践必须遵守的三个原则1. 不要让Camera Kit在主线程操作相机配置是耗时操作特别是start()和release()。推荐用单独的TaskPool或arkts异步任务执行。2. 使用状态变量管理相机状态不要用全局变量记录相机状态页面被销毁后状态丢失。用State或Storage保证页面重建时能恢复。3. 主动释放资源Camera Kit的底层通过HDI持有硬件资源不主动释放会导致系统相机不可用其他应用无法拍照。特别在页面跳转时务必清理。八、FAQQ为什么真机预览正常模拟器上相机列表为空A模拟器没有物理摄像头Camera Kit返回空列表是预期行为。测试必须在真机上进行。Q为什么页面返回后相机状态丢失A页面销毁后Camera Kit会释放资源。返回时重建页面需要重新初始化相机。这是设计如此不是bug。Q为什么第一次获取相机成功第二次失败A主要原因可能是第一次使用后没有正确释放资源导致第二次找不到可用设备。检查release()是否在正确时机调用。如果你也遇到过类似问题建议重点检查生命周期绑定和状态同步逻辑。下一篇会讲如何实现「预览拍照录像」三合一功能包括踩过的坑和最佳实践。