鸿蒙应用开发--音频捕获(录音)功能,需使用 @ohos.multimedia.audio 和 @ohos.multimedia.media 模块
·
在鸿蒙(HarmonyOS)开发中实现音频捕获(录音)功能,需使用 @ohos.multimedia.audio 和 @ohos.multimedia.media 模块。以下是完整实现方案,涵盖权限配置、音频流捕获、实时处理和保存等核心步骤。
一、权限配置
1. 声明权限 (module.json5)
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.MICROPHONE",
"reason": "需要访问麦克风进行录音"
},
{
"name": "ohos.permission.WRITE_MEDIA",
"reason": "保存录音文件到设备存储"
}
]
}
}
2. 动态权限申请
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
async function requestMicrophonePermission() {
const atManager = abilityAccessCtrl.createAtManager();
try {
const result = await atManager.requestPermissionsFromUser(
getContext(),
['ohos.permission.MICROPHONE', 'ohos.permission.WRITE_MEDIA']
);
return result.authResults[0] === 0; // 0 表示权限已授予
} catch (err) {
console.error('权限申请失败:', err.code);
return false;
}
}
二、音频捕获核心实现
1. 初始化音频参数
import audio from '@ohos.multimedia.audio';
// 配置音频参数
const audioConfig: audio.AudioCapturerOptions = {
streamInfo: {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100, // 采样率 44.1kHz
channels: audio.AudioChannel.CHANNEL_1, // 单声道
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 16位小端PCM
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 原始音频数据
},
capturerInfo: {
source: audio.SourceType.SOURCE_TYPE_MIC, // 麦克风输入
capturerFlags: 0 // 默认标志
}
};
2. 创建音频捕获器
let audioCapturer: audio.AudioCapturer | null = null;
async function initAudioCapturer() {
try {
audioCapturer = await audio.createAudioCapturer(audioConfig);
console.log('音频捕获器创建成功');
} catch (err) {
console.error('创建失败:', err.code);
}
}
3. 实时音频捕获与处理
async function startCapture() {
if (!audioCapturer) return;
// 创建临时文件保存音频
const filePath = getContext().filesDir + '/recording.pcm';
const file = await fs.open(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
// 启动捕获
await audioCapturer.start();
console.log('录音开始');
// 实时读取音频数据
while (audioCapturer.state === audio.AudioState.STATE_RUNNING) {
const buffer = await audioCapturer.read(BufferSize.SIZE_2048, false);
if (buffer === null) break;
// 处理音频数据(示例:写入文件)
await fs.write(file.fd, buffer);
// 可在此处添加实时处理逻辑(如降噪、格式转换)
}
// 停止捕获
await audioCapturer.stop();
await fs.close(file);
console.log('录音已保存至:', filePath);
}
三、高级功能扩展
1. 实时音频波形分析
function analyzeWaveform(buffer: ArrayBuffer) {
const dataView = new DataView(buffer);
let maxAmplitude = 0;
// 分析每个采样点的振幅(16位PCM)
for (let i = 0; i < dataView.byteLength; i += 2) {
const sample = dataView.getInt16(i, true); // 小端模式读取
maxAmplitude = Math.max(maxAmplitude, Math.abs(sample));
}
// 转换为分贝 (dBFS)
const dB = 20 * Math.log10(maxAmplitude / 32767);
console.log(`当前最大音量: ${dB.toFixed(1)} dB`);
}
2. 跨设备音频采集(分布式能力)
import distributedHardware from '@ohos.distributedHardware';
async function captureFromRemoteDevice() {
// 发现附近设备的麦克风
const devices = await distributedHardware.getDeviceList(['mic']);
const remoteMic = devices[0];
// 连接远程设备
const capturer = await audio.createAudioCapturer({
streamInfo: { ... }, // 参数需与远程设备协商一致
capturerInfo: {
source: audio.SourceType.SOURCE_TYPE_REMOTE_MIC,
deviceId: remoteMic.deviceId
}
});
// 使用方式与本地相同
capturer.start();
}
四、音频格式转换(PCM → WAV)
import fileio from '@ohos.fileio';
async function convertToWav(pcmPath: string, wavPath: string) {
const pcmStats = fs.statSync(pcmPath);
const pcmSize = pcmStats.size;
// WAV文件头结构
const wavHeader = Buffer.alloc(44);
wavHeader.write('RIFF', 0); // ChunkID
wavHeader.writeUInt32LE(pcmSize + 36, 4); // ChunkSize
wavHeader.write('WAVE', 8); // Format
wavHeader.write('fmt ', 12); // Subchunk1ID
wavHeader.writeUInt32LE(16, 16); // Subchunk1Size
wavHeader.writeUInt16LE(1, 20); // AudioFormat (PCM)
wavHeader.writeUInt16LE(1, 22); // NumChannels
wavHeader.writeUInt32LE(44100, 24); // SampleRate
wavHeader.writeUInt32LE(44100 * 1 * 2, 28); // ByteRate
wavHeader.writeUInt16LE(1 * 2, 32); // BlockAlign
wavHeader.writeUInt16LE(16, 34); // BitsPerSample
wavHeader.write('data', 36); // Subchunk2ID
wavHeader.writeUInt32LE(pcmSize, 40); // Subchunk2Size
// 写入文件
const wavFile = await fs.open(wavPath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
await fs.write(wavFile.fd, wavHeader.buffer);
const pcmFile = await fs.open(pcmPath, fs.OpenMode.READ_ONLY);
let offset = 0;
const bufferSize = 4096;
while (offset < pcmSize) {
const readSize = Math.min(bufferSize, pcmSize - offset);
const pcmData = await fs.read(pcmFile.fd, { offset, length: readSize });
await fs.write(wavFile.fd, pcmData.buffer);
offset += readSize;
}
await fs.close(wavFile);
await fs.close(pcmFile);
console.log('WAV 文件已生成:', wavPath);
}
五、常见问题解决
1. 录音无声音
- 检查权限:确认
MICROPHONE和WRITE_MEDIA权限已授予 - 验证设备:确认麦克风未被其他应用占用
- 测试硬件:使用系统录音机验证麦克风是否正常
2. 音频数据错乱
- 参数匹配:确保采样率、位深与实际硬件支持一致
- 字节序处理:小端模式(
S16LE)与大端模式(S16BE)需正确对应
3. 高延迟问题
- 优化缓冲区:调整
read()的缓冲区大小(推荐 2048-8192 字节) - 使用低延迟API:选择
AudioCapturerFlag.SOURCE_TYPE_VOICE_RECOGNITION模式
六、完整调用示例
@Entry
@Component
struct AudioCapturePage {
@State isRecording: boolean = false;
async toggleRecording() {
if (this.isRecording) {
await audioCapturer?.stop();
} else {
const hasPermission = await requestMicrophonePermission();
if (!hasPermission) return;
await initAudioCapturer();
this.isRecording = true;
startCapture(); // 异步执行
}
this.isRecording = !this.isRecording;
}
build() {
Column() {
Button(this.isRecording ? '停止录音' : '开始录音')
.onClick(() => this.toggleRecording())
Text('文件保存路径: /data/storage/recording.pcm')
.margin(20)
}
}
}
通过以上代码,您可以在鸿蒙系统中实现完整的音频捕获功能。关键点在于正确配置音频参数、处理权限申请以及合理管理音频数据流。对于需要更高性能的场景(如语音识别),可进一步优化缓冲区策略并集成硬件加速能力。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)