鸿蒙媒体开发系列07——AVRecorder音频录制

 如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!扫描下方名片,关注公众号,公众号更新更快,同时也有更多学习资料和技术讨论群。

1、概述

在HarmonyOS系统中,多种API都提供了音频录制开发的支持,不同的API适用于不同录音输出格式、音频使用场景或不同开发语言。因此,选择合适的音频录制API,有助于降低开发工作量,实现更佳的音频录制效果。

  • AVRecorder:功能较完善的音频、视频录制ArkTS/JS API,集成了音频输入录制、音频编码和媒体封装的功能。开发者可以直接调用设备硬件如麦克风录音,并生成m4a音频文件。

  • AudioCapturer:用于音频输入的的ArkTS/JS API,仅支持PCM格式,需要应用持续读取音频数据进行工作。应用可以在音频输出后添加数据处理,要求开发者具备音频处理的基础知识,适用于更专业、更多样化的媒体录制应用开发。

  • OpenSL ES:一套跨平台标准化的音频Native API,目前阶段唯一的音频类Native API,同样提供音频输入原子能力,仅支持PCM格式,适用于从其他嵌入式平台移植,或依赖在Native层实现音频输入功能的录音应用使用。

注意:

应用可以调用麦克风录制音频,但该行为属于隐私敏感行为,在调用麦克风前,需要先向用户申请权限“ohos.permission.MICROPHONE”。

2、使用AVRecorder音频录制

使用AVRecorder可以实现音频录制功能,本文将以“开始录制-暂停录制-恢复录制-停止录制”的一次流程为示例,介绍AVRecorder音频录制相关功能。

在进行应用开发的过程中,我们可以通过AVRecorder的state属性,主动获取当前状态或使用on('stateChange')方法监听状态变化。开发过程中应该严格遵循状态机要求,例如只能在started状态下调用pause()接口,只能在paused状态下调用resume()接口。

AVRecorderState主要的状态罗列如下:

图片

AVRecorderState各个状态的流转变化如下图所示👇🏻👇🏻。

图片

3、开发步骤

1、创建AVRecorder实例

实例创建完成后,State将会进入idle状态。

import media from '@ohos.multimedia.media';let avRecorder = undefined;media.createAVRecorder().then((recorder) => {  avRecorder = recorder;}, (err) => {  console.error(`Invoke createAVRecorder failed, code is ${err.code}, message is ${err.message}`);})

2、设置业务需要监听的事件,监听状态变化及错误上报

图片

// 状态上报回调函数avRecorder.on('stateChange', (state, reason) => {  console.log(`current state is ${state}`);  // 用户可以在此补充状态发生切换后想要进行的动作})// 错误上报回调函数avRecorder.on('error', (err) => {  console.error(`avRecorder failed, code is ${err.code}, message is ${err.message}`);})

3、配置音频录制参数,调用prepare()接口,此时进入prepared状态。​​​​​​​

let avProfile = {  audioBitrate: 100000, // 音频比特率  audioChannels: 2, // 音频声道数  audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aac  audioSampleRate: 48000, // 音频采样率  fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前只支持m4a}let avConfig = {  audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, // 音频输入源,这里设置为麦克风  profile: avProfile,  url: 'fd://35', // 参考应用文件访问与管理中的开发示例获取创建的音频文件fd填入此处}avRecorder.prepare(avConfig).then(() => {  console.log('Invoke prepare succeeded.');}, (err) => {  console.error(`Invoke prepare failed, code is ${err.code}, message is ${err.message}`);})

4、开始录制,调用start()接口,此时进入started状态。

5、暂停录制,调用pause()接口,此时进入paused状态。

6、恢复录制,调用resume()接口,此时再次进入started状态。

7、停止录制,调用stop()接口,此时进入stopped状态。

8、重置资源,调用reset()重新进入idle状态,允许重新配置录制参数。

9、销毁实例,调用release()进入released状态,退出录制。

以一个“开始录制-暂停录制-恢复录制-停止录制”的流程为例,demo如下:​​​​​​​

import media from '@ohos.multimedia.media';export class AudioRecorderDemo {  private avRecorder;  private avProfile = {    audioBitrate: 100000, // 音频比特率    audioChannels: 2, // 音频声道数    audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aac    audioSampleRate: 48000, // 音频采样率    fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前只支持m4a  };  private avConfig = {    audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, // 音频输入源,这里设置为麦克风    profile: this.avProfile,    url: 'fd://35', // 参考应用文件访问与管理开发示例新建并读写一个文件  };  // 注册audioRecorder回调函数  setAudioRecorderCallback() {    // 状态机变化回调函数    this.avRecorder.on('stateChange', (state, reason) => {      console.log(`AudioRecorder current state is ${state}`);    })    // 错误上报回调函数    this.avRecorder.on('error', (err) => {      console.error(`AudioRecorder failed, code is ${err.code}, message is ${err.message}`);    })  }  // 开始录制对应的流程  async startRecordingProcess() {    // 1.创建录制实例    this.avRecorder = await media.createAVRecorder();    this.setAudioRecorderCallback();    // 2.获取录制文件fd赋予avConfig里的url;参考FilePicker文档    // 3.配置录制参数完成准备工作    await this.avRecorder.prepare(this.avConfig);    // 4.开始录制    await this.avRecorder.start();  }  // 暂停录制对应的流程  async pauseRecordingProcess() {    if (this.avRecorder.state === 'started') { // 仅在started状态下调用pause为合理状态切换      await this.avRecorder.pause();    }  }  // 恢复录制对应的流程  async resumeRecordingProcess() {    if (this.avRecorder.state === 'paused') { // 仅在paused状态下调用resume为合理状态切换      await this.avRecorder.resume();    }  }  // 停止录制对应的流程  async stopRecordingProcess() {    // 1. 停止录制    if (this.avRecorder.state === 'started'    || this.avRecorder.state === 'paused') { // 仅在started或者paused状态下调用stop为合理状态切换      await this.avRecorder.stop();    }    // 2.重置    await this.avRecorder.reset();    // 3.释放录制实例    await this.avRecorder.release();    // 4.关闭录制文件fd  }  // 一个完整的【开始录制-暂停录制-恢复录制-停止录制】示例  async audioRecorderDemo() {    await this.startRecordingProcess(); // 开始录制    // 用户此处可以自行设置录制时长,例如通过设置休眠阻止代码执行    await this.pauseRecordingProcess(); //暂停录制    await this.resumeRecordingProcess(); // 恢复录制    await this.stopRecordingProcess(); // 停止录制  }}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/145138.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Stable Diffusion 使用详解(11)--- 场景ICON制作

目录 背景 controlNet 整体描述 Canny Lineart Depth 实际使用 AI绘制需求 绘制过程 PS打底 场景模型选择 设置提示词及绘制参数 controlnet 设置 canny 边缘 depth 深度 lineart 线稿 效果 背景 这段时间不知道为啥小伙伴似乎喜欢制作很符合自己场景的ICON。…

Codeforces Round 784 (Div. 4) Kotlin

本期封面原图 画师煮タ 大福豆 最近学了下Kotlin的基础语法 想着巩固一下就开了一把div4 最后几题没时间了还是换回了C 要不然没法AK了 Idea编译的时候最后必须加上一句main函数的调用,但是cf的测评机又不能加这一句,总是忘记注释掉所以ce了很多发&…

Leetcode Hot 100刷题记录 -Day18(反转链表)

反转链表: 问题描述: 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1]示例 2: 输入:head [1,2] 输出&a…

工作中遇到的问题总结(1)

文章目录 第一题问题描述解决思路 第二题问题描述解决思路核心大表如何优化数据迁移过程是怎么样的如何将流量从旧系统迁移到新系统上 第三题问题描述解决思路 第四题问题描述解决思路方案一:双写机制方案二:基于时间戳的分流机制方案三:灰度…

【资料分析】刷题日记3

第一套 √ 考点:基期比重差很温柔的题 普通专科女生 占比 52.5% - 1.7% 50.8% 成人本专科女生 占比 57.8% - 4.6% 53.2% 相比降低了2.4% 知比重和部分量,求整体在花生老师的解法中体会啥叫适当约分 0.1899 / 47.8% / 87.5% 》0.19 / (4…

MySQL高阶1890-2020年最后一次登录

目录 题目 准备数据 分析数据 题目 编写解决方案以获取在 2020 年登录过的所有用户的本年度 最后一次 登录时间。结果集 不 包含 2020 年没有登录过的用户。 返回的结果集可以按 任意顺序 排列。 准备数据 Create table If Not Exists Logins (user_id int, time_stamp …

Ansbile-变量

文章目录 一、Ansible的常量(内置的变量)有哪些???????????????&#xff1…

Java之封装

文章目录 1.封装1.1 什么是封装1.2 访问限定符1.3 包1.3.1 什么是包1.3.2 导包1.3.3 自定义包 2. static2.1 static 修饰成员变量2.2 static 修饰成员方法2.3 static成员变量初始化 3. 代码快3.1 普通代码块3.2 实例代码块3.3 静态代码块 4. 对象的打印 1.封装 1.1 什么是封装…

力扣 713.乘积小于k的子数组

文章目录 题目介绍解法 题目介绍 解法 和209.长度最小的子数组思路大致相同。 思路:如果从l到r这一段的乘积是小于k的,那么[l,r]、[l1,r]….[r,r]这些子数组都是满足乘积小于k的,一共有r-l1个。 class Solution {public int minSubArrayLen…

Node.js backend for OpenAI image generation giving error code 400

题意:用于 OpenAI 图像生成的 Node.js 后端返回错误代码 400。 问题背景: I am trying to build a backend for the first time using Node.js. This is what I need: Generate image based on prompt -> Get the image and upload it to supabase s…

浅析OceanBase数据库的向量化执行引擎

本篇博客是偏数据库系统概念性的内容,不会深入到 OceanBase 中各个算子和表达式的在向量化中的详细设计和实现。 背景 为了提升OceanBase社区版用户解决问题的效率,OceanBase官方不久前推出了《OceanBase 从入门到实践》系列课程。在第七期直播课程后&a…

基于MATLAB的安全帽检测系统

课题名称 课题介绍 众所周知,在一些施工工地,必须明确佩戴安全帽。可以对生命安全起到保障作用。该课题为常见的安全帽的识别,主要分为红色,蓝色,黄色三类安全帽。而安全帽的主要是红色,蓝色&…

项目文件配置

1. 参数配置化 1.1 问题分析 1.2 问题解决 Value 注解通常用于外部配置的属性注入,具体用法为:Value("${配置文件中的key}") 2. yml配置文件 2.1 SpringBoot提供了多种属性配置方式 2.2 常见配置文件格式对比 2.3 yml 基本语法 大小写敏…

相位型SLM硬件产品面型性能提升

背景介绍 作为一种动态可编程光学元件,液晶空间光调制器(LC-SLM)在波前整形和光束控制等精密光学调控应用中发挥着非常重要的作用。典型的纯相位SLM工作原理是通过加载的电压控制在每个液晶像素处诱导相位延迟,实现对入射光波波前…

滚珠花键与滚珠丝杆的区别与应用

在机械工业中,经常使用滚珠花键这种传动元件,人们经常拿它与滚珠丝杆相比较,甚至与之混淆。事实上,它们是不同的,滚珠花键和滚珠丝杆在机械传动领域中各有其独特的作用和特点。那么,两者之间的区别是什么呢…

渐变色代码主题你受得了吗

分享一个vscode编辑器的渐变色主题 效果图如下 vscode扩展搜索 gradient theme安装即可。

LinuxC高级作业2

1.整理思维导图 2.做一套笔试题 一: 1.cd .. mkdir dir1 cd dir1 touch file1 2.cp ~/mnt/dir1/ -r * ~/home/dir2/ 3.pwd 4.ls -l 5.ifconfig 6.top 10.find /usr -type f -name "*name*" 11.:wq 13.df -h 14.tar -xzvf tmp.tar.gz 15.sudo c…

Windows安装启动:stable-diffusion-webui,AIGC大模型文生图、文生视频,Python

Windows安装启动:stable-diffusion-webui,AIGC大模型文生图、文生视频,Python stable-diffusion-webui是github上的AIGC开源项目,地址: https://github.com/AUTOMATIC1111/stable-diffusion-webuihttps://github.com/AUTOMATIC1…

ThreadLocal的用法

概述 ThreadLocal提供了线程局部变量,用于在线程中保存数据,在ThreadLocal中保存的数据仅属于当前线程,所以ThreadLocal实例的get或set方法访问自己的独立副本,这些副本之间相互隔离,互不影响 ThreadLocal利用Thread中…

YOLOv8改进系列,YOLOv8替换主干网络为PP-HGNetV2(百度飞桨视觉团队自研,助力涨点)

摘要 PP-HGNetV2(High Performance GPU Network V2) 是百度飞桨视觉团队自研的 PP-HGNet 的下一代版本,其在 PP-HGNet 的基础上,做了进一步优化和改进,最终在 NVIDIA GPU 设备上,将 “Accuracy-Latency Balance” 做到了极致,精度大幅超过了其他同样推理速度的模型。其在…