欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > 《鸿蒙开发实战:音频录制、文件读取与播放功能全解析》

《鸿蒙开发实战:音频录制、文件读取与播放功能全解析》

2025/3/22 3:17:15 来源:https://blog.csdn.net/weixin_61662736/article/details/146338202  浏览:    关键词:《鸿蒙开发实战:音频录制、文件读取与播放功能全解析》

引言

随着HarmonyOS生态的快速发展,音频处理能力成为应用开发的核心需求之一。本文将从音频录制文件存储管理音频播放三个模块出发,结合完整代码示例,详解鸿蒙系统中音频功能的全链路开发实践。

1.1 核心模块

  1. 音频录制:基于Meadia Kit的AVRecorder实现高精度录音,支持实时波形显示。
  2. 文件管理:通过沙箱路径读写音频文件,适配不同设备存储策略。
  3. 音频播放:利用AVPlayer组件实现本地文件播放与状态控制。

官方文档

二、音频录制实现

1、申请权限

在module.json5声明麦克风权限

//src/main/module.json5"requestPermissions": [{"name":"ohos.permission.MICROPHONE","usedScene": {},"reason":"$string:EntryAbility_desc"}],

首先录音,那必然是需要录音权限,我们先询问用户申请录音权限,只有拿到录音权限之后才能够去录音。

使用abilityAccessCtrl.createAtManager() 向用户申请麦克风权限ohos.permission.MICROPHONE

async apply_for_right(){// 向用户申请麦克风权限const manager = abilityAccessCtrl.createAtManager()const result = await manager.requestPermissionsFromUser(getContext(), ['ohos.permission.MICROPHONE'])if(result.authResults[0] === -1) {//   表示用户点击了禁用,直接打开设置页面,要用户去设置// 定义参数const want: Want = {bundleName: 'com.huawei.hmos.settings',abilityName: 'com.huawei.hmos.settings.MainAbility',uri: 'application_info_entry',parameters: {// ✨✨✨修改成你的应用包名,跳转到该应用的设置页面 (包名在APP.json5)pushParams: 'com.example.hm_mianjing'}}const uiContext = getContext() as common.UIAbilityContext// 调起手机设置中的当前应用设置面板uiContext.startAbility(want)}}

如果用户点击了不允许录音,那我们便要向用户二次申请授权

在“设置”应用中的路径:设置 > 应用和元服务 > 某个应用

跳转的核心代码

// 定义参数
const want: Want = {bundleName: 'com.huawei.hmos.settings',abilityName: 'com.huawei.hmos.settings.MainAbility',uri: 'application_info_entry',parameters: {// ✨✨✨修改成你的应用包名,跳转到该应用的设置页面pushParams: 'com.itcast.interview_bjhm4App'}
}const uiContext = getContext() as common.UIAbilityContext
// 调起手机设置中的当前应用设置面板
uiContext.startAbility(want)
2.录制音频

利用AVRecorder录制基本的.m4a的音频文件

录制的核心代码

// 准备一个文件来接收录音数据写入
const filePath = getContext().filesDir + '/' + Date.now() + '.m4a'
// 以【创建】和【读写】权限打开文件
const file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
// 获取文件地址
const fd = file.fd 

录音的配置对象

const config: media.AVRecorderConfig = {audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC,  //音频采集源为麦克风profile: {audioBitrate: 100000, // 音频比特率audioChannels: 1, // 音频声道数audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aacaudioSampleRate: 48000, // 音频采样率fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前只支持m4a},url: `fd://${file.fd}`  //第一步中的文件地址
}

完整的录制代码

// 录制async transcribe(){// 1. 创建了录音对象this.avRecorder = await media.createAVRecorder()// 2.事件监听// 状态上报回调函数this.avRecorder.on('stateChange', (state: media.AVRecorderState, reason: media.StateChangeReason) => {console.log(`current state is ${state}`);// 用户可以在此补充状态发生切换后想要进行的动作})// 错误上报回调函数this.avRecorder.on('error', (err: BusinessError) => {console.error(`avRecorder failed, code is ${err.code}, message is ${err.message}`);})// 3.配置录音参数let avProfile: media.AVRecorderProfile = {audioBitrate: 100000, // 音频比特率audioChannels: 2, // 音频声道数audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前支持ACC,MP3,G711MUaudioSampleRate: 48000, // 音频采样率fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前支持MP4,M4A,MP3,WAV};const context: Context = getContext(this); // 参考应用文件访问与管理this.filePath = context.filesDir + '/'+ Date.now() + '.mp3';let audioFile: fs.File = fs.openSync(this.filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);let fileFd: number = audioFile.fd; // 获取文件fdlet avConfig: media.AVRecorderConfig = {audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, // 音频输入源,这里设置为麦克风profile: avProfile,url: 'fd://' + fileFd.toString(), // 参考应用文件访问与管理中的开发示例获取创建的音频文件fd填入此处};await this.avRecorder.prepare(avConfig)//   4. 开始录音this.avRecorder.start()}
3.播放音频

使用fd://文件fd 结合 AVPlayer 来完成录音的播放

使用 timeUpdate来监听播放时间的改变

//创建播放器对象const player = await media.createAVPlayer();player.on('stateChange',state=>{if (state === 'initialized') {player.prepare()}else if(state === 'prepared'){// player.loop = trueplayer.play()}})const file = fs.openSync(this.filePath,fs.OpenMode.READ_ONLY)// 赋值播放源: fd://文件的数字标记player.url = 'fd://' + file.fd

完整代码

import { abilityAccessCtrl, common, Want } from '@kit.AbilityKit'
import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';
import fs from '@ohos.file.fs';
import { relationalStore } from '@kit.ArkData';
import json from '@ohos.util.json';interface IArticle {id: numbertitle: stringcontent: stringcreate_time: number
}@Entry
@Component
struct AvrecorderAndRdbDemoPage {// 数据库表名tableName: string = 'article' //数据库的表名称,由我们自己定义store: relationalStore.RdbStore = {} as relationalStore.RdbStorefilePath: string = ''@State buttonColor:boolean = false// 创建AVRecorder实例avRecorder: media.AVRecorder = {} as media.AVRecorder// 申请权限async apply_for_right(){// 向用户申请麦克风权限const manager = abilityAccessCtrl.createAtManager()const result = await manager.requestPermissionsFromUser(getContext(), ['ohos.permission.MICROPHONE'])if(result.authResults[0] === -1) {//   表示用户点击了禁用,直接打开设置页面,要用户去设置// 定义参数const want: Want = {bundleName: 'com.huawei.hmos.settings',abilityName: 'com.huawei.hmos.settings.MainAbility',uri: 'application_info_entry',parameters: {// ✨✨✨修改成你的应用包名,跳转到该应用的设置页面 (包名在APP.json5)pushParams: 'com.example.hm_mianjing'}}const uiContext = getContext() as common.UIAbilityContext// 调起手机设置中的当前应用设置面板uiContext.startAbility(want)}}// 录制async transcribe(){// 1. 创建了录音对象this.avRecorder = await media.createAVRecorder()// 2.事件监听// 状态上报回调函数this.avRecorder.on('stateChange', (state: media.AVRecorderState, reason: media.StateChangeReason) => {console.log(`current state is ${state}`);// 用户可以在此补充状态发生切换后想要进行的动作})// 错误上报回调函数this.avRecorder.on('error', (err: BusinessError) => {console.error(`avRecorder failed, code is ${err.code}, message is ${err.message}`);})// 3.配置录音参数let avProfile: media.AVRecorderProfile = {audioBitrate: 100000, // 音频比特率audioChannels: 2, // 音频声道数audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前支持ACC,MP3,G711MUaudioSampleRate: 48000, // 音频采样率fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前支持MP4,M4A,MP3,WAV};const context: Context = getContext(this); // 参考应用文件访问与管理this.filePath = context.filesDir + '/'+ Date.now() + '.mp3';let audioFile: fs.File = fs.openSync(this.filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);let fileFd: number = audioFile.fd; // 获取文件fdlet avConfig: media.AVRecorderConfig = {audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, // 音频输入源,这里设置为麦克风profile: avProfile,url: 'fd://' + fileFd.toString(), // 参考应用文件访问与管理中的开发示例获取创建的音频文件fd填入此处};await this.avRecorder.prepare(avConfig)//   4. 开始录音this.avRecorder.start()}build() {Column({space:10}){Button('获取权限').onClick(()=>{this.apply_for_right()}).margin({bottom:20})Row({space:10}){Button('开始录制').onClick(() => {this.buttonColor = truethis.transcribe()})Button('停止录制').backgroundColor(this.buttonColor? Color.Red :'common_blue').onClick(() => {this.buttonColor = false// 停止录制this.avRecorder.stop();// 重置资源this.avRecorder.reset();// 销毁实例this.avRecorder.release();})}Button('播放音频').margin({top:20}).onClick(async ()=>{//创建播放器对象const player = await media.createAVPlayer();player.on('stateChange',state=>{if (state === 'initialized') {player.prepare()}else if(state === 'prepared'){// player.loop = trueplayer.play()}})const file = fs.openSync(this.filePath,fs.OpenMode.READ_ONLY)// 赋值播放源: fd://文件的数字标记player.url = 'fd://' + file.fd})}.width('100%').height('100%')}
}

总结:

完整的录制音频的流程:


1.由于录音会调用手机端麦克风,所以需要做如下权限配置,在项目的module.json5中声明麦克风的使用权限使用鸿蒙的底层api来向用户申请麦克风的使用权限使用abilityAccessCtrl这个api来授权
如果用户禁止使用麦克风,则使用UIAbilityContent的startAbility来进行二次引导授权此时用户如果点击了禁止,我们应该引导用户进行二次权限设置。


2.此时可以使用 AVRecorder对象来进行音频的录制在应用程序目录的files下准备一个文件用来接收音频数据的利用AVRecorder的start方法来采集麦克风的音频数据。

3.此时自动将音频数据保存到文件中使用AVPlayer对象播放录制好的音频。

适用HarmonyOS NEXT / API12或以上版本 -----------------

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词