# UvcCamera **Repository Path**: left-back/uvcCamera ## Basic Information - **Project Name**: UvcCamera - **Description**: 鸿蒙外接uvc摄像头预览操作程序 - **Primary Language**: C++ - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2025-01-23 - **Last Updated**: 2025-07-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # UvcCamera ### 简介 鸿蒙外接uvc摄像头预览操作程序 1. 支持无界面/有界面预览 2. 支持设置分辨率/曝光度等参数 3. 使用设备为OpenHarmony ### 软件架构 当前为dev版本 ### 安装教程 1. ohpm i uvc_camera ### 使用说明 #### 操作基础类 `UvcCameraManager` ##### `library_name` 常量,需要预览画面时,给`XComponent`的`libraryname`参数设置 例: ```typescript XComponent({ id: "surface_uvc", type: XComponentType.SURFACE, libraryname: UvcCameraManager.library_name, controller: this.xComponent }) .alignRules({ left: { anchor: "__container__", align: HorizontalAlign.Start }, right: { anchor: "__container__", align: HorizontalAlign.End }, top: { anchor: "__container__", align: VerticalAlign.Top }, bottom: { anchor: "__container__", align: VerticalAlign.Bottom } }) .onLoad(async () => { }) .backgroundColor("#fff") ``` ##### `debuggable` debug模式开关,打开后会有基础日志输出 ```typescript let result = UvcCameraManager.debuggable(true); ``` ##### `getUvcDevices` 获取当前设备上的usb摄像头列表 ```extendtypescript let usbDevices = UvcCameraManager.getUvcDevices(); ``` ##### `getDeviceForId` 根据传入的vId和pId获取对应的usb设备 ```extendtypescript let usbDevice = UvcCameraManager.getDeviceForId(vId, pId); ``` ##### `checkDeviceUvc` 检查当前设备是否是uvc摄像头设备 ```extendtypescript let isUvc = UvcCameraManager.checkDeviceUvc(usbDevice); ``` #### 打开摄像头 异步打开摄像头,需要Camera权限,且,需要申请usb临时权限,最大等待超时时间为10s ```extendtypescript try { let cameraDevice :CameraDevice = await UvcCameraManager.openCamera(usbDevice); //打开成功,返回操作对象 } catch (e) { //打开失败,返回异常信息 } ``` #### 关闭摄像头 ```extendtypescript //使用CameraDevice对象来进行后续操作 cameraDevice.close(); ``` #### 设置预览控件 设置当前usb设备数据绘制到对应的`XComponent`控件上,值为`XComponent`的id字段, ```extendtypescript cameraDevice.setDisplaySurfaceId("surface_uvc") ``` #### 设置使用分辨率 设置预览分辨率 支持格式YUY2/MJPEG 分辨率支持列表通过`getSupportParameters`获取 ```extendtypescript let result:boolean = cameraDevice.setPreviewSize(640, 480, CameraFormatMode.YUY2); ``` #### 设置预览监听 ```extendtypescript cameraDevice.setPreviewListener((data:Uint8Array, width:number, height:number) => { }, CameraResultFormat.RGBA); ``` #### 开启预览 开启预览,建议在promise内使用 ```extendtypescript cameraDevice.startPreview(); ``` #### 关闭预览 关闭预览操作,使用`CameraDevice`对象 ```extendtypescript cameraDevice.stopPreview(); ``` #### 设置参数值 支持设置自动曝光/曝光度/分辨率/预览图形变换规则等参数 ```extendtypescript cameraDevice.setParameter(CameraParameter.AUTO_EXPOSURE, true); ``` #### 获取参数信息 获取当前设置的参数信息 ```extendtypescript let autoExposure = cameraDevice.getParameter(CameraParameter.AUTO_EXPOSURE); ``` #### 获取参数范围 可获取分辨率列表,支持的曝光度范围,亮度范围,等 ```extendtypescript let autoExposure = cameraDevice.getSupportParameters(CameraParameter.PREVIEW_SIZE); ``` #### 设置usb断开监听 在usb设备被拔出后回调该监听 ```extendtypescript cameraDevice.setDetachedCloseListener(() => { }); ``` ### 枚举/类 内置枚举/类说明 #### `CameraResultFormat` 预览监听返回的数据类型。 目前只支持`RGBA`、`NV21` #### `CameraFormatMode` 预览分辨率使用的格式类型,根据分辨率列表返回值确定 目前支持`MJPEG`、`YUY2` #### `IntRange` 使用`getSupportParameters`时,当前返回值为范围值时使用,返回最大值和最小值 `min`:最小值 `max`:最大值 #### `DisplayTransformState` 对应当前`surface`窗口变化支持的类型 * `TRANSFORM_IDENTITY`:无变化 * `TRANSFORM_MIRROR_HORIZONTAL`:水平镜像 * `TRANSFORM_MIRROR_VERTICAL`:垂直镜像 * `TRANSFORM_ROTATE_90`:旋转90度 * `TRANSFORM_ROTATE_180`:旋转180度 * `TRANSFORM_ROTATE_270`:旋转270度 * `TRANSFORM_FLIP_H_ROTATE_90`:旋转90度+水平镜像 * `TRANSFORM_FLIP_H_ROTATE_180`:旋转180度+水平镜像 * `TRANSFORM_FLIP_H_ROTATE_270`:旋转270度+水平镜像 * `TRANSFORM_FLIP_V_ROTATE_90`:旋转90度+垂直镜像 * `TRANSFORM_FLIP_V_ROTATE_180`:旋转180度+垂直镜像 * `TRANSFORM_FLIP_V_ROTATE_270`:旋转270度+垂直镜像s * #### `CameraParameter` 目前支持设置/获取的参数信息 * `AUTO_EXPOSURE`: 自动曝光状态 * `EXPOSURE`: 曝光度值 * `BRIGHTNESS`: 亮度值 * `CONTRAST`: 对比度值 * `GAIN`: 增益值 * `SATURATION`: 饱和度 * `ZOOM`: 缩放大小 * `DISPLAY_TRANSFORM`: 窗口变化支持的类型,见`DisplayTransformState` * `PREVIEW_SIZE`: 分辨率信息 #### `CameraSupportParameters` 获取支持的参数范围 `AUTO_EXPOSURE`:是否支持自动曝光 `EXPOSURE`:曝光度范围,为null或者 最大值 = 最小值时,表示不支持 `BRIGHTNESS`:亮度范围,为null或者 最大值 = 最小值时,表示不支持 `CONTRAST`:对比度范围,为null或者 最大值 = 最小值时,表示不支持 `GAIN`:增益值范围,为null或者 最大值 = 最小值时,表示不支持 `SATURATION`:饱和度范围,为null或者 最大值 = 最小值时,表示不支持 `ZOOM`:缩放范围,为null或者 最大值 = 最小值时,表示不支持 `PREVIEW_SIZE`:支持的分辨率列表 #### `CameraSize` 分辨率信息 * `width`: 宽度 * `height`:高度 * `format`:对应的分辨率,详见`CameraFormatMode` ### 例: ```extendtypescript @Component struct SurfaceChild { private mCameraDevice : CameraDevice | null | undefined; build() { NavDestination() { RelativeContainer() { XComponent({ id: "surface_uvc", type: XComponentType.SURFACE, libraryname: UvcCameraManager.library_name, }) .alignRules({ left: { anchor: "__container__", align: HorizontalAlign.Start }, right: { anchor: "__container__", align: HorizontalAlign.End }, top: { anchor: "__container__", align: VerticalAlign.Top }, bottom: { anchor: "__container__", align: VerticalAlign.Bottom } }) .onLoad(async () => { }) .backgroundColor("#fff") } .width("100%") .height("100%") } .width("100%") .height("100%") .hideTitleBar(true) .onAppear(() => { }) .onBackPressed(() => { return true; }) .onShown(async () => { this.open(); }) .onHidden(() => { this.close(); }) } private updateRotation() { if (!this.mCameraDevice) { return; } this.mCameraDevice.setParameter(CameraParameter.DISPLAY_TRANSFORM, DisplayTransformState.TRANSFORM_ROTATE_90) } private async open() { hilog.debug(0x0000, "surfaceDraw", "获取到的设备信息:%{public}s", JSON.stringify(usbDevice)); let devices = UvcCameraManager.getUvcDevices(); if (!devices || devices.length === 0) { return; } this.mCameraDevice = await UvcCameraManager.openCamera(devices[0]); if (!this.mCameraDevice) { return; } this.initParameter(); this.mCameraDevice.setDisplaySurfaceId("surface_uvc"); this.mCameraDevice.setPreviewSize(640, 480, CameraFormatMode.YUY2); this.mCameraDevice.setPreviewListener((bytes, width, height) => { // hilog.warn(0x0000, "surfaceDraw", "当前数据帧:%{public}d,%{public}d*%{public}d", bytes.byteLength, width, height); }, CameraResultFormat.NV21) this.mCameraDevice.startPreview(); } private initParameter() { if (!this.mCameraDevice) { return; } let currentSupportExposure = this.mCameraDevice.getSupportParameters(CameraSupportParameters.EXPOSURE); let currentSupportBrightness = this.mCameraDevice.getSupportParameters(CameraSupportParameters.BRIGHTNESS); let currentSupportContrast = this.mCameraDevice.getSupportParameters(CameraSupportParameters.CONTRAST); let currentSupportGain = this.mCameraDevice.getSupportParameters(CameraSupportParameters.GAIN); let currentSupportSaturation = this.mCameraDevice.getSupportParameters(CameraSupportParameters.SATURATION); let currentSupportPreviewSizes = this.mCameraDevice.getSupportParameters(CameraSupportParameters.PREVIEW_SIZE); let currentAutoExposure = this.mCameraDevice.getParameter(CameraParameter.AUTO_EXPOSURE) ?? false; let currentExposure = this.mCameraDevice.getParameter(CameraParameter.EXPOSURE); let currentBrightness = this.mCameraDevice.getParameter(CameraParameter.BRIGHTNESS); let currentGain = this.mCameraDevice.getParameter(CameraParameter.GAIN); let currentContrast = this.mCameraDevice.getParameter(CameraParameter.CONTRAST); let currentSaturation = this.mCameraDevice.getParameter(CameraParameter.SATURATION); let currentSelectPreviewSize = this.mCameraDevice.getParameter(CameraParameter.PREVIEW_SIZE) hilog.debug(0x0000, "UvcCamera", "分辨率列表:%{public}s", JSON.stringify(currentSupportPreviewSizes)); hilog.debug(0x0000, "UvcCamera", "曝光度列表:%{public}s", JSON.stringify(currentSupportExposure)); hilog.debug(0x0000, "UvcCamera", "亮度列表:%{public}s", JSON.stringify(currentSupportBrightness)); hilog.debug(0x0000, "UvcCamera", "增益值列表:%{public}s", JSON.stringify(currentSupportGain)); hilog.debug(0x0000, "UvcCamera", "对比度列表:%{public}s", JSON.stringify(currentSupportContrast)); hilog.debug(0x0000, "UvcCamera", "饱和度列表:%{public}s", JSON.stringify(currentSupportSaturation)); hilog.debug(0x0000, "UvcCamera", "当前自动曝光状态:%{public}s", JSON.stringify(currentAutoExposure)); hilog.debug(0x0000, "UvcCamera", "当前曝光度:%{public}s", JSON.stringify(currentExposure)); hilog.debug(0x0000, "UvcCamera", "当前亮度:%{public}s", JSON.stringify(currentBrightness)); hilog.debug(0x0000, "UvcCamera", "当前增益值:%{public}s", JSON.stringify(currentSupportGain)); hilog.debug(0x0000, "UvcCamera", "当前对比度:%{public}s", JSON.stringify(currentContrast)); hilog.debug(0x0000, "UvcCamera", "当前饱和度:%{public}s", JSON.stringify(currentSaturation)); } private close() { if (this.mCameraDevice) { this.mCameraDevice.stopPreview(); this.mCameraDevice.close(); } } } ```