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

鸿蒙 Next 如何使用 AVRecorder 从0到1实现视频录制功能(ArkTS)

在平时工作中,我们常常会遇到视频开发相关的业务需求,不过好在鸿蒙SDK提供了相关的解决方案:AVRecorder 是一个强大的视频录制工具,它集成了音频捕获、音频编码、视频编码和音视频封装功能,能够帮助开发者实现简单的视频录制功能,并直接生成本地视频文件。

本文将详细介绍如何在鸿蒙 Next 中使用 AVRecorder 进行视频录制,包括开发步骤、注意事项以及具体的代码示例。

一、AVRecorder 概述

AVRecorder 是鸿蒙系统提供的一个用于视频录制的 API,它支持音频和视频的同步录制,并能够将录制的内容保存为本地文件。它适用于需要实现简单视频录制功能的场景,例如录制视频日记、教学视频等。通过 AVRecorder,开发者可以轻松地控制录制的开始、暂停、恢复和停止,并且可以通过监听事件实时获取录制状态。

二、开发步骤

(一)申请权限

在使用 AVRecorder 进行视频录制之前,需要申请以下权限:

  • 麦克风权限:如果需要录制音频,需要申请 ohos.permission.MICROPHONE 权限。
  • 相机权限:如果需要使用相机录制视频,需要申请 ohos.permission.CAMERA 权限。
  • 文件读写权限:如果需要保存录制的视频文件到图库,需要申请ohos.permission.READ_IMAGEVIDEOohos.permission.WRITE_IMAGEVIDEO 权限。

示例代码如下:

import { Context } from '@ohos.app.ability.UIAbility';
import { fileIo as fs } from '@kit.CoreFileKit';const context: Context = getContext(this);
context.requestPermissions(['ohos.permission.MICROPHONE', 'ohos.permission.CAMERA'], (err, result) => {if (result[0] === 'ohos.permission.MICROPHONE' && result[1] === 'ohos.permission.CAMERA') {console.log('Permissions granted');} else {console.error('Permissions denied');}
});

(二)创建 AVRecorder 实例

调用 media.createAVRecorder() 方法创建 AVRecorder 实例,实例创建完成后进入 idle 状态。示例代码如下:

import { media } from '@kit.MediaKit';let avRecorder: media.AVRecorder;
media.createAVRecorder().then((recorder: media.AVRecorder) => {avRecorder = recorder;
}, (error) => {console.error('createAVRecorder failed: ' + error.message);
});

(三)设置监听事件

AVRecorder 提供了多种监听事件,开发者可以根据实际需求设置相应的监听事件。常用的监听事件包括:

  • stateChange:监听录制器状态变化。
  • error:监听录制器错误信息。

示例代码如下:

avRecorder.on('stateChange', (state: media.AVRecorderState, reason: media.StateChangeReason) => {console.info('current state is: ' + state);
});avRecorder.on('error', (err) => {console.error('error happened, error message is ' + err.message);
});

(四)配置录制参数

调用 prepare() 方法配置录制参数,此时 AVRecorder 进入 prepared 状态。配置参数时需要注意以下几点:

  • 确保已经申请了相关权限。
  • prepare() 方法的入参 avConfig 中仅设置视频相关的配置参数。
  • 录制输出的文件路径需要使用 fd:// 格式,可以通过调用基础文件操作接口(Core File Kitohos.file.fs)实现应用文件访问能力。

示例代码如下:

import { media } from '@kit.MediaKit';
import { fileIo as fs } from '@kit.CoreFileKit';let avProfile: media.AVRecorderProfile = {fileFormat: media.ContainerFormatType.CFT_MPEG_4,videoBitrate: 200000,videoCodec: media.CodecMimeType.VIDEO_AVC,videoFrameWidth: 640,videoFrameHeight: 480,videoFrameRate: 30
};const context: Context = getContext(this);
let filePath: string = context.filesDir + '/example.mp4';
let videoFile: fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let fileFd = videoFile.fd;let avConfig: media.AVRecorderConfig = {videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV,profile: avProfile,url: 'fd://' + fileFd.toString(),rotation: 0
};avRecorder.prepare(avConfig).then(() => {console.info('avRecorder prepare success');
}, (error) => {console.error('avRecorder prepare failed: ' + error.message);
});

(五)获取 SurfaceID

调用 getInputSurface() 方法获取录制所需的 SurfaceID,该 SurfaceID 用于传递给视频数据输入源模块(如相机)。示例代码如下:

avRecorder.getInputSurface().then((surfaceId: string) => {console.info('avRecorder getInputSurface success: ' + surfaceId);
}, (error) => {console.error('avRecorder getInputSurface failed: ' + error.message);
});

(六)初始化视频数据输入源

该步骤需要在输入源模块完成,以相机为例,需要创建录像输出流,包括创建 Camera 对象、获取相机列表、创建相机输入流等。示例代码如下:

import { camera } from '@kit.CameraKit';async function prepareCamera() {let cameraDevice: camera.CameraDevice;let cameraIdList: string[] = await camera.getCameraIdList();if (cameraIdList.length > 0) {cameraDevice = await camera.createCameraDevice(cameraIdList[0]);await cameraDevice.open();}return cameraDevice;
}async function startCameraOutput(cameraDevice: camera.CameraDevice, surfaceId: string) {let videoOutput: camera.VideoOutput = cameraDevice.createVideoOutput(surfaceId);await videoOutput.start();
}async function stopCameraOutput(videoOutput: camera.VideoOutput) {await videoOutput.stop();
}async function releaseCamera(cameraDevice: camera.CameraDevice) {await cameraDevice.close();
}

(七)开始录制

调用 start() 方法开始录制,此时 AVRecorder 进入 started 状态。示例代码如下:

avRecorder.start().then(() => {console.info('avRecorder start success');
}, (error) => {console.error('avRecorder start failed: ' + error.message);
});

(八)暂停录制

调用 pause() 方法暂停录制,此时 AVRecorder 进入 paused 状态。示例代码如下:

avRecorder.pause().then(() => {console.info('avRecorder pause success');
}, (error) => {console.error('avRecorder pause failed: ' + error.message);
});

(九)恢复录制

调用 resume() 方法恢复录制,此时 AVRecorder 再次进入 started 状态。示例代码如下:

avRecorder.resume().then(() => {console.info('avRecorder resume success');
}, (error) => {console.error('avRecorder resume failed: ' + error.message);
});

(十)停止录制

调用 stop() 方法停止录制,此时 AVRecorder 进入 stopped 状态。示例代码如下:

avRecorder.stop().then(() => {console.info('avRecorder stop success');
}, (error) => {console.error('avRecorder stop failed: ' + error.message);
});

(十一)重置资源

调用 reset() 方法重新进入 idle 状态,允许重新配置录制参数。示例代码如下:

avRecorder.reset().then(() => {console.info('avRecorder reset success');
}, (error) => {console.error('avRecorder reset failed: ' + error.message);
});

(十二)销毁实例

调用 release() 方法销毁实例,释放相关资源。示例代码如下:

avRecorder.release().then(() => {console.info('avRecorder release success');
}, (error) => {console.error('avRecorder release failed: ' + error.message);
});

三、完整代码示例

以下是一个完整的示例代码,展示了如何使用 AVRecorder 完成“开始录制-暂停录制-恢复录制-停止录制”的完整流程:

import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileIo as fs, fileUri } from '@kit.CoreFileKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';const TAG = 'VideoRecorderDemo:';
export class VideoRecorderDemo {private context: Context;constructor() {this.context = getContext(this);}private avRecorder: media.AVRecorder | undefined = undefined;private videoOutSurfaceId: string = "";private avProfile: media.AVRecorderProfile = {fileFormat : media.ContainerFormatType.CFT_MPEG_4, // 视频文件封装格式,只支持MP4。videoBitrate : 100000, // 视频比特率。videoCodec : media.CodecMimeType.VIDEO_AVC, // 视频文件编码格式,支持avc格式。videoFrameWidth : 640,  // 视频分辨率的宽。videoFrameHeight : 480, // 视频分辨率的高。videoFrameRate : 30 // 视频帧率。};private avConfig: media.AVRecorderConfig = {videoSourceType : media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV, // 视频源类型,支持YUV和ES两种格式。profile : this.avProfile,url : 'fd://35', //  参考应用文件访问与管理开发示例新建并读写一个文件。rotation : 0 // 视频旋转角度,默认为0不旋转,支持的值为0、90、180、270。};private uriPath: string = ''; // 文件uri,可用于安全控件保存媒体资源。private filePath: string = ''; // 文件路径。private fileFd: number = 0;// 创建文件以及设置avConfig.url。async createAndSetFd() {const path: string = this.context.filesDir + '/example.mp4'; // 文件沙箱路径,文件后缀名应与封装格式对应。const videoFile: fs.File = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);this.avConfig.url = 'fd://' + videoFile.fd; // 设置url。this.fileFd = videoFile.fd; // 文件fd。this.filePath = path;}// 注册avRecorder回调函数。setAvRecorderCallback() {if (this.avRecorder != undefined) {// 状态机变化回调函数。this.avRecorder.on('stateChange', (state: media.AVRecorderState, reason: media.StateChangeReason) => {console.info(TAG + 'current state is: ' + state);})// 错误上报回调函数。this.avRecorder.on('error', (err: BusinessError) => {console.error(TAG + 'error ocConstantSourceNode, error message is ' + err);})}}// 相机相关准备工作。async prepareCamera() {// 具体实现查看相机资料。}// 启动相机出流。async startCameraOutput() {// 调用VideoOutput的start接口开始录像输出。}// 停止相机出流。async stopCameraOutput() {// 调用VideoOutput的stop接口停止录像输出。}// 释放相机实例。async releaseCamera() {// 释放相机准备阶段创建出的实例。}// 开始录制对应的流程。async startRecordingProcess() {if (this.avRecorder === undefined) {// 1.创建录制实例。this.avRecorder = await media.createAVRecorder();this.setAvRecorderCallback();}// 2. 获取录制文件fd;获取到的值传递给avConfig里的url,实现略。// 3.配置录制参数完成准备工作。await this.avRecorder.prepare(this.avConfig);this.videoOutSurfaceId = await this.avRecorder.getInputSurface();// 4.完成相机相关准备工作。await this.prepareCamera();// 5.启动相机出流。await this.startCameraOutput();// 6. 启动录制。await this.avRecorder.start();}// 暂停录制对应的流程。async pauseRecordingProcess() {if (this.avRecorder != undefined && this.avRecorder.state === 'started') { // 仅在started状态下调用pause为合理状态切换。await this.avRecorder.pause();await this.stopCameraOutput(); // 停止相机出流。}}// 恢复录制对应的流程。async resumeRecordingProcess() {if (this.avRecorder != undefined && this.avRecorder.state === 'paused') { // 仅在paused状态下调用resume为合理状态切换。await this.startCameraOutput();  // 启动相机出流。await this.avRecorder.resume();}}async stopRecordingProcess() {if (this.avRecorder != undefined) {// 1. 停止录制。if (this.avRecorder.state === 'started'|| this.avRecorder.state === 'paused' ) { // 仅在started或者paused状态下调用stop为合理状态切换。await this.avRecorder.stop();await this.stopCameraOutput();}// 2.重置。await this.avRecorder.reset();// 3.释放录制实例。await this.avRecorder.release();// 4.文件录制完成后,关闭fd,实现略。await fs.close(this.fileFd);// 5.释放相机相关实例。await this.releaseCamera();}}// 安全控件保存媒体资源至图库。async saveRecorderAsset() {let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(this.context);// 需要确保uriPath对应的资源存在。this.uriPath = fileUri.getUriFromPath(this.filePath); // 获取录制文件的uri,用于安全控件保存至图库。let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = photoAccessHelper.MediaAssetChangeRequest.createVideoAssetRequest(this.context, this.uriPath);await phAccessHelper.applyChanges(assetChangeRequest);}// 一个完整的【开始录制-暂停录制-恢复录制-停止录制】示例。async videoRecorderDemo() {await this.startRecordingProcess();         // 开始录制。// 用户此处可以自行设置录制时长,例如通过设置休眠阻止代码执行。await this.pauseRecordingProcess();         //暂停录制。await this.resumeRecordingProcess();        // 恢复录制。await this.stopRecordingProcess();          // 停止录制。// 安全控件保存媒体资源至图库。await this.saveRecorderAsset();}
}
http://www.dtcms.com/a/593743.html

相关文章:

  • 动态背景网站北京网站设计制作费用
  • LSTM模型做分类任务2(PyTorch实现)
  • 企业网站模板 简洁wordpress 水印
  • PostgreSQL模式:数据库中的命名空间艺术
  • 数据库的4个基本概念
  • 做a网站wordpress 导入xml
  • zzcms网站开发wordpress 文章密码保护
  • 51-55 函数
  • 社交网站图片展示上门做网站公司哪家好
  • 请求头中传递错误信息
  • 安装使用IDEA完整过程(含maven,tomcat配置)
  • Vue3中的常用指令
  • C语言算法:排序算法进阶
  • Unity2D光照 - Spot Light 2D和Shadow Caster 2D的实践
  • LED蜡烛灯/火焰灯MCU控制方案开发设计
  • 技术融合新纪元:小鹏机器人+轻语AI+亚马逊倒模,能否打造革命性伴侣机器人
  • 中国各大网站网站域名好了下一步
  • 网站建设板块建议北京兼职网站建设
  • 两个浮点数如何判断相等
  • 盐城哪里做网站如何在网上推广app
  • 直播预告|AI + MCP 双驱,重塑操作系统交互逻辑,一键开启智能办公新范式
  • 佛山市 骏域网站建设除了凡科建站还有什么网站吗
  • 深入解析 Reactor 模式:从基类设计到模块协同的高性能服务器实现
  • 南阳网站建设seo安阳后营贴吧
  • 网站开发主流技术国产服务器系统免费的有哪些
  • 提升机器学习效率的秘密武器:GGML Tensor库
  • 管家婆软件登录提示:您连接的服务器版本不对,请重新升级安装服务器应用程序
  • BridgeVLA 算法:3D 操作学习的 VLM 对齐新范式
  • 做app网站建设百度指数 网站
  • 潮州网站制作佛山模板网站建设