OpenHarmony相机的用法详解
前言
API和组件介绍
OpenHarmony 框架相机功能需要调用相机管理接口、图片处理接口、媒体服务接口和媒体库管理接口等API和组件实现完整的相机操作和使用。
-
用于控制设备相机的主要 API。当您构建相机应用时,该 API 可用于获取相机设备列表、加载相机、加载预览输出模块、拍照和录像等功能。
-
用于接收拍照生成的图片数据。
-
用于创建视频接收器录制视频并保存到设备。
-
用于读取保存的图片和视频数据。
-
用于展示相机预览图像数据的组件。
相机组件架构图


相机功能的开发流程
-
在配置文件中添加相机需要的权限,编写用户授权逻辑;
-
在页面中添加 XComponent 组件;
-
初始化相机管理器,获取可用摄像头设备;
-
创建拍照会话实例;
-
创建相机输入实例;
-
创建预览输出实例;
-
创建照片输出实例或者视频输出实例,并创建对应的保存逻辑;
-
配置拍照会话实例;
-
开启拍照会话实例;
-
在页面中添加拍照和录像触发条件,并编写逻辑;
相机权限
相机功能需要用户授予相应的权限后才能使用,如果用户不同意授权,应用是无法使用相机功能的,调用时会抛出 Permission to Access Camera Denied 错误,提示应用未取得用户授权。
相机功能需要的权限:
-
摄像头权限: ohos.permission.CAMERA
-
麦克风权限: ohos.permission.MICROPHONE
-
媒体和文件操作权限: ohos.permission.MEDIA_LOCATION, ohos.permission.READ_MEDIA, ohos.permission.WRITE_MEDIA
相关文档:
配置权限
在进行相机功能开发前需要先在配置文件中配置需要的权限信息。
Stage 模型配置 module.json5
{ "module":{ "requestPermissions": [ { "name": "ohos.permission.CAMERA" }, { "name": "ohos.permission.MICROPHONE" }, { "name": "ohos.permission.MEDIA_LOCATION" }, { "name": "ohos.permission.READ_MEDIA" }, { "name": "ohos.permission.WRITE_MEDIA" } ] } }
FA 模型配置 config.json
{ "module":{ "reqPermissions": [ { "name": "ohos.permission.CAMERA" }, { "name": "ohos.permission.MICROPHONE" }, { "name": "ohos.permission.MEDIA_LOCATION" }, { "name": "ohos.permission.READ_MEDIA" }, { "name": "ohos.permission.WRITE_MEDIA" } ] } }
请求用户授权
获取 AbilityContext
Stage 模型通过继承 Ability 接口,在 Ability 被拉起时获取上下文环境。
export default class MainAbility extends Ability { onCreate(want, launchParam) { globalThis.context = this.context } }
FA 模型通过 FeatureAbility API 获取上下文环境。
import FeatureAbility from '@ohos.ability.featureAbility' globalThis.context = FeatureAbility.getContext()
获取 bundleName
Stage 模型通过 Context 可以直接获取到当前应用包名信息。
const bundleName = globalThis.context.abilityInfo.bundleName
FA 模型通过 getBundleName 接口获取当前应用包名信息。
const bundleName = globalThis.context.getBundleName()
获取 accessTokenId
根据给定的包名获取 ApplicationInfo (应用程序信息),其中包含字段:accessTokenId
accessTokenId 是应用在安装时由系统分配的唯一标识,重新安装会刷新。
import Bundle from '@ohos.bundle' const appInfo = Bundle.getApplicationInfo(bundleName: string, bundleFlags: number, userId?: number): Promise<ApplicationInfo> const accessTokenId = appInfo.accessTokenId
校验应用是否授予权限
-
获取访问控制模块对象。
import AbilityAccessCtrl from '@ohos.abilityAccessCtrl' AtManager = AbilityAccessCtrl.createAtManager()
-
校验应用是否授予权限, tokenID 为应用程序的 accessTokenId,permissionName 为权限名称。
AtManager.verifyAccessToken(tokenID: number, permissionName: string): Promise<GrantStatus>
GrantStatus 说明
export enum GrantStatus { // access_token permission check fail PERMISSION_DENIED = -1, // access_token permission check success PERMISSION_GRANTED = 0, }
动态申请权限
拉起弹窗请求用户授权,传入需要申请的权限数组,得到用户授权结果。
Context.requestPermissionsFromUser(permissions: Array<string>) : Promise<PermissionRequestResult>;
PermissionRequestResult 说明
interface PermissionRequestResult { requestCode: number; // 用户传入的权限数组 permissions: Array<string>; // 相应请求权限的结果数组。0表示授权成功,-1表示失败 authResults: Array<number>; }
相机请求用户授权代码示例
Stage 模型为例:
Module 配置文件: Ability 生命周期管理类: 请求用户授权页面:
预览功能的实现
XComponent 组件
XComponent 可用于EGL/OpenGLES和媒体数据写入,并显示在XComponent组件,相机中使用 XComponent 组件来展示预览图像数据。
-
在页面 build 中添加 XComponent 组件
xComponentController: XComponentController = new XComponentController() XComponent({ id: '', type: 'surface', controller: this.xComponentController }).onLoad(() => {})
XComponent 的 width 和 height 可以随页面逻辑需要设置。
-
获取 XComponent 对应 Surface 的 ID
xComponentController.getXComponentSurfaceId(): string
-
设置 XComponent 持有 Surface 的宽度和高度
xComponentController.setXComponentSurfaceSize(value: {surfaceWidth: number, surfaceHeight: number}): void
Surface:用于管理和传递图形和媒体的共享内存。具体场景包括图形的送显、合成,媒体的播放、录制等。 Surface 的 width 和 height 不可随意设置,需要根据摄像头支持的宽和高进行设置。
初始化相机功能
获取相机列表
-
获取相机管理器
import Camera from '@ohos.multimedia.camera' CameraManager = await Camera.getCameraManager(context: Context): Promise<CameraManager>
-
获取支持的所有相机设备列表
Cameras = await CameraManager.getCameras(): Promise<Array<Camera>>
Camera 说明
interface Camera { // 相机ID readonly cameraId: string; // 相机位置 0:相机连接类型 1:后置相机 2:前置相机 readonly cameraPosition: CameraPosition; // 相机类型 0:未指定相机类型 1:广角相机 2:超级广角相机 3:长焦相机 4:深度相机 readonly cameraType: CameraType; // 相机连接类型 0:内置相机 1:外置USB相机 2:分布式相机 readonly connectionType: ConnectionType; }
示例:
--------------Camera Info------------- CameraId: device@3.5/legacy/0 CameraPosition: 1 CameraType: 0 ConnectionType: 0 -------------------------------------- CameraId: device@3.5/legacy/1 CameraPosition: 2 CameraType: 0 ConnectionType: 0 -------------------------------------- CameraId: device@3.5/legacy/2 CameraPosition: 1 CameraType: 0 ConnectionType: 0 -------------------------------------- CameraId: device@3.5/legacy/3 CameraPosition: 1 CameraType: 0 ConnectionType: 0 -------------------------------------- CameraId: device@3.5/legacy/4 CameraPosition: 1 CameraType: 0 ConnectionType: 0 --------------------------------------
拍照会话类
一个会话对应我们一个操作模式,比如用后置摄像头拍照为一个会话。当我们切换摄像头之后,我们要销毁当前的会话,重新创建会话设置相机输入、预览输出和拍照输出等配置。
-
创建拍照会话实例
CaptureSession = await Camera.createCaptureSession(context: Context): Promise<CaptureSession>
-
使用
CameraId创建相机输入实例
CameraInput = await CameraManager.createCameraInput(cameraId: string): Promise<CameraInput>
-
创建预览输出实例, surfaceId 为 xComponent 生成的 surfaceId
PreviewOutput = await Camera.createPreviewOutput(surfaceId: string): Promise<PreviewOutput>
-
开启设置此拍照会话实例
CaptureSession.beginConfig(): Promise<void>
-
为此拍照会话实例添加一个相机输入实例
CaptureSession.addInput(cameraInput: CameraInput): Promise<void>
-
为此拍照会话实例添加一个预览输出实例
CaptureSession.addOutput(previewOutput: PreviewOutput): Promise<void>
-
提交此拍照会话实例的设置
CaptureSession.commitConfig(): Promise<void>
-
开启拍照会话实例
CaptureSession.start(): Promise<void>
获取支持的图像尺寸
CameraInput.getSupportedSizes(format: CameraFormat): Promise<Array<Size>>
示例:
SupportedSizes 0 width = 4160 height = 3120 SupportedSizes 1 width = 4160 height = 2600 SupportedSizes 2 width = 4160 height = 2336 SupportedSizes 3 width = 3840 height = 2160 SupportedSizes 4 width = 3264 height = 2448 SupportedSizes 5 width = 3264 height = 1840 SupportedSizes 6 width = 3120 height = 3120 SupportedSizes 7 width = 2304 height = 1728 SupportedSizes 8 width = 2048 height = 1536 SupportedSizes 9 width = 1920 height = 1440 SupportedSizes 10 width = 1920 height = 1080 SupportedSizes 11 width = 1744 height = 1088 SupportedSizes 12 width = 1280 height = 720 SupportedSizes 13 width = 1232 height = 768 SupportedSizes 14 width = 1152 height = 720 SupportedSizes 15 width = 640 height = 480 SupportedSizes 16 width = 320 height = 240
预览功能代码示例
Stage 模型为例:
预览相机页面:
拍照功能的实现
图像接收器
在使用相机进行拍照操作时,需要创建图像接收器和拍照会话进行绑定,相机在触发拍照动作后,会把图像发送给图像接收器,并触发 imageArrival 回调。
-
创建图像接收器实例,传入图像的宽、高、格式和同时访问的最大图像数。
import Image from '@ohos.multimedia.image' ImageReceiver = Image.createImageReceiver(width: number, height: number, format: number, capacity: number): ImageReceiver
-
获取图像接收器实例的 surfaceId
SurfaceId = await ImageReceiver.getReceivingSurfaceId(): Promise<string>
-
设置收到图像时的监听
ImageReceiver.on(type: 'imageArrival', callback: AsyncCallback<void>): void
-
在监听的回调函数中,获取图像实例
Image = await ImageReceiver.readNextImage(): Promise<Image>
-
获取图像的组件实例
Component = await Image.getComponent(componentType: ComponentType): Promise<Component>
ComponentType 说明
enum ComponentType { // 亮度信息 YUV_Y = 1, // 色度信息 YUV_U = 2, // 色度信息 YUV_V = 3, // Jpeg 类型 JPEG = 4, }
Component 说明
interface Component { // 组件类型 readonly componentType: ComponentType; // 行距 readonly rowStride: number; // 像素间距 readonly pixelStride: number; // 组件缓冲区 readonly byteBuffer: ArrayBuffer; }
-
获取图像的 Buffer
Buffer = Component.byteBuffer
媒体资源文件
创建媒体资源
-
获取媒体库的实例
import MediaLibrary from '@ohos.multimedia.mediaLibrary' MediaLib = MediaLibrary.getMediaLibrary(context: Context): MediaLibrary
-
获取媒体检索配置关键字和媒体类型
FileKeyObj = MediaLibrary.FileKey MediaType = MediaLibrary.MediaType.IMAGE
-
获取公共目录路径
type = MediaLibrary.DirectoryType.DIR_IMAGE PublicPath = await MediaLib.getPublicDirectory(type: DirectoryType): Promise<string>
DirectoryType 说明
enum DirectoryType { // 表示Camera文件路径 DIR_CAMERA = 0, // 表示视频路径 DIR_VIDEO, // 表示图片路径 DIR_IMAGE, // 表示音频路径 DIR_AUDIO, // 表示文档路径 DIR_DOCUMENTS, // 表示下载路径 DIR_DOWNLOAD }
-
创建媒体资源文件
FileAsset = await MediaLib.createAsset(mediaType: MediaType, displayName: string, relativePath: string): Promise<FileAsset>
验证媒体资源文件创建是否成功
-
创建检索条件
let args = FileAsset.id.toString() let fetchOp = { selections: `${FileKeyObj.ID} = ? `, selectionArgs: [args], }
-
根据条件检索文件
FetchFileResult = await MediaLib.getFileAssets(options: MediaFetchOptions): Promise<FetchFileResult>
-
获取文件检索结果中的所有文件资产
FileAssets = await FetchFileResult.getAllObject(): Promise<Array<FileAsset>>
如果 FileAssets 数据大于 0 则文件创建成功
保存图片数据
-
打开当前文件的读写权限
FdNumber = await FileAsset.open(mode: string): Promise<number>
mode:打开文件方式,如:'r'(只读), 'w'(只写), 'rw'(读写)
-
将数据写入文件
import FileIO from '@ohos.fileio' FileIO.write(fd: number, buffer: ArrayBuffer | string, options?: { offset?: number; length?: number; position?: number; encoding?: string; }): Promise<number>
-
关闭当前文件
FileAsset.close(fd: number): Promise<void>
拍照会话类
-
初始化拍照会话类
同相机预览功能实现一样的步骤,创建拍照会话实例、相机输入实例和预览输出实例,并进行配置。
-
创建照片输出实例,此处的 surfaceId 为图像接收器获取的 surfaceId
PhotoOutPut = await CameraManager.createPhotoOutput(surfaceId: string): Promise<PhotoOutput>
-
将照片输出实例配置进拍照会话实例
CaptureSession.addOutput(photoOutput: PhotoOutput): Promise<void>
-
提交此拍照会话实例的设置
CaptureSession.commitConfig(): Promise<void>
-
开启拍照会话实例
CaptureSession.start(): Promise<void>
拍照事件
-
创建拍照设置
const photoSettings = { // 图片旋转角度 rotation: Camera.ImageRotation.ROTATION_0, // 图片质量 quality: Camera..QUALITY_LEVEL_HIGH, }
ImageRotation 说明
enum ImageRotation { // 图片旋转0度 ROTATION_0 = 0, // 图片旋转90度 ROTATION_90 = 90, // 图片旋转180度 ROTATION_180 = 180, // 图片旋转270度 ROTATION_270 = 270 }
QualityLevel 说明
enum QualityLevel { // 图片质量高 QUALITY_LEVEL_HIGH = 0, // 图片质量中等 QUALITY_LEVEL_MEDIUM, // 图片质量差 QUALITY_LEVEL_LOW }
-
调用照片输出实例的拍照方法,触发图像接收器的监听事件,保存图片
PhotoOutput. capture(setting?: PhotoCaptureSetting): Promise<void>
拍照功能代码示例
Stage 模型为例:
拍照功能页面:
录像功能的实现
视频录制器
-
创建媒体资源文件
创建视频资源文件与照片的媒体资源文件创建步骤是一样的,但在创建的时候获取公共资源路径的 MediaType 需要设置为 MediaLibrary.MediaType.VIDEO。
-
获取 FdNumber
FdNumber = await FileAsset.open(mode: string): Promise<number>
-
创建视频录制配置文件
let videoProfile = { // 音频编码比特率 audioBitrate: 48000, // 音频编码比特率 audioChannels: 2, // 音频编码比特率 audioCodec: 'audio/mp4a-latm', // 音频采样率 audioSampleRate: 48000, // 文件的容器格式 fileFormat: 'mp4', // 视频编码比特率 videoBitrate: 48000, // 视频编码格式 videoCodec: 'video/mp4v-es', // 录制视频帧的宽 videoFrameWidth: 1280, // 录制视频帧的高 videoFrameHeight: 720, // 录制视频帧的高 videoFrameRate: 30 } let videoConfig = { // 视频录制的音频源类型 // AUDIO_SOURCE_TYPE_DEFAULT 0 , AUDIO_SOURCE_TYPE_MIC 1 audioSourceType: 0, // 视频录制的音频源类型 // VIDEO_SOURCE_TYPE_SURFACE_YUV 0, VIDEO_SOURCE_TYPE_SURFACE_YUV 1 videoSourceType: 0, // 视频录制的profile profile: this.videoProfile, // 视频输出URL:fd://xx (fd number) // 文件需要由调用者创建,并赋予适当的权限 url: `fd://${FdNumber}`, // 录制视频的旋转角度 rotation: 0, // 录制视频的旋转角度 location: { latitude: 30, longitude: 130 } }
-
创建视频录制器实例
import Media from '@ohos.multimedia.media' videoRecorder = await Media.createVideoRecorder(): Promise<VideoRecorder>
-
视频录制的参数设置
videoRecorder.prepare(config: VideoRecorderConfig): Promise<void>
-
获取视频录制器实例的 surfaceId
SurfaceId = await videoRecorder.getInputSurface(): Promise<string>
拍照会话类
-
初始化拍照会话类
同相机预览功能实现一样的步骤,创建拍照会话实例、相机输入实例和预览输出实例,并进行配置。
-
创建视频输出实例,此处的 surfaceId 为视频录制器实例获取的 surfaceId
VideoOutput = await CameraManager.createVideoOutput(surfaceId: string): Promise<VideoOutput>
-
将视频输出实例配置进拍照会话实例
CaptureSession.addOutput(videoOutput: VideoOutput): Promise<void>
-
提交此拍照会话实例的设置
CaptureSession.commitConfig(): Promise<void>
-
开启拍照会话实例
CaptureSession.start(): Promise<void>
录像事件
-
开始录制
开启视频输出实例
VideoOutput.start(): Promise<void>
开始视频录制
VideoRecorder.start(): Promise<void>
-
暂停视频录制
停止视频输出实例
VideoOutput.stop(): Promise<void>
暂停视频录制
VideoRecorder.pause(): Promise<void>
-
恢复视频录制
开启视频输出实例
VideoOutput.start(): Promise<void>
恢复视频录制
VideoRecorder.resume(): Promise<void>
-
录制结束,停止视频录制
停止视频输出实例
VideoOutput.stop(): Promise<void>
停止视频录制
VideoRecorder.stop(): Promise<void>
录像功能代码示例
Stage 模型为例:
录像功能页面:
释放资源
当相机功能使用完毕或需要退出相机所在页面或应用时,需要对相机调用的资源进行释放。
-
释放相机输入实例
CameraInput.release(): Promise<void>
-
释放预览输出实例
PreviewOutput.release(): Promise<void>
-
释放图像接收器实例
ImageReceiver.release(): Promise<void>
-
释放照片输出实例
PhotoOutPut.release(): Promise<void>
-
释放视频录制器实例
VideoRecorder.release(): Promise<void>
-
释放视频输出实例
VideoOutput.release(): Promise<void>
-
关闭媒体资源文件实例
FileAsset.close(fd: number): Promise<void>
-
释放拍照会话实例
CaptureSession.release(): Promise<void>
相机的其他功能
设置闪光灯模式
判断设备是否支持闪光灯。
CameraInput.hasFlash(): Promise<boolean>
判断设备是否支持指定闪光灯模式。
CameraInput.isFlashModeSupported(flashMode: FlashMode): Promise<boolean>
设置闪光灯模式,进行设置之前,需要先检查:
-
设备是否支持闪光灯。
-
设备是否支持指定的闪光灯模式。
CameraInput.setFlashMode(flashMode: FlashMode): Promise<void>
FlashMode 说明
enum FlashMode { // 闪光灯关闭 FLASH_MODE_CLOSE = 0, // 闪光灯关闭。 FLASH_MODE_OPEN, // 自动闪光灯 FLASH_MODE_AUTO, // 闪光灯常亮 FLASH_MODE_ALWAYS_OPEN }
设置焦距模式
判断设备是否支持指定的焦距模式。
CameraInput.isFocusModeSupported(afMode: FocusMode): Promise<boolean>
设置焦距模式,进行设置之前,需要先检查设备是否支持指定的焦距模式。
CameraInput.setFocusMode(afMode: FocusMode): Promise<void>
FocusMode 说明
enum FocusMode { // 手动变焦模式 FOCUS_MODE_MANUAL = 0, // 连续自动变焦模式 FOCUS_MODE_CONTINUOUS_AUTO, // 自动变焦模式 FOCUS_MODE_AUTO, // 定焦模式 FOCUS_MODE_LOCKED }
设置可变焦距比
获取可变焦距比范围
CameraInput.getZoomRatioRange(): Promise<Array<number>>
获取当前的可变焦距比
CameraInput.getZoomRatio(): Promise<number>
设置可变焦距比
CameraInput.setZoomRatio(zoomRatio: number): Promise<void>更多推荐




所有评论(0)