HarmonyOS 鸿蒙Next中AVRecorder如何录制MP3格式音频?
HarmonyOS 鸿蒙Next中AVRecorder如何录制MP3格式音频? AVRecorder如何录制MP3格式音频?
AVRecorder 支持以下音频编码格式:
- ✅ MP3 (AUDIO_MP3)
- AAC (AUDIO_AAC)
- G711MU (AUDIO_G711MU)
- AMR-NB (AUDIO_AMR_NB)
- AMR-WB (AUDIO_AMR_WB)
MP3 录制完整示例
方案一:ArkTS 实现
import { common } from '@kit.AbilityKit';
import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileIo as fs } from '@kit.CoreFileKit';
export class MP3Recorder {
private avRecorder: media.AVRecorder | undefined = undefined;
private audioFile: fs.File | undefined = undefined;
/**
* 初始化 MP3 录音器
*/
async init(context: common.Context): Promise<boolean> {
try {
// 1. 创建 AVRecorder 实例
this.avRecorder = await media.createAVRecorder();
// 2. 注册状态变化回调
this.avRecorder.on('stateChange', (state: media.AVRecorderState, reason: media.StateChangeReason) => {
console.info(`AVRecorder state changed to ${state}, reason: ${reason}`);
});
// 3. 注册错误回调
this.avRecorder.on('error', (error: BusinessError) => {
console.error(`AVRecorder error: ${error.code}, ${error.message}`);
});
// 4. 创建 MP3 文件
let path: string = context.filesDir + '/recording_' + Date.now() + '.mp3';
this.audioFile = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
console.info(`MP3 file created at: ${path}`);
// 5. 配置录制参数 - 重点:MP3 格式配置
let avProfile: media.AVRecorderProfile = {
audioBitrate: 128000, // 比特率 128kbps(常用:64k/128k/192k/320k)
audioChannels: 2, // 立体声(1=单声道,2=立体声)
audioCodec: media.CodecMimeType.AUDIO_MP3, // ⭐ MP3 编码
audioSampleRate: 44100, // 采样率 44.1kHz(常用:44100/48000)
fileFormat: media.ContainerFormatType.CFT_MP3 // ⭐ MP3 容器格式
};
let avConfig: media.AVRecorderConfig = {
audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, // 麦克风输入
profile: avProfile,
url: 'fd://' + this.audioFile.fd
};
// 6. 准备录制
if (this.avRecorder.state === 'idle' || this.avRecorder.state === 'stopped') {
await this.avRecorder.prepare(avConfig);
console.info('AVRecorder prepared for MP3 recording');
return true;
}
} catch (error) {
let err = error as BusinessError;
console.error(`Failed to init MP3 recorder: ${err.code}, ${err.message}`);
return false;
}
return false;
}
/**
* 开始录制
*/
async start(): Promise<boolean> {
try {
if (this.avRecorder?.state === 'prepared') {
await this.avRecorder.start();
console.info('MP3 recording started');
return true;
}
} catch (error) {
let err = error as BusinessError;
console.error(`Failed to start recording: ${err.code}, ${err.message}`);
}
return false;
}
/**
* 暂停录制
*/
async pause(): Promise<boolean> {
try {
if (this.avRecorder?.state === 'started') {
await this.avRecorder.pause();
console.info('MP3 recording paused');
return true;
}
} catch (error) {
let err = error as BusinessError;
console.error(`Failed to pause recording: ${err.code}, ${err.message}`);
}
return false;
}
/**
* 恢复录制
*/
async resume(): Promise<boolean> {
try {
if (this.avRecorder?.state === 'paused') {
await this.avRecorder.resume();
console.info('MP3 recording resumed');
return true;
}
} catch (error) {
let err = error as BusinessError;
console.error(`Failed to resume recording: ${err.code}, ${err.message}`);
}
return false;
}
/**
* 停止录制
*/
async stop(): Promise<boolean> {
try {
if (this.avRecorder?.state === 'started' || this.avRecorder?.state === 'paused') {
await this.avRecorder.stop();
console.info('MP3 recording stopped');
return true;
}
} catch (error) {
let err = error as BusinessError;
console.error(`Failed to stop recording: ${err.code}, ${err.message}`);
}
return false;
}
/**
* 释放资源
*/
async release(): Promise<void> {
try {
// 重置录制器
if (this.avRecorder) {
await this.avRecorder.reset();
await this.avRecorder.release();
this.avRecorder = undefined;
}
// 关闭文件
if (this.audioFile) {
await fs.close(this.audioFile.fd);
this.audioFile = undefined;
}
console.info('MP3 recorder released');
} catch (error) {
let err = error as BusinessError;
console.error(`Failed to release recorder: ${err.code}, ${err.message}`);
}
}
/**
* 获取当前状态
*/
getState(): string {
return this.avRecorder?.state || 'unknown';
}
}
方案二:在 UI 组件中使用
import { MP3Recorder } from './MP3Recorder';
@Entry
@Component
struct RecordingPage {
private recorder: MP3Recorder = new MP3Recorder();
@State recordingState: string = 'idle';
@State recordingTime: number = 0;
private timer: number = -1;
async aboutToAppear() {
// 初始化录音器
let context = getContext(this) as common.UIAbilityContext;
await this.recorder.init(context);
this.recordingState = this.recorder.getState();
}
aboutToDisappear() {
// 释放资源
this.recorder.release();
if (this.timer !== -1) {
clearInterval(this.timer);
}
}
// 开始录音
async startRecording() {
let success = await this.recorder.start();
if (success) {
this.recordingState = 'recording';
this.recordingTime = 0;
// 启动计时器
this.timer = setInterval(() => {
this.recordingTime++;
}, 1000);
}
}
// 暂停录音
async pauseRecording() {
let success = await this.recorder.pause();
if (success) {
this.recordingState = 'paused';
if (this.timer !== -1) {
clearInterval(this.timer);
}
}
}
// 恢复录音
async resumeRecording() {
let success = await this.recorder.resume();
if (success) {
this.recordingState = 'recording';
// 重启计时器
this.timer = setInterval(() => {
this.recordingTime++;
}, 1000);
}
}
// 停止录音
async stopRecording() {
let success = await this.recorder.stop();
if (success) {
this.recordingState = 'stopped';
if (this.timer !== -1) {
clearInterval(this.timer);
}
}
}
// 格式化时间显示
formatTime(seconds: number): string {
let min = Math.floor(seconds / 60);
let sec = seconds % 60;
return `${min.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`;
}
build() {
Column() {
Text('MP3 录音')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
// 录音时长显示
Text(this.formatTime(this.recordingTime))
.fontSize(48)
.fontWeight(FontWeight.Medium)
.margin({ bottom: 20 })
// 状态显示
Text(`状态: ${this.recordingState}`)
.fontSize(16)
.margin({ bottom: 40 })
// 控制按钮
Row() {
Button('开始')
.onClick(() => this.startRecording())
.enabled(this.recordingState === 'prepared')
.margin({ right: 10 })
Button('暂停')
.onClick(() => this.pauseRecording())
.enabled(this.recordingState === 'recording')
.margin({ right: 10 })
Button('继续')
.onClick(() => this.resumeRecording())
.enabled(this.recordingState === 'paused')
.margin({ right: 10 })
Button('停止')
.onClick(() => this.stopRecording())
.enabled(this.recordingState === 'recording' || this.recordingState === 'paused')
}
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
权限配置
不要忘记在 module.json5 中申请麦克风权限:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.MICROPHONE",
"reason": "$string:microphone_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
}
在使用前动态申请权限:
import { abilityAccessCtrl, common } from '@kit.AbilityKit';
async function requestMicrophonePermission(context: common.UIAbilityContext): Promise<boolean> {
let atManager = abilityAccessCtrl.createAtManager();
try {
let data = await atManager.requestPermissionsFromUser(context, ['ohos.permission.MICROPHONE']);
if (data.authResults[0] === 0) {
console.info('Microphone permission granted');
return true;
} else {
console.error('Microphone permission denied');
return false;
}
} catch (error) {
console.error(`Failed to request permission: ${error}`);
return false;
}
}
更多关于HarmonyOS 鸿蒙Next中AVRecorder如何录制MP3格式音频?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,AVRecorder目前不支持直接录制MP3格式音频。系统默认支持的音频编码格式为AAC。如需处理MP3文件,可通过MediaCodec进行音频格式转码,或使用第三方库实现MP3编码功能。开发者需在config中配置音频编码类型为AudioEncoder.AAC,录制完成后通过转换工具生成MP3文件。
在HarmonyOS Next中,目前AVRecorder暂不支持直接录制MP3格式音频。系统默认支持的音频编码格式为AAC(通过AudioEncoder.AAC_LC配置),这是移动设备上更通用的音频格式。
如果需要MP3格式输出,建议采用以下方案:
-
录制后转码:先使用AVRecorder录制AAC格式音频,然后通过第三方音频处理库(如LAME)将生成的AAC文件转换为MP3格式。
-
配置参数示例:
let avRecorder: media.AVRecorder
let profile: media.AVRecorderProfile = {
audioBitrate: 128000,
audioChannels: 2,
audioCodec: media.CodecMimeType.AUDIO_AAC,
audioSampleRate: 44100,
fileFormat: media.ContainerFormatType.CFT_MPEG_4
}
- 文件处理:录制完成后获取文件路径,使用转码工具处理:
// 获取录制文件
let file = fs.openSync(outputPath, fs.OpenMode.READ_WRITE)
// 调用转码接口转换为MP3
这种方案既保证了录制过程的稳定性,又能最终获得MP3格式文件。建议优先考虑AAC格式,其在保持音质的同时具有更好的设备兼容性。

