当前位置: 首页 > news >正文

有没有做任务的网站网站建设 上市公司

有没有做任务的网站,网站建设 上市公司,个人简历在线编辑文档,wordpress分享到微信二维码1 简介 开发者通过调用Camera Kit(相机服务)提供的接口可以开发相机应用#xff0c;应用通过访问和操作相机硬件#xff0c;实现基础操作#xff0c;如预览、拍照和录像#xff1b;还可以通过接口组合完成更多操作#xff0c;如控制闪光灯和曝光时间、对焦或调焦等。 2 …1 简介 开发者通过调用Camera Kit(相机服务)提供的接口可以开发相机应用应用通过访问和操作相机硬件实现基础操作如预览、拍照和录像还可以通过接口组合完成更多操作如控制闪光灯和曝光时间、对焦或调焦等。 2 开发模型 相机调用摄像头采集、加工图像视频数据精确控制对应的硬件灵活输出图像、视频内容满足多镜头硬件适配如广角、长焦、TOF、多业务场景适配如不同分辨率、不同格式、不同效果的要求。 相机的工作流程如图所示可概括为相机输入设备管理、会话管理和相机输出管理三部分。 相机设备调用摄像头采集数据作为相机输入流。会话管理可配置输入流即选择哪些镜头进行拍摄。另外还可以配置闪光灯、曝光时间、对焦和调焦等参数实现不同效果的拍摄从而适配不同的业务场景。应用可以通过切换会话满足不同场景的拍摄需求。配置相机的输出流即将内容以预览流、拍照流或视频流输出。 相机应用通过控制相机实现图像显示预览、照片保存拍照、视频录制录像等基础操作。在实现基本操作过程中相机服务会控制相机设备采集和输出数据采集的图像数据在相机底层的设备硬件接口HDIHardware Device Interfaces直接通过BufferQueue传递到具体的功能模块进行处理。BufferQueue在应用开发中无需关注用于将底层处理的数据及时送到上层进行图像显示。 以视频录制为例进行说明相机应用在录制视频过程中媒体录制服务先创建一个视频Surface用于传递数据并提供给相机服务相机服务可控制相机设备采集视频数据生成视频流。采集的数据通过底层相机HDI处理后通过Surface将视频流传递给媒体录制服务媒体录制服务对视频数据进行处理后保存为视频文件完成视频录制。 3 开发准备 相机应用开发的主要流程包含开发准备、设备输入、会话管理、预览、拍照和录像等。 在开发相机应用时需要先申请相机相关权限确保应用拥有访问相机硬件及其他功能的权限需要的权限如下表。在申请权限前请保证符合权限使用的基本原则。 以上权限的授权方式均为user_grant用户授权即开发者在module.json5文件中配置对应的权限后需要使用接口abilityAccessCtrl.requestPermissionsFromUser去校验当前用户是否已授权。如果是应用可以直接访问/操作目标对象否则需要弹框向用户申请授权。 说明 即使用户曾被授予过权限应用在调用此权限保护的接口前也应该先检查是否有权限。不能把之前授予的状态持久化因为用户在动态授予后可能通过“设置”取消应用权限。 当前相机提供了ArkTS和C两种开发语言的开发指导如下表所示。 4 相机开发ArkTS 4.1 设备输入 在开发一个相机应用前需要先创建一个独立的相机设备应用通过调用和控制相机设备完成预览、拍照和录像等基础操作。 4.1.1 开发步骤 详细的API说明请参考Camera API参考。 // 导入camera接口 import camera from ohos.multimedia.camera; import { BusinessError } from ohos.base; import common from ohos.app.ability.common;// 通过getCameraManager方法获取cameraManager对象。 // Context获取方式请参考获取UIAbility的上下文信息。 function getCameraManager(context: common.BaseContext): camera.CameraManager {let cameraManager: camera.CameraManager camera.getCameraManager(context);return cameraManager; }//说明如果获取对象失败说明相机可能被占用或无法使用。 // 如果被占用须等到相机被释放后才能重新获取。// 通过cameraManager类中的getSupportedCameras方法获取当前设备支持的相机列表列表中存储了设备支持的所有相机ID。若列表不为空则说明列表中的每个ID都支持独立创建相机对象否则说明当前设备无可用相机不可继续后续操作。 function getCameraDevices(cameraManager: camera.CameraManager): Arraycamera.CameraDevice {let cameraArray: Arraycamera.CameraDevice cameraManager.getSupportedCameras();if (cameraArray ! undefined cameraArray.length 0) {for (let index 0; index cameraArray.length; index) {console.info(cameraId : cameraArray[index].cameraId); // 获取相机IDconsole.info(cameraPosition : cameraArray[index].cameraPosition); // 获取相机位置console.info(cameraType : cameraArray[index].cameraType); // 获取相机类型console.info(connectionType : cameraArray[index].connectionType); // 获取相机连接类型}return cameraArray;} else {console.error(cameraManager.getSupportedCameras error);return [];} }// 通过getSupportedOutputCapability方法获取当前设备支持的所有输出流如预览流、拍照流等。输出流在CameraOutputCapability中的各个profile字段中。 async function getSupportedOutputCapability(cameraDevice: camera.CameraDevice, cameraManager: camera.CameraManager, sceneMode: camera.SceneMode): Promisecamera.CameraOutputCapability | undefined {// 创建相机输入流let cameraInput: camera.CameraInput | undefined undefined;try {cameraInput cameraManager.createCameraInput(cameraDevice);} catch (error) {let err error as BusinessError;console.error(Failed to createCameraInput errorCode err.code);}if (cameraInput undefined) {return undefined;}// 监听cameraInput错误信息cameraInput.on(error, cameraDevice, (error: BusinessError) {console.error(Camera input error code: ${error.code});});// 打开相机await cameraInput.open();// 获取相机设备支持的输出流能力let cameraOutputCapability: camera.CameraOutputCapability cameraManager.getSupportedOutputCapability(cameraDevice, sceneMode);if (!cameraOutputCapability) {console.error(cameraManager.getSupportedOutputCapability error);return undefined;}console.info(outputCapability: JSON.stringify(cameraOutputCapability));return cameraOutputCapability; }4.1.2 状态监听 在相机应用开发过程中可以随时监听相机状态包括新相机的出现、相机的移除、相机的可用状态。在回调函数中通过相机ID、相机状态这两个参数进行监听如当有新相机出现时可以将新相机加入到应用的备用相机中。 通过注册cameraStatus事件通过回调返回监听结果callback返回CameraStatusInfo参数参数的具体内容可参考相机管理器回调接口实例CameraStatusInfo。 function onCameraStatus(cameraManager: camera.CameraManager): void {cameraManager.on(cameraStatus, (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) {console.info(camera: ${cameraStatusInfo.camera.cameraId});console.info(status: ${cameraStatusInfo.status});}); }4.2 会话管理 相机使用预览、拍照、录像、元数据功能前均需要创建相机会话。 在会话中可以完成以下功能 配置相机的输入流和输出流。相机在拍摄前必须完成输入输出流的配置。 配置输入流即添加设备输入对用户而言相当于选择设备的某一摄像头拍摄配置输出流即选择数据将以什么形式输出。当应用需要实现拍照时输出流应配置为预览流和拍照流预览流的数据将显示在XComponent组件上拍照流的数据将通过ImageReceiver接口的能力保存到相册中。 添加闪光灯、调整焦距等配置。具体支持的配置及接口说明请参考Camera API参考。 会话切换控制。应用可以通过移除和添加输出流的方式切换相机模式。如当前会话的输出流为拍照流应用可以将拍照流移除然后添加视频流作为输出流即完成了拍照到录像的切换。 完成会话配置后应用提交和开启会话可以开始调用相机相关功能。 4.2.1 开发步骤 // 1. 导入相关接口 import camera from ohos.multimedia.camera; import { BusinessError } from ohos.base;// 2. 调用cameraManager类中的createSession方法创建一个会话。 function getSession(cameraManager: camera.CameraManager): camera.Session | undefined {let session: camera.Session | undefined undefined;try {session cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession;} catch (error) {let err error as BusinessError;console.error(Failed to create the session instance. error: ${JSON.stringify(err)});}return session; }// 3. 调用PhotoSession类中的beginConfig方法配置会话。 function beginConfig(photoSession: camera.PhotoSession): void {try {photoSession.beginConfig();} catch (error) {let err error as BusinessError;console.error(Failed to beginConfig. error: ${JSON.stringify(err)});} }// 4. 使能。向会话中添加相机的输入流和输出流调用addInput添加相机的输入流调用addOutput添加相机的输出流。以下示例代码以添加预览流previewOutput和拍照流photoOutput为例即当前模式支持拍照和预览。 调用PhotoSession类中的commitConfig和start方法提交相关配置并启动会话。 async function startSession(photoSession: camera.PhotoSession, cameraInput: camera.CameraInput, previewOutput: camera.PreviewOutput, photoOutput: camera.PhotoOutput): Promisevoid {try {photoSession.addInput(cameraInput);} catch (error) {let err error as BusinessError;console.error(Failed to addInput. error: ${JSON.stringify(err)});}try {photoSession.addOutput(previewOutput);} catch (error) {let err error as BusinessError;console.error(Failed to add previewOutput. error: ${JSON.stringify(err)});}try {photoSession.addOutput(photoOutput);} catch (error) {let err error as BusinessError;console.error(Failed to add photoOutput. error: ${JSON.stringify(err)});}try {await photoSession.commitConfig();} catch (error) {let err error as BusinessError;console.error(Failed to commitConfig. error: ${JSON.stringify(err)});}try {await photoSession.start();} catch (error) {let err error as BusinessError;console.error(Failed to start. error: ${JSON.stringify(err)});} }// 5. 会话控制。调用PhotoSession类中的stop方法可以停止当前会话。调用removeOutput和addOutput方法可以完成会话切换控制。以下示例代码以移除拍照流photoOutput添加视频流videoOutput为例完成了拍照到录像的切换。async function switchOutput(photoSession: camera.PhotoSession, videoOutput: camera.VideoOutput, photoOutput: camera.PhotoOutput): Promisevoid {try {await photoSession.stop();} catch (error) {let err error as BusinessError;console.error(Failed to stop. error: ${JSON.stringify(err)});}try {photoSession.beginConfig();} catch (error) {let err error as BusinessError;console.error(Failed to beginConfig. error: ${JSON.stringify(err)});}// 从会话中移除拍照输出流try {photoSession.removeOutput(photoOutput);} catch (error) {let err error as BusinessError;console.error(Failed to remove photoOutput. error: ${JSON.stringify(err)});}// 向会话中添加视频输出流try {photoSession.addOutput(videoOutput);} catch (error) {let err error as BusinessError;console.error(Failed to add videoOutput. error: ${JSON.stringify(err)});} } 4.3 预览 预览是启动相机后看见的画面通常在拍照和录像前执行。 4.3.1 开发步骤 详细的API说明请参考Camera API参考。 // 导入camera接口接口中提供了相机相关的属性和方法导入方法如下。import camera from ohos.multimedia.camera; import { BusinessError } from ohos.base;// 创建Surface。 // XComponent组件为预览流提供的Surface而XComponent的能力由UI提供相关介绍可参考XComponent组件参考。 // 说明 预览流与录像输出流的分辨率的宽高比要保持一致如示例代码中宽高比为1920:1080 16:9则需要预览流中的分辨率的宽高比也为16:9如分辨率选择640:360或960:540或1920:1080以此类推。// xxx.ets // 创建XComponentController Component struct XComponentPage {// 创建XComponentControllermXComponentController: XComponentController new XComponentController;surfaceId: string ;build() {Flex() {// 创建XComponentXComponent({id: ,type: surface,libraryname: ,controller: this.mXComponentController}).onLoad(() {// 设置Surface宽高1920*1080预览尺寸设置参考前面 previewProfilesArray 获取的当前设备所支持的预览分辨率大小去设置// 预览流与录像输出流的分辨率的宽高比要保持一致this.mXComponentController.setXComponentSurfaceSize({surfaceWidth:1920,surfaceHeight:1080});// 获取Surface IDthis.surfaceId this.mXComponentController.getXComponentSurfaceId();}).width(1920px).height(1080px)}} }//通过CameraOutputCapability类中的previewProfiles属性获取当前设备支持的预览能力返回previewProfilesArray数组 。通过createPreviewOutput方法创建预览输出流其中createPreviewOutput方法中的两个参数分别是previewProfilesArray数组中的第一项和步骤二中获取的surfaceId。function getPreviewOutput(cameraManager: camera.CameraManager, cameraOutputCapability: camera.CameraOutputCapability, surfaceId: string): camera.PreviewOutput | undefined {let previewProfilesArray: Arraycamera.Profile cameraOutputCapability.previewProfiles;let previewOutput: camera.PreviewOutput | undefined undefined;try {previewOutput cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId);} catch (error) {let err error as BusinessError;console.error(Failed to create the PreviewOutput instance. error code: err.code);}return previewOutput; }// 使能。通过Session.start方法输出预览流接口调用失败会返回相应错误码错误码类型参见CameraErrorCode。 async function startPreviewOutput(cameraManager: camera.CameraManager, previewOutput: camera.PreviewOutput): Promisevoid {let cameraArray: Arraycamera.CameraDevice [];cameraArray cameraManager.getSupportedCameras();if (cameraArray.length 0) {console.error(no camera.);return;}// 获取支持的模式类型let sceneModes: Arraycamera.SceneMode cameraManager.getSupportedSceneModes(cameraArray[0]);let isSupportPhotoMode: boolean sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) 0;if (!isSupportPhotoMode) {console.error(photo mode not support);return;}let cameraInput: camera.CameraInput | undefined undefined;cameraInput cameraManager.createCameraInput(cameraArray[0]);if (cameraInput undefined) {console.error(cameraInput is undefined);return;}// 打开相机await cameraInput.open();let session: camera.PhotoSession cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession;session.beginConfig();session.addInput(cameraInput);session.addOutput(previewOutput);await session.commitConfig();await session.start(); }4.3.2 状态监听 在相机应用开发过程中可以随时监听预览输出流状态包括预览流启动、预览流结束、预览流输出错误。 // 通过注册固定的frameStart回调函数获取监听预览启动结果previewOutput创建成功时即可监听预览第一次曝光时触发有该事件返回结果则认为预览流已启动。 function onPreviewOutputFrameStart(previewOutput: camera.PreviewOutput): void {previewOutput.on(frameStart, () {console.info(Preview frame started);}); }// 通过注册固定的frameEnd回调函数获取监听预览结束结果previewOutput创建成功时即可监听预览完成最后一帧时触发有该事件返回结果则认为预览流已结束。 function onPreviewOutputFrameEnd(previewOutput: camera.PreviewOutput): void {previewOutput.on(frameEnd, () {console.info(Preview frame ended);}); }// 通过注册固定的error回调函数获取监听预览输出错误结果callback返回预览输出接口使用错误时对应的错误码错误码类型参见CameraErrorCode。 function onPreviewOutputError(previewOutput: camera.PreviewOutput): void {previewOutput.on(error, (previewOutputError: BusinessError) {console.error(Preview output error code: ${previewOutputError.code});}); }4.4 拍照 拍照是相机的最重要功能之一拍照模块基于相机复杂的逻辑为了保证用户拍出的照片质量在中间步骤可以设置分辨率、闪光灯、焦距、照片质量及旋转角度等信息。 4.4.1 开发步骤 详细的API说明请参考Camera API参考。 // 导入image接口。创建拍照输出流的SurfaceId以及拍照输出的数据都需要用到系统提供的image接口能力导入image接口的方法如下。import image from ohos.multimedia.image; import camera from ohos.multimedia.camera; import fs from ohos.file.fs; import PhotoAccessHelper from ohos.file.photoAccessHelper; import { BusinessError } from ohos.base;// 创建拍照输出流。 // 通过CameraOutputCapability类中的photoProfiles属性可获取当前设备支持的拍照输出流通过createPhotoOutput方法传入支持的某一个输出流及步骤一获取的SurfaceId创建拍照输出流。function getPhotoOutput(cameraManager: camera.CameraManager, cameraOutputCapability: camera.CameraOutputCapability): camera.PhotoOutput | undefined {let photoProfilesArray: Arraycamera.Profile cameraOutputCapability.photoProfiles;if (!photoProfilesArray) {console.error(createOutput photoProfilesArray null || undefined);}let photoOutput: camera.PhotoOutput | undefined undefined;try {photoOutput cameraManager.createPhotoOutput(photoProfilesArray[0]);} catch (error) {let err error as BusinessError;console.error(Failed to createPhotoOutput. error: ${JSON.stringify(err)});}return photoOutput; }// 设置拍照photoAvailable的回调并将拍照的buffer保存为图片。 // Context获取方式请参考获取UIAbility的上下文信息。let context getContext(this);async function savePicture(buffer: ArrayBuffer, img: image.Image) {let photoAccessHelper: PhotoAccessHelper.PhotoAccessHelper PhotoAccessHelper.getPhotoAccessHelper(context);let options: PhotoAccessHelper.CreateOptions {title: Date.now().toString()};let photoUri: string await photoAccessHelper.createAsset(PhotoAccessHelper.PhotoType.IMAGE, jpg, options);//createAsset的调用需要ohos.permission.READ_IMAGEVIDEO和ohos.permission.WRITE_IMAGEVIDEO的权限let file: fs.File fs.openSync(photoUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);await fs.write(file.fd, buffer);fs.closeSync(file);img.release(); }function setPhotoOutputCb(photoOutput: camera.PhotoOutput) { //设置回调之后调用photoOutput的capture方法就会将拍照的buffer回传到回调中photoOutput.on(photoAvailable, (errCode: BusinessError, photo: camera.Photo): void {console.info(getPhoto start);console.info(err: ${JSON.stringify(errCode)});if (errCode || photo undefined) {console.error(getPhoto failed);return;}let imageObj: image.Image photo.main;imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void {console.info(getComponent start);if (errCode || component undefined) {console.error(getComponent failed);return;}let buffer: ArrayBuffer;if (component.byteBuffer) {buffer component.byteBuffer;} else {console.error(byteBuffer is null);return;}savePicture(buffer, imageObj);});}); }// 参数配置。 // 配置相机的参数可以调整拍照的一些功能包括闪光灯、变焦、焦距等。 function configuringSession(photoSession: camera.PhotoSession): void {// 判断设备是否支持闪光灯let flashStatus: boolean false;try {flashStatus photoSession.hasFlash();} catch (error) {let err error as BusinessError;console.error(Failed to hasFlash. error: ${JSON.stringify(err)});}console.info(Returned with the flash light support status: ${flashStatus});if (flashStatus) {// 判断是否支持自动闪光灯模式let flashModeStatus: boolean false;try {let status: boolean photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO);flashModeStatus status;} catch (error) {let err error as BusinessError;console.error(Failed to check whether the flash mode is supported. error: ${JSON.stringify(err)});}if (flashModeStatus) {// 设置自动闪光灯模式try {photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO);} catch (error) {let err error as BusinessError;console.error(Failed to set the flash mode. error: ${JSON.stringify(err)});}}}// 判断是否支持连续自动变焦模式let focusModeStatus: boolean false;try {let status: boolean photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);focusModeStatus status;} catch (error) {let err error as BusinessError;console.error(Failed to check whether the focus mode is supported. error: ${JSON.stringify(err)});}if (focusModeStatus) {// 设置连续自动变焦模式try {photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);} catch (error) {let err error as BusinessError;console.error(Failed to set the focus mode. error: ${JSON.stringify(err)});}}// 获取相机支持的可变焦距比范围let zoomRatioRange: Arraynumber [];try {zoomRatioRange photoSession.getZoomRatioRange();} catch (error) {let err error as BusinessError;console.error(Failed to get the zoom ratio range. error: ${JSON.stringify(err)});}if (zoomRatioRange.length 0 ) {return;}// 设置可变焦距比try {photoSession.setZoomRatio(zoomRatioRange[0]);} catch (error) {let err error as BusinessError;console.error(Failed to set the zoom ratio value. error: ${JSON.stringify(err)});} }// 触发拍照。 // 通过photoOutput类的capture方法执行拍照任务。该方法有两个参数第一个参数为拍照设置参数的settingsetting中可以设置照片的质量和旋转角度第二参数为回调函数。function capture(captureLocation: camera.Location, photoOutput: camera.PhotoOutput): void {let settings: camera.PhotoCaptureSetting {quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高rotation: camera.ImageRotation.ROTATION_0, // 设置图片旋转角度0location: captureLocation, // 设置图片地理位置mirror: false // 设置镜像使能开关(默认关)};photoOutput.capture(settings, (err: BusinessError) {if (err) {console.error(Failed to capture the photo. error: ${JSON.stringify(err)});return;}console.info(Callback invoked to indicate the photo capture request success.);}); } 4.4.2 状态监听 在相机应用开发过程中可以随时监听拍照输出流状态包括拍照流开始、拍照帧的开始与结束、拍照输出流的错误。 // 通过注册固定的captureStart回调函数获取监听拍照开始结果photoOutput创建成功时即可监听拍照第一次曝光时触发该事件返回此次拍照的captureId。 function onPhotoOutputCaptureStart(photoOutput: camera.PhotoOutput): void {photoOutput.on(captureStartWithInfo, (err: BusinessError, captureStartInfo: camera.CaptureStartInfo) {console.info(photo capture started, captureId : ${captureStartInfo.captureId});}); }// 通过注册固定的captureEnd回调函数获取监听拍照结束结果photoOutput创建成功时即可监听该事件返回结果为拍照完全结束后的相关信息CaptureEndInfo。 function onPhotoOutputCaptureEnd(photoOutput: camera.PhotoOutput): void {photoOutput.on(captureEnd, (err: BusinessError, captureEndInfo: camera.CaptureEndInfo) {console.info(photo capture end, captureId : ${captureEndInfo.captureId});console.info(frameCount : ${captureEndInfo.frameCount});}); }// 通过注册固定的error回调函数获取监听拍照输出流的错误结果。callback返回拍照输出接口使用错误时的对应错误码错误码类型参见CameraErrorCode。 function onPhotoOutputError(photoOutput: camera.PhotoOutput): void {photoOutput.on(error, (error: BusinessError) {console.error(Photo output error code: ${error.code});}); }4.5 录像 录像也是相机应用的最重要功能之一录像是循环帧的捕获。对于录像的流畅度开发者可以参考拍照中的步骤4设置分辨率、闪光灯、焦距、照片质量及旋转角度等信息。 4.5.1 开发步骤 详细的API说明请参考Camera API参考。 // 导入media模块。创建拍照输出流的SurfaceId以及拍照输出的数据都需要用到系统提供的media接口能力导入media接口的方法如下。import { BusinessError } from ohos.base; import media from ohos.multimedia.media;// 创建Surface。 // 系统提供的media接口可以创建一个录像AVRecorder实例通过该实例的getInputSurface方法获取SurfaceId与录像输出流做关联处理录像输出流输出的数据。 async function getVideoSurfaceId(aVRecorderConfig: media.AVRecorderConfig): Promisestring | undefined { // aVRecorderConfig可参考下一章节let avRecorder: media.AVRecorder | undefined undefined;try {avRecorder await media.createAVRecorder();} catch (error) {let err error as BusinessError;console.error(createAVRecorder call failed. error code: ${err.code});}if (avRecorder undefined) {return undefined;}avRecorder.prepare(aVRecorderConfig, (err: BusinessError) {if (err null) {console.info(prepare success);} else {console.error(prepare failed and error is err.message);}});let videoSurfaceId await avRecorder.getInputSurface();return videoSurfaceId; }// 创建录像输出流。 // 通过CameraOutputCapability类中的videoProfiles属性可获取当前设备支持的录像输出流。然后定义创建录像的参数通过createVideoOutput方法创建录像输出流。 // 说明 预览流与录像输出流的分辨率的宽高比要保持一致如示例代码中宽高比为640:480 4:3则需要预览流中的分辨率的宽高比也为4:3如分辨率选择640:480或960:720或1440:1080以此类推 async function getVideoOutput(cameraManager: camera.CameraManager, videoSurfaceId: string, cameraOutputCapability: camera.CameraOutputCapability): Promisecamera.VideoOutput | undefined {let videoProfilesArray: Arraycamera.VideoProfile cameraOutputCapability.videoProfiles;if (!videoProfilesArray) {console.error(createOutput videoProfilesArray null || undefined);return undefined;}// AVRecorderProfilelet aVRecorderProfile: media.AVRecorderProfile {fileFormat : media.ContainerFormatType.CFT_MPEG_4, // 视频文件封装格式只支持MP4videoBitrate : 100000, // 视频比特率videoCodec : media.CodecMimeType.VIDEO_AVC, // 视频文件编码格式支持avc格式videoFrameWidth : 640, // 视频分辨率的宽videoFrameHeight : 480, // 视频分辨率的高videoFrameRate : 30 // 视频帧率};// 创建视频录制的参数预览流与录像输出流的分辨率的宽(videoFrameWidth)高(videoFrameHeight)比要保持一致let aVRecorderConfig: media.AVRecorderConfig {videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV,profile: aVRecorderProfile,url: fd://35,rotation: 90 // 90°为默认竖屏显示角度如果由于设备原因或应用期望以其他方式显示等原因请根据实际情况调整该参数};// 创建avRecorderlet avRecorder: media.AVRecorder | undefined undefined;try {avRecorder await media.createAVRecorder();} catch (error) {let err error as BusinessError;console.error(createAVRecorder call failed. error code: ${err.code});}if (avRecorder undefined) {return undefined;}// 设置视频录制的参数avRecorder.prepare(aVRecorderConfig);// 创建VideoOutput对象let videoOutput: camera.VideoOutput | undefined undefined;// createVideoOutput传入的videoProfile对象的宽高需要和aVRecorderProfile保持一致。let videoProfile: undefined | camera.VideoProfile videoProfilesArray.find((profile: camera.VideoProfile) {return profile.size.width aVRecorderProfile.videoFrameWidth profile.size.height aVRecorderProfile.videoFrameHeight;});if (!videoProfile) {console.error(videoProfile is not found);return;}try {videoOutput cameraManager.createVideoOutput(videoProfile, videoSurfaceId);} catch (error) {let err error as BusinessError;console.error(Failed to create the videoOutput instance. errorCode err.code);}return videoOutput; }开始录像。先通过videoOutput的start方法启动录像输出流再通过avRecorder的start方法开始录像。async function startVideo(videoOutput: camera.VideoOutput, avRecorder: media.AVRecorder): Promisevoid {videoOutput.start(async (err: BusinessError) {if (err) {console.error(Failed to start the video output ${err.message});return;}console.info(Callback invoked to indicate the video output start success.);});try {await avRecorder.start();} catch (error) {let err error as BusinessError;console.error(avRecorder start error: ${JSON.stringify(err)});} } ts async function startVideo(videoOutput: camera.VideoOutput, avRecorder: media.AVRecorder): Promisevoid {videoOutput.start(async (err: BusinessError) {if (err) {console.error(Failed to start the video output ${err.message});return;}console.info(Callback invoked to indicate the video output start success.);});try {await avRecorder.start();} catch (error) {let err error as BusinessError;console.error(avRecorder start error: ${JSON.stringify(err)});} }// 停止录像。 // 先通过avRecorder的stop方法停止录像再通过videoOutput的stop方法停止录像输出流。 async function stopVideo(videoOutput: camera.VideoOutput, avRecorder: media.AVRecorder): Promisevoid {try {await avRecorder.stop();} catch (error) {let err error as BusinessError;console.error(avRecorder stop error: ${JSON.stringify(err)});}videoOutput.stop((err: BusinessError) {if (err) {console.error(Failed to stop the video output ${err.message});return;}console.info(Callback invoked to indicate the video output stop success.);}); }4.5.2 状态监听 在相机应用开发过程中可以随时监听录像输出流状态包括录像开始、录像结束、录像流输出的错误。 // 通过注册固定的frameStart回调函数获取监听录像开始结果videoOutput创建成功时即可监听录像第一次曝光时触发有该事件返回结果则认为录像开始。 function onVideoOutputFrameStart(videoOutput: camera.VideoOutput): void {videoOutput.on(frameStart, () {console.info(Video frame started);}); }// 通过注册固定的frameEnd回调函数获取监听录像结束结果videoOutput创建成功时即可监听录像完成最后一帧时触发有该事件返回结果则认为录像流已结束。 function onVideoOutputFrameEnd(videoOutput: camera.VideoOutput): void {videoOutput.on(frameEnd, () {console.info(Video frame ended);}); }// 通过注册固定的error回调函数获取监听录像输出错误结果callback返回预览输出接口使用错误时对应的错误码错误码类型参见CameraErrorCode。 function onVideoOutputError(videoOutput: camera.VideoOutput): void {videoOutput.on(error, (error: BusinessError) {console.error(Video output error code: ${error.code});}); }4.6 元数据 元数据Metadata是对相机返回的图像信息数据的描述和上下文针对图像信息提供的更详细的数据如照片或视频中识别人像的取景框坐标等信息。 Metadata主要是通过一个TAGKey去找对应的Data用于传递参数和配置信息减少内存拷贝操作。 4.6.1 开发步骤 详细的API说明请参考Camera API参考。 // 导入相关接口导入方法如下。 import camera from ohos.multimedia.camera; import { BusinessError } from ohos.base;// 调用CameraOutputCapability类中的supportedMetadataObjectTypes属性获取当前设备支持的元数据类型并通过createMetadataOutput方法创建元数据输出流。 function getMetadataOutput(cameraManager: camera.CameraManager, cameraOutputCapability: camera.CameraOutputCapability): camera.MetadataOutput | undefined {let metadataObjectTypes: Arraycamera.MetadataObjectType cameraOutputCapability.supportedMetadataObjectTypes;let metadataOutput: camera.MetadataOutput | undefined undefined;try {metadataOutput cameraManager.createMetadataOutput(metadataObjectTypes);} catch (error) {let err error as BusinessError;console.error(Failed to createMetadataOutput, error code: ${err.code});}return metadataOutput; }// 调用Session.start方法开启metadata数据输出再通过监听事件metadataObjectsAvailable回调拿到数据接口调用失败时会返回相应错误码错误码类型参见Camera错误码。 // previewOutput获取方式请参考相机预览开发步骤。 async function startMetadataOutput(previewOutput: camera.PreviewOutput, metadataOutput: camera.MetadataOutput, cameraManager: camera.CameraManager): Promisevoid {let cameraArray: Arraycamera.CameraDevice [];cameraArray cameraManager.getSupportedCameras();if (cameraArray.length 0) {console.error(no camera.);return;}// 获取支持的模式类型let sceneModes: Arraycamera.SceneMode cameraManager.getSupportedSceneModes(cameraArray[0]);let isSupportPhotoMode: boolean sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) 0;if (!isSupportPhotoMode) {console.error(photo mode not support);return;}let cameraInput: camera.CameraInput | undefined undefined;cameraInput cameraManager.createCameraInput(cameraArray[0]);if (cameraInput undefined) {console.error(cameraInput is undefined);return;}// 打开相机await cameraInput.open();let session: camera.PhotoSession cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession;session.beginConfig();session.addInput(cameraInput);session.addOutput(previewOutput);session.addOutput(metadataOutput);await session.commitConfig();await session.start(); }// 调用Session.stop方法停止输出metadata数据接口调用失败会返回相应错误码错误码类型参见Camera错误码。 function stopMetadataOutput(session: camera.Session): void {session.stop().then(() {console.info(Callback returned with session stopped.);}).catch((err: BusinessError) {console.error(Failed to session stop, error code: ${err.code});}); }4.6.2 状态监听 在相机应用开发过程中可以随时监听metadata数据以及输出流的状态。 /// 通过注册监听获取metadata对象监听事件固定为metadataObjectsAvailable。检测到有效metadata数据时callback返回相应的metadata数据信息metadataOutput创建成功时可监听。 function onMetadataObjectsAvailable(metadataOutput: camera.MetadataOutput): void {metadataOutput.on(metadataObjectsAvailable, (err: BusinessError, metadataObjectArr: Arraycamera.MetadataObject) {console.info(metadata output metadataObjectsAvailable);}); }// 说明当前的元数据类型仅支持人脸检测FACE_DETECTION功能。 // 元数据信息对象为识别到的人脸区域的矩形信息Rect // 包含矩形区域的左上角x坐标、y坐标和矩形的宽高数据。//通过注册回调函数获取监听metadata流的错误结果callback返回metadata输出接口使用错误时返回的错误码错误码类型参见CameraErrorCode。function onMetadataError(metadataOutput: camera.MetadataOutput): void {metadataOutput.on(error, (metadataOutputError: BusinessError) {console.error(Metadata output error code: ${metadataOutputError.code});}); }4.7 高性能拍照(仅对系统应用开放) 高性能拍照是相机的重要功能之一优化了拍照响应时延提升用户体验。高性能拍照又名分段式拍照应用下发拍照请求后第一阶段系统会很快返回给应用一张缩略图应用需将该图片及相关信息存入媒体库第二阶段子服务会根据系统压力及定制化场景进行调度将后处理好的原图回传给媒体库。 应用开发分段式拍照主要分为以下步骤 查询当前设备的当前模式是否支持分段式拍照。如果支持分段式能力可以调用相机框架提供的使能接口使能分段式能力。监听缩略图回调获取缩略图代理类将缩略图存入媒体库。 说明 分段式拍照能力是根据设备和模式决定的不同的设备支持不同的模式不同的模式下分段式能力也各有不同所以应用在切换设备或模式后需要重新使能分段式能力。 分段式使能需要在配流期间完成配流完成后的使能操作不生效。 4.7.1 开发步骤 详细的API说明请参考Camera API参考。 // 导入依赖需要导入相机框架、媒体库、图片相关领域依赖。import camera from ohos.multimedia.camera; import image from ohos.multimedia.image; import mediaLibrary from ohos.multimedia.mediaLibrary; import fs from ohos.file.fs; import photoAccessHelper from ohos.file.photoAccessHelper; import { BusinessError } from ohos.base;// 确定拍照输出流。 // 通过CameraOutputCapability类中的photoProfiles属性可获取当前设备支持的拍照输出流通过createPhotoOutput方法创建拍照输出流。function getPhotoOutput(cameraManager: camera.CameraManager, cameraOutputCapability: camera.CameraOutputCapability): camera.PhotoOutput | undefined {let photoProfilesArray: Arraycamera.Profile cameraOutputCapability.photoProfiles;if (!photoProfilesArray) {console.error(createOutput photoProfilesArray null || undefined);}let photoOutput: camera.PhotoOutput | undefined undefined;try {photoOutput cameraManager.createPhotoOutput(photoProfilesArray[0]);} catch (error) {let err error as BusinessError;console.error(Failed to createPhotoOutput. error: ${JSON.stringify(err)});}return photoOutput; }// 查询当前设备当前模式是否支持相应分段式能力。 function isDeferredImageDeliverySupported(photoOutput: camera.PhotoOutput): boolean {let isSupported: boolean false;if (photoOutput ! null) {isSupported photoOutput.isDeferredImageDeliverySupported(camera.DeferredDeliveryImageType.PHOTO);}console.info(isDeferredImageDeliverySupported isSupported: ${isSupported});return isSupported; }// 使能分段式拍照能力。 function EnableDeferredPhotoAbility(photoOutput: camera.PhotoOutput): void {photoOutput.deferImageDelivery(camera.DeferredDeliveryImageType.PHOTO); }// 查询是否已经成功使能分段式拍照。 function isDeferredImageDeliveryEnabled(photoOutput: camera.PhotoOutput): boolean {let isEnabled: boolean false;if (photoOutput ! null) {isEnabled photoOutput.isDeferredImageDeliveryEnabled(camera.DeferredDeliveryImageType.PHOTO);}console.info(isDeferredImageDeliveryEnabled isEnabled: ${isEnabled});return isEnabled; }触发拍照与普通拍照方式相同请参考拍照。 4.7.2 状态监听 注册缩略图监听回调。 function onPhotoOutputDeferredPhotoProxyAvailable(photoOutput: camera.PhotoOutput): void {photoOutput.on(deferredPhotoProxyAvailable, (err: BusinessError, proxyObj: camera.DeferredPhotoProxy): void {if (err) {console.info(deferredPhotoProxyAvailable error: ${JSON.stringify(err)}.);return;}console.info(photoOutPutCallBack deferredPhotoProxyAvailable);// 获取缩略图 pixelMapproxyObj.getThumbnail().then((thumbnail: image.PixelMap) {AppStorage.setOrCreate(proxyThumbnail, thumbnail);});// 调用媒体库接口落盘缩略图详细实现见2。saveDeferredPhoto(proxyObj);}); }// 调用媒体库接口落盘缩略图。 // Context获取方式请参考获取UIAbility的上下文信息。 let context getContext(this); async function saveDeferredPhoto(proxyObj: camera.DeferredPhotoProxy) { try {// 创建 photoAssetlet photoAccessHelper PhotoAccessHelper.getPhotoAccessHelper(context);let testFileName testFile Date.now() .jpg;let photoAsset await photoAccessHelper.createAsset(testFileName);// 将缩略图代理类传递给媒体库let mediaRequest: PhotoAccessHelper.MediaAssetChangeRequest new PhotoAccessHelper.MediaAssetChangeRequest(photoAsset);mediaRequest.addResource(PhotoAccessHelper.ResourceType.PHOTO_PROXY, proxyObj);let res await photoAccessHelper.applyChanges(mediaRequest);console.info(saveDeferredPhoto success.);} catch (err) {console.error(Failed to saveDeferredPhoto. error: ${JSON.stringify(err)});} }5 相机实践ArkTS 5.1 拍照实现方案 当前示例提供完整的拍照流程介绍方便开发者了解完整的接口调用顺序。 在参考以下示例前建议开发者查看相机开发指导(ArkTS)的具体章节了解设备输入、会话管理、拍照等单个流程。 5.1.1 开发流程 在获取到相机支持的输出流能力后开始创建拍照流开发流程如下。 5.1.2 完整示例 Context获取方式请参考获取UIAbility的上下文信息。 import camera from ohos.multimedia.camera; import image from ohos.multimedia.image; import { BusinessError } from ohos.base; import common from ohos.app.ability.common; import fs from ohos.file.fs; import PhotoAccessHelper from ohos.file.photoAccessHelper;let context getContext(this);async function savePicture(buffer: ArrayBuffer, img: image.Image): Promisevoid {let photoAccessHelper: PhotoAccessHelper.PhotoAccessHelper PhotoAccessHelper.getPhotoAccessHelper(context);let options: PhotoAccessHelper.CreateOptions {title: Date.now().toString()};let photoUri: string await photoAccessHelper.createAsset(PhotoAccessHelper.PhotoType.IMAGE, jpg, options);//createAsset的调用需要ohos.permission.READ_IMAGEVIDEO和ohos.permission.WRITE_IMAGEVIDEO的权限let file: fs.File fs.openSync(photoUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);await fs.write(file.fd, buffer);fs.closeSync(file);img.release(); }function setPhotoOutputCb(photoOutput: camera.PhotoOutput): void {//设置回调之后调用photoOutput的capture方法就会将拍照的buffer回传到回调中photoOutput.on(photoAvailable, (errCode: BusinessError, photo: camera.Photo): void {console.info(getPhoto start);console.info(err: ${JSON.stringify(errCode)});if (errCode || photo undefined) {console.error(getPhoto failed);return;}let imageObj photo.main;imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void {console.info(getComponent start);if (errCode || component undefined) {console.error(getComponent failed);return;}let buffer: ArrayBuffer;if (component.byteBuffer) {buffer component.byteBuffer;} else {console.error(byteBuffer is null);return;}savePicture(buffer, imageObj);});}); }async function cameraShootingCase(baseContext: common.BaseContext, surfaceId: string): Promisevoid {// 创建CameraManager对象let cameraManager: camera.CameraManager camera.getCameraManager(baseContext);if (!cameraManager) {console.error(camera.getCameraManager error);return;}// 监听相机状态变化cameraManager.on(cameraStatus, (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) {console.info(camera : ${cameraStatusInfo.camera.cameraId});console.info(status: ${cameraStatusInfo.status});});// 获取相机列表let cameraArray: Arraycamera.CameraDevice cameraManager.getSupportedCameras();if (cameraArray.length 0) {console.error(cameraManager.getSupportedCameras error);return;}for (let index 0; index cameraArray.length; index) {console.info(cameraId : cameraArray[index].cameraId); // 获取相机IDconsole.info(cameraPosition : cameraArray[index].cameraPosition); // 获取相机位置console.info(cameraType : cameraArray[index].cameraType); // 获取相机类型console.info(connectionType : cameraArray[index].connectionType); // 获取相机连接类型}// 创建相机输入流let cameraInput: camera.CameraInput | undefined undefined;try {cameraInput cameraManager.createCameraInput(cameraArray[0]);} catch (error) {let err error as BusinessError;console.error(Failed to createCameraInput errorCode err.code);}if (cameraInput undefined) {return;}// 监听cameraInput错误信息let cameraDevice: camera.CameraDevice cameraArray[0];cameraInput.on(error, cameraDevice, (error: BusinessError) {console.error(Camera input error code: ${error.code});})// 打开相机await cameraInput.open();// 获取支持的模式类型let sceneModes: Arraycamera.SceneMode cameraManager.getSupportedSceneModes(cameraArray[0]);let isSupportPhotoMode: boolean sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) 0;if (!isSupportPhotoMode) {console.error(photo mode not support);return;}// 获取相机设备支持的输出流能力let cameraOutputCap: camera.CameraOutputCapability cameraManager.getSupportedOutputCapability(cameraArray[0], camera.SceneMode.NORMAL_PHOTO);if (!cameraOutputCap) {console.error(cameraManager.getSupportedOutputCapability error);return;}console.info(outputCapability: JSON.stringify(cameraOutputCap));let previewProfilesArray: Arraycamera.Profile cameraOutputCap.previewProfiles;if (!previewProfilesArray) {console.error(createOutput previewProfilesArray null || undefined);}let photoProfilesArray: Arraycamera.Profile cameraOutputCap.photoProfiles;if (!photoProfilesArray) {console.error(createOutput photoProfilesArray null || undefined);}// 创建预览输出流,其中参数 surfaceId 参考上文 XComponent 组件预览流为XComponent组件提供的surfacelet previewOutput: camera.PreviewOutput | undefined undefined;try {previewOutput cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId);} catch (error) {let err error as BusinessError;console.error(Failed to create the PreviewOutput instance. error code: ${err.code});}if (previewOutput undefined) {return;}// 监听预览输出错误信息previewOutput.on(error, (error: BusinessError) {console.error(Preview output error code: ${error.code});});// 创建拍照输出流let photoOutput: camera.PhotoOutput | undefined undefined;try {photoOutput cameraManager.createPhotoOutput(photoProfilesArray[0]);} catch (error) {let err error as BusinessError;console.error(Failed to createPhotoOutput errorCode err.code);}if (photoOutput undefined) {return;}//调用上面的回调函数来保存图片setPhotoOutputCb(photoOutput);//创建会话let photoSession: camera.PhotoSession | undefined undefined;try {photoSession cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession;} catch (error) {let err error as BusinessError;console.error(Failed to create the session instance. errorCode err.code);}if (photoSession undefined) {return;}// 监听session错误信息photoSession.on(error, (error: BusinessError) {console.error(Capture session error code: ${error.code});});// 开始配置会话try {photoSession.beginConfig();} catch (error) {let err error as BusinessError;console.error(Failed to beginConfig. errorCode err.code);}// 向会话中添加相机输入流try {photoSession.addInput(cameraInput);} catch (error) {let err error as BusinessError;console.error(Failed to addInput. errorCode err.code);}// 向会话中添加预览输出流try {photoSession.addOutput(previewOutput);} catch (error) {let err error as BusinessError;console.error(Failed to addOutput(previewOutput). errorCode err.code);}// 向会话中添加拍照输出流try {photoSession.addOutput(photoOutput);} catch (error) {let err error as BusinessError;console.error(Failed to addOutput(photoOutput). errorCode err.code);}// 提交会话配置await photoSession.commitConfig();// 启动会话await photoSession.start().then(() {console.info(Promise returned to indicate the session start success.);});// 判断设备是否支持闪光灯let flashStatus: boolean false;try {flashStatus photoSession.hasFlash();} catch (error) {let err error as BusinessError;console.error(Failed to hasFlash. errorCode err.code);}console.info(Returned with the flash light support status: flashStatus);if (flashStatus) {// 判断是否支持自动闪光灯模式let flashModeStatus: boolean false;try {let status: boolean photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO);flashModeStatus status;} catch (error) {let err error as BusinessError;console.error(Failed to check whether the flash mode is supported. errorCode err.code);}if(flashModeStatus) {// 设置自动闪光灯模式try {photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO);} catch (error) {let err error as BusinessError;console.error(Failed to set the flash mode. errorCode err.code);}}}// 判断是否支持连续自动变焦模式let focusModeStatus: boolean false;try {let status: boolean photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);focusModeStatus status;} catch (error) {let err error as BusinessError;console.error(Failed to check whether the focus mode is supported. errorCode err.code);}if (focusModeStatus) {// 设置连续自动变焦模式try {photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);} catch (error) {let err error as BusinessError;console.error(Failed to set the focus mode. errorCode err.code);}}// 获取相机支持的可变焦距比范围let zoomRatioRange: Arraynumber [];try {zoomRatioRange photoSession.getZoomRatioRange();} catch (error) {let err error as BusinessError;console.error(Failed to get the zoom ratio range. errorCode err.code);}if (zoomRatioRange.length 0) {return;}// 设置可变焦距比try {photoSession.setZoomRatio(zoomRatioRange[0]);} catch (error) {let err error as BusinessError;console.error(Failed to set the zoom ratio value. errorCode err.code);}let photoCaptureSetting: camera.PhotoCaptureSetting {quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高rotation: camera.ImageRotation.ROTATION_0 // 设置图片旋转角度0}// 使用当前拍照设置进行拍照photoOutput.capture(photoCaptureSetting, (err: BusinessError) {if (err) {console.error(Failed to capture the photo ${err.message});return;}console.info(Callback invoked to indicate the photo capture request success.);});// 停止当前会话photoSession.stop();// 释放相机输入流cameraInput.close();// 释放预览输出流previewOutput.release();// 释放拍照输出流photoOutput.release();// 释放会话photoSession.release();// 会话置空photoSession undefined; } 5.2 录像实现方案 当前示例提供完整的录像流程介绍方便开发者了解完整的接口调用顺序。 在参考以下示例前建议开发者查看相机开发指导(ArkTS)的具体章节了解设备输入、会话管理、录像等单个流程。 5.2.1 开发流程 在获取到相机支持的输出流能力后开始创建录像流开发流程如下。 5.2.2 完整示例 Context获取方式请参考获取UIAbility的上下文信息。 import camera from ohos.multimedia.camera; import { BusinessError } from ohos.base; import media from ohos.multimedia.media; import common from ohos.app.ability.common; import PhotoAccessHelper from ohos.file.photoAccessHelper; import fs from ohos.file.fs;async function videoRecording(context: common.Context, surfaceId: string): Promisevoid {// 创建CameraManager对象let cameraManager: camera.CameraManager camera.getCameraManager(context);if (!cameraManager) {console.error(camera.getCameraManager error);return;}// 监听相机状态变化cameraManager.on(cameraStatus, (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) {console.info(camera : ${cameraStatusInfo.camera.cameraId});console.info(status: ${cameraStatusInfo.status});});// 获取相机列表let cameraArray: Arraycamera.CameraDevice [];try {cameraArray cameraManager.getSupportedCameras();} catch (error) {let err error as BusinessError;console.error(getSupportedCameras call failed. error code: ${err.code});}if (cameraArray.length 0) {console.error(cameraManager.getSupportedCameras error);return;}// 获取支持的模式类型let sceneModes: Arraycamera.SceneMode cameraManager.getSupportedSceneModes(cameraArray[0]);let isSupportVideoMode: boolean sceneModes.indexOf(camera.SceneMode.NORMAL_VIDEO) 0;if (!isSupportVideoMode) {console.error(video mode not support);return;}// 获取相机设备支持的输出流能力let cameraOutputCap: camera.CameraOutputCapability cameraManager.getSupportedOutputCapability(cameraArray[0], camera.SceneMode.NORMAL_VIDEO);if (!cameraOutputCap) {console.error(cameraManager.getSupportedOutputCapability error)return;}console.info(outputCapability: JSON.stringify(cameraOutputCap));let previewProfilesArray: Arraycamera.Profile cameraOutputCap.previewProfiles;if (!previewProfilesArray) {console.error(createOutput previewProfilesArray null || undefined);}let photoProfilesArray: Arraycamera.Profile cameraOutputCap.photoProfiles;if (!photoProfilesArray) {console.error(createOutput photoProfilesArray null || undefined);}let videoProfilesArray: Arraycamera.VideoProfile cameraOutputCap.videoProfiles;if (!videoProfilesArray) {console.error(createOutput videoProfilesArray null || undefined);}// videoProfile的宽高需要与AVRecorderProfile的宽高保持一致并且需要使用AVRecorderProfile锁支持的宽高let videoSize: camera.Size {width: 640,height: 480}let videoProfile: undefined | camera.VideoProfile videoProfilesArray.find((profile: camera.VideoProfile) {return profile.size.width videoSize.width profile.size.height videoSize.height;});if (!videoProfile) {console.error(videoProfile is not found);return;}// 配置参数以实际硬件设备支持的范围为准let aVRecorderProfile: media.AVRecorderProfile {audioBitrate: 48000,audioChannels: 2,audioCodec: media.CodecMimeType.AUDIO_AAC,audioSampleRate: 48000,fileFormat: media.ContainerFormatType.CFT_MPEG_4,videoBitrate: 2000000,videoCodec: media.CodecMimeType.VIDEO_AVC,videoFrameWidth: videoSize.width,videoFrameHeight: videoSize.height,videoFrameRate: 30};let options: PhotoAccessHelper.CreateOptions {title: Date.now().toString()};let photoAccessHelper: PhotoAccessHelper.PhotoAccessHelper PhotoAccessHelper.getPhotoAccessHelper(context);let videoUri: string await photoAccessHelper.createAsset(PhotoAccessHelper.PhotoType.VIDEO, mp4, options);let file: fs.File fs.openSync(videoUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);let aVRecorderConfig: media.AVRecorderConfig {audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC,videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV,profile: aVRecorderProfile,url: fd://${file.fd.toString()}, // 文件需先由调用者创建赋予读写权限将文件fd传给此参数eg.fd://45--file:///data/media/01.mp4rotation: 0, // 合理值0、90、180、270非合理值prepare接口将报错location: { latitude: 30, longitude: 130 }};let avRecorder: media.AVRecorder | undefined undefined;try {avRecorder await media.createAVRecorder();} catch (error) {let err error as BusinessError;console.error(createAVRecorder call failed. error code: ${err.code});}if (avRecorder undefined) {return;}try {await avRecorder.prepare(aVRecorderConfig);} catch (error) {let err error as BusinessError;console.error(prepare call failed. error code: ${err.code});}let videoSurfaceId: string | undefined undefined; // 该surfaceID用于传递给相机接口创造videoOutputtry {videoSurfaceId await avRecorder.getInputSurface();} catch (error) {let err error as BusinessError;console.error(getInputSurface call failed. error code: ${err.code});}if (videoSurfaceId undefined) {return;}// 创建VideoOutput对象let videoOutput: camera.VideoOutput | undefined undefined;try {videoOutput cameraManager.createVideoOutput(videoProfile, videoSurfaceId);} catch (error) {let err error as BusinessError;console.error(Failed to create the videoOutput instance. error: ${JSON.stringify(err)});}if (videoOutput undefined) {return;}// 监听视频输出错误信息videoOutput.on(error, (error: BusinessError) {console.error(Preview output error code: ${error.code});});//创建会话let videoSession: camera.CaptureSession | undefined undefined;try {videoSession cameraManager.createSession(camera.SceneMode.NORMAL_VIDEO) as camera.VideoSession;} catch (error) {let err error as BusinessError;console.error(Failed to create the session instance. error: ${JSON.stringify(err)});}if (videoSession undefined) {return;}// 监听session错误信息videoSession.on(error, (error: BusinessError) {console.error(Video session error code: ${error.code});});// 开始配置会话try {videoSession.beginConfig();} catch (error) {let err error as BusinessError;console.error(Failed to beginConfig. error: ${JSON.stringify(err)});}// 创建相机输入流let cameraInput: camera.CameraInput | undefined undefined;try {cameraInput cameraManager.createCameraInput(cameraArray[0]);} catch (error) {let err error as BusinessError;console.error(Failed to createCameraInput. error: ${JSON.stringify(err)});}if (cameraInput undefined) {return;}// 监听cameraInput错误信息let cameraDevice: camera.CameraDevice cameraArray[0];cameraInput.on(error, cameraDevice, (error: BusinessError) {console.error(Camera input error code: ${error.code});});// 打开相机try {await cameraInput.open();} catch (error) {let err error as BusinessError;console.error(Failed to open cameraInput. error: ${JSON.stringify(err)});}// 向会话中添加相机输入流try {videoSession.addInput(cameraInput);} catch (error) {let err error as BusinessError;console.error(Failed to add cameraInput. error: ${JSON.stringify(err)});}// 创建预览输出流其中参数 surfaceId 参考下面 XComponent 组件预览流为XComponent组件提供的surfacelet previewOutput: camera.PreviewOutput | undefined undefined;try {previewOutput cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId);} catch (error) {let err error as BusinessError;console.error(Failed to create the PreviewOutput instance. error: ${JSON.stringify(err)});}if (previewOutput undefined) {return;}// 向会话中添加预览输出流try {videoSession.addOutput(previewOutput);} catch (error) {let err error as BusinessError;console.error(Failed to add previewOutput. error: ${JSON.stringify(err)});}// 向会话中添加录像输出流try {videoSession.addOutput(videoOutput);} catch (error) {let err error as BusinessError;console.error(Failed to add videoOutput. error: ${JSON.stringify(err)});}// 提交会话配置try {await videoSession.commitConfig();} catch (error) {let err error as BusinessError;console.error(videoSession commitConfig error: ${JSON.stringify(err)});}// 启动会话try {await videoSession.start();} catch (error) {let err error as BusinessError;console.error(videoSession start error: ${JSON.stringify(err)});}// 启动录像输出流videoOutput.start((err: BusinessError) {if (err) {console.error(Failed to start the video output. error: ${JSON.stringify(err)});return;}console.info(Callback invoked to indicate the video output start success.);});// 开始录像try {await avRecorder.start();} catch (error) {let err error as BusinessError;console.error(avRecorder start error: ${JSON.stringify(err)});}// 停止录像输出流videoOutput.stop((err: BusinessError) {if (err) {console.error(Failed to stop the video output. error: ${JSON.stringify(err)});return;}console.info(Callback invoked to indicate the video output stop success.);});// 停止录像try {await avRecorder.stop();} catch (error) {let err error as BusinessError;console.error(avRecorder stop error: ${JSON.stringify(err)});}// 停止当前会话videoSession.stop();// 关闭文件fs.closeSync(file);// 释放相机输入流cameraInput.close();// 释放预览输出流previewOutput.release();// 释放录像输出流videoOutput.release();// 释放会话videoSession.release();// 会话置空videoSession undefined; } 参考文献 [1]OpenHarmoney应用开发文档
http://www.dnsts.com.cn/news/199626.html

相关文章:

  • 网站备案系统验证码出错用ps软件做ppt模板下载网站有哪些内容
  • 域名空间网站怎么做wordpress推荐
  • mooc网站建设网站开发投入产出分析
  • 一家做特卖的网站公司营销策划方案案例
  • 钢材贸易网站建设农产品网站设计方案
  • 网站建设有什么费用wordpress 域名 根目录
  • 网站的栏目有什么名字怎么查看网站外链
  • 昆山建设企业网站旅游网站设计说明
  • 模板生成网站share poine 户做网站
  • 中国航空集团建设开发有限公司网站产品网络营销推广方式
  • 安徽住房和城乡建设部网站首页想学电商去哪学
  • 做电影网站犯法吗好一点网站建设公司
  • 云南电商网站开发网络营销专业
  • 自己做网站分销关于茶文化网站建设的背景
  • 鹤岗市建设局网站如何成立网站
  • 网站制作标准网站建设客源在哪里找
  • 小微企业做网站前端如何兼职做网站
  • 巴中市网站建设中山seo技术
  • 政务网站集约化建设难点与建议个人asp网站模板下载
  • 网站的设计制作与维护网络营销课程总结1500字
  • 网站ui天津建设工程信息网如何投标报名
  • 酒店设计网站推荐江西建设职业技术学院招生信息网站
  • 如何查看网站空间商wordpress 外勤人员
  • 无锡模板网站应用市场
  • 一个人怎样做网站手工网站和自助建站式网站却别
  • 人家做网站是什么吉林省工伤保险网站
  • 深圳网站建设讯美wordpress去掉谷歌字体
  • 做网站协议怎么签网络品牌推广就选
  • 人才招聘网站大全长沙ui设计公司
  • 吉林华商建设集团网站网站开发服务器