HarmonyOS鸿蒙Next中AudioCapturer录制的音频使用AVPlayer播放,报类型不支持错误怎么解决
HarmonyOS鸿蒙Next中AudioCapturer录制的音频使用AVPlayer播放,报类型不支持错误怎么解决
【问题现象】
通过AudioCapturer录制音频,并将音频存储在wav格式的文件中。将wav格式文件通过base64编码后发送给服务端,服务端拿到base64编码后的文件作语音识别并播放。服务端使用AVPlayer播放时,发生报错,错误信息为"BusinessError: Unsupport Format: unsupport interface@5056652b"。
【背景知识】
-
音频录制开发概述:系统提供了多样化的API,来帮助开发者完成音频录制的开发,不同的API适用于不同录音输出格式、音频使用场景或不同开发语言。
- AudioCapturer:音频输入的ArkTS/JS API,仅支持PCM格式,需要应用持续读取音频数据进行工作。
- OpenSL ES:Native API,同样提供音频输入原子能力,仅支持PCM格式,适用于从其他嵌入式平台移植,或依赖在Native层实现音频输入功能的录音应用使用。
- OHAudio:音频输入的Native API,支持普通音频通路和低时延通路。仅支持PCM格式,适用于依赖Native层实现音频输入功能的场景。
- AVRecorder:音频录制的ArkTS/JS API,集成了音频输入录制、音频编码和媒体封装的功能。开发者可以直接调用设备硬件如麦克风录音,并生成m4a音频文件。
-
AVPlayer:将Audio/Video媒体资源(比如mp4/mp3/mkv/mpeg-ts等)转码为可供渲染的图像和可听见的音频模拟信号,并通过输出设备进行播放。
【定位思路】
- 确认pcm格式转wav格式是否正确。wav文件(PCM数据)分为三个部分,RIFF块描述、fmt块以及data块。如果需要把pcm码流保存成wav格式需要添加所对应的文件头(RIFF块和fmt块)。
- 确认base64编解码是否正确。
【解决方案】
- pcm格式转wav格式分两个步骤:先构造wav格式的文件头,再将pcm数据写入到wav文件中。
- wav格式的文件头构造:
// 写入wav文件头函数
private writeWaveFileHeader(
out: fs.File,
audioDataSize: number,
totalDataLen: number,
byteRate: number
) {
const header = new ArrayBuffer(44);
const dv = new DataView(header);
const bitsPerSample = 16; // 当前位深是16
// 写入RIFF块
this.writeString(dv, 0, 'RIFF');
dv.setUint32(4, totalDataLen, true);
this.writeString(dv, 8, 'WAVE');
// 写入fmt块
this.writeString(dv, 12, 'fmt ');
dv.setUint32(16, 16, true); // fmt块大小
dv.setUint16(20, 1, true); // 格式类别 (PCM)
dv.setUint16(22, this.mChannel, true); // 通道数
dv.setUint32(24, this.mSampleRate, true); // 采样率
dv.setUint32(28, byteRate, true); // ByteRate 码率
dv.setUint16(32, this.mChannel * bitsPerSample / 8, true); // BlockAlign
dv.setUint16(34, bitsPerSample, true); // 位深
// 写入data块
this.writeString(dv, 36, 'data');
dv.setUint32(40, audioDataSize, true); // 数据块大小
fs.writeSync(out.fd, new Uint8Array(header).buffer, {
length: 44
})
}
- pcm数据写入到wav文件中:
private writePcmData(inFile: fs.File, outFile: fs.File, audioDataSize: number) {
// 写入 pcm 数据
let readSize = 0
let data = new ArrayBuffer(audioDataSize);
let readOptions: ReadOptions = {
offset: readSize,
length: audioDataSize
};
let readLen = fs.readSync(inFile.fd, data, readOptions);
while (readLen > 0) {
readSize += readLen;
fs.writeSync(outFile.fd, data, { length: readLen});
readOptions.offset = readSize;
readLen = fs.readSync(inFile.fd, data, readOptions);
}
fs.closeSync(inFile.fd)
fs.closeSync(outFile.fd)
}
- 音频文件使用base64编码参考:
let file = await fileIo.open(this.selectedUri, fileIo.OpenMode.READ_ONLY);
let fileSize = fileIo.statSync(f.fd).size;
console.info('file Size: ' + fileSize);
let buffer = new ArrayBuffer(fileSize);
fileIo.readSync(f.fd, buffer);
fileIo.closeSync(f);
// Base64Helper的构造函数
let base64 = new util.Base64Helper();
// 通过输入参数编码后输出Uint8Array对象
let unit8data = base64.encodeSync(new Uint8Array(buffer.slice(0, buffer.byteLength)))
// 将字节数组解码为字符串,格式为utf-8
let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM : true })
let retStr = textDecoder.decodeWithStream( unit8data , {stream: false});
【总结】
-
AudioCapturer录制的音频格式为pcm格式,如果需要直接播放pcm音频文件,可以考虑使用AudioRenderer播放音频。
-
如果需要使用AVPlayer播放音频AudioCapturer录制的音频,必须将pcm格式音频文件转为AVPlayer播放器支持的文件格式。在进行格式转换时需要比较格式之间的差异(比如文件头差异),防止在格式转换时引入未知的错误。
更多关于HarmonyOS鸿蒙Next中AudioCapturer录制的音频使用AVPlayer播放,报类型不支持错误怎么解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙Next中AudioCapturer录制的音频使用AVPlayer播放,报类型不支持错误怎么解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,使用AudioCapturer录制的音频通过AVPlayer播放时,报类型不支持错误
在HarmonyOS鸿蒙Next中,使用AudioCapturer录制的音频通过AVPlayer播放时,报类型不支持错误,通常是由于音频格式或编码方式与AVPlayer支持的类型不匹配。AVPlayer支持的音频格式有限,可能无法直接播放AudioCapturer录制的原始PCM数据。可以通过以下步骤解决:
-
确认音频格式:检查AudioCapturer录制的音频格式,确保其为AVPlayer支持的格式,如AAC、MP3等。如果录制的是PCM数据,需先进行编码转换。
-
音频编码转换:如果录制的是PCM数据,使用鸿蒙的音频编码接口(如AudioEncoder)将其转换为AVPlayer支持的格式,如AAC或MP3。
-
设置AVPlayer的源:确保转换后的音频文件路径或数据流正确设置给AVPlayer。
-
检查权限:确认应用已获取必要的音频录制和播放权限。
-
日志分析:通过日志进一步分析错误信息,确认具体不支持的格式或编码。
通过这些步骤,可以解决AVPlayer播放AudioCapturer录制音频时的类型不支持错误。