HarmonyOS鸿蒙Next中解码base64音频数据,播放音频报错5400102

HarmonyOS鸿蒙Next中解码base64音频数据,播放音频报错5400102 【问题描述】:解码base64音频数据,播放音频报错5400102

【问题现象】:

解码代码:

this.audioFilePath = context.tempDir + '/test.mp3';
let result = new util.Base64Helper().decodeSync(this.base64Str);
const file = fs.openSync(this.audioFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
const writeLen = fs.writeSync(file.fd, result.buffer);
this.url = 'fd://' + file.fd
fs.closeSync(file);
console.info(`Base64解码写入成功,字节数:${writeLen}`);

在播放按钮的点击事件只执行了

this.avPlayer.url = this.url

avplayer的对象创建和监听stateChange用的是官方文档里的案例,应该是没有问题的,但是点击播放按钮就会报错

【版本信息】:api20

【复现代码】:同上

【尝试解决方案】:无


更多关于HarmonyOS鸿蒙Next中解码base64音频数据,播放音频报错5400102的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

可以参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-file-fs#fsclosesync
cke_367.png

因此,需要先打开file对象,fd拼接出的路径才有效,示例代码:

let fdPath = ‘fd://’;

let file = fs.openSync(this.audioFilePath);

fdPath = fdPath + ‘’ + file.fd;

this.avPlayer.url = fdPath

这样就可以播放了,然后在监听事件中及时执行fs.closesync来关闭file对象防止内存泄漏

更多关于HarmonyOS鸿蒙Next中解码base64音频数据,播放音频报错5400102的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,解码Base64音频数据后播放报错5400102,通常表示音频格式不支持或数据损坏。请检查Base64字符串是否完整,解码后的音频格式是否为系统支持的格式(如AAC、MP3)。确保使用正确的解码方法,并验证音频数据在播放前的完整性。

错误码5400102通常表示AVPlayer在设置播放源(URL)时遇到了问题,具体是AV_ERROR_IO_INVALID,即无效的输入/输出。根据你提供的代码,问题很可能出在文件描述符(fd)的处理上。

核心问题在于:你在将文件描述符(file.fd)拼接成'fd://' + file.fd格式的URL后,立即关闭了文件fs.closeSync(file))。这导致当AVPlayer尝试通过这个文件描述符访问音频文件时,该描述符已经失效,从而引发IO错误。

解决方案: 不要过早关闭文件。文件描述符需要在AVPlayer的整个播放生命周期内保持有效。正确的做法是在确定不再需要播放该文件时(例如,在AVPlayer的stateChange监听器中收到STATE_IDLESTATE_STOPPED状态,并准备释放资源时),再关闭文件描述符。

修改后的代码逻辑建议:

  1. 解码和写入文件部分保持不变,但不要立即关闭文件:

    this.audioFilePath = context.tempDir + '/test.mp3';
    let result = new util.Base64Helper().decodeSync(this.base64Str);
    const file = fs.openSync(this.audioFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    const writeLen = fs.writeSync(file.fd, result.buffer);
    // 关键:此处不要调用 fs.closeSync(file);
    this.url = 'fd://' + file.fd;
    this.audioFile = file; // 将file对象保存到成员变量中,以便后续关闭
    console.info(`Base64解码写入成功,字节数:${writeLen}`);
    
  2. 在适当的时机关闭文件: 例如,在AVPlayer的stateChange监听器中,当播放结束或播放器被释放时。

    // 假设在avPlayer的stateChange回调中
    avPlayer.on('stateChange', (state, reason) => {
      if (state === avPlayer.AVState.STOPPED || state === avPlayer.AVState.IDLE) {
        // 当播放停止或闲置时,关闭之前打开的文件
        if (this.audioFile) {
          fs.closeSync(this.audioFile);
          this.audioFile = undefined;
          console.info('音频文件已关闭');
        }
      }
    });
    

    或者,在你的业务逻辑中明确知道不再需要播放该音频时(例如,组件销毁或切换音频源前),手动调用关闭。

其他注意事项:

  • 文件路径有效性: 确保context.tempDir是有效的应用临时目录路径。
  • Base64数据格式: 确认this.base64Str是标准的、无换行符等杂质的Base64编码字符串,且解码后的二进制数据是有效的MP3格式。
  • 权限: 确保应用已申请必要的文件读写权限(ohos.permission.READ_MEDIAohos.permission.WRITE_MEDIA)。

通过延迟文件描述符的关闭时机,应该能解决5400102报错问题。

回到顶部