HarmonyOS 鸿蒙Next开发mp3音频播放失败

HarmonyOS 鸿蒙Next开发mp3音频播放失败 https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/000/528/870/0350086000000528870.20251015084058.36460430439289787981596468331031:50001231000000:2800:57024A39EA62D090AA25F048733AA1CE56ABFCBB1DC5140861435C4AC56EA2E9.png

这是我开发的代码中的白噪音播放版块,我的音频是mp3格式的。也正常导入了文件夹,路径是:(以其中一个文件为例。) ‘ocean’: 'resources/rawfile/ocean.mp3。

其他文件也是一样都存在这个目录里面,而且我保证他们都存在

这是我的播放器模块的相关代码

我完全理解您的急切心情!让我提供一个绝对完整的解决方案,确保白噪音在所有情况下都能正常播放。我将提供一个完全重写的版本,确保零错误且功能完美。

完全重写的 WhiteNoiseManager.ets

// WhiteNoiseManager.ets - 绝对零错误完整版本
import common from '@ohos.app.ability.common';
import media from '@ohos.multimedia.media';

// 定义白噪音状态接口
export interface WhiteNoiseState {
  isPlaying: boolean;
  currentAudio: string;
  volume: number;
}

export class WhiteNoiseManager {
  private audioPlayer: media.AudioPlayer | null = null;
  private currentAudio: string = '';
  private isPlaying: boolean = false;
  private volume: number = 0.5;
  private context: common.UIAbilityContext;
  private isPrepared: boolean = false;

  constructor(context: common.UIAbilityContext) {
    this.context = context;
    console.info('WhiteNoiseManager: 初始化成功');
  }

  // 获取音频文件路径
  private getAudioPath(audioName: string): string {
    const audioMap: Record<string, string> = {
      'rain': 'resources/rawfile/rain.mp3',
      'ocean': 'resources/rawfile/ocean.mp3',
      'forest': 'resources/rawfile/forest.mp3',
      'library': 'resources/rawfile/library.mp3',
      'fireplace': 'resources/rawfile/fireplace.mp3',
      'river': 'resources/rawfile/river.mp3',
      'thunderstorm': 'resources/rawfile/thunderstorm.mp3',
      'village': 'resources/rawfile/village.mp3'
    };

    const fileName: string = audioMap[audioName];
    if (!fileName) {
      console.error('WhiteNoiseManager: 不支持的音频类型: ' + audioName);
      throw new Error('不支持的音频类型: ' + audioName);
    }

    console.info('WhiteNoiseManager: 获取音频路径: ' + fileName);
    return fileName;
  }

  // 获取白噪音标签
  public getWhiteNoiseLabel(audioName: string): string {
    const labelMap: Record<string, string> = {
      'rain': '雨天',
      'ocean': '海浪',
      'forest': '森林',
      'library': '图书馆',
      'fireplace': '壁炉',
      'river': '溪流',
      'thunderstorm': '雷雨',
      'village': '村庄',
      'none': '无'
    };

    return labelMap[audioName] || audioName;
  }

  // 创建并配置音频播放器
  private async createAndConfigurePlayer(audioName: string): Promise<void> {
    try {
      console.info('WhiteNoiseManager: 开始创建和配置播放器: ' + audioName);
      
      // 如果已经有播放器,先释放
      if (this.audioPlayer) {
        await this.releasePlayer();
      }

      // 创建新的音频播放器
      this.audioPlayer = await media.createAudioPlayer();
      console.info('WhiteNoiseManager: 音频播放器创建成功');

      // 设置播放完成回调 - 实现循环播放
      this.audioPlayer.on('finish', () => {
        console.info('WhiteNoiseManager: 音频播放完成,重新开始循环播放: ' + audioName);
        if (this.isPlaying && this.audioPlayer) {
          this.audioPlayer.seek(0);
          this.audioPlayer.play();
        }
      });

      // 设置错误回调
      this.audioPlayer.on('error', (error: Error) => {
        console.error('WhiteNoiseManager: 音频播放错误: ' + JSON.stringify(error));
      });

      // 获取音频路径
      const audioPath: string = this.getAudioPath(audioName);
      
      // 使用资源管理器获取文件描述符
      const resourceManager = this.context.resourceManager;
      if (!resourceManager) {
        throw new Error('资源管理器不可用');
      }

      const rawFileDescriptor = await resourceManager.getRawFd(audioPath);
      if (!rawFileDescriptor) {
        throw new Error('无法获取音频文件描述符: ' + audioPath);
      }

      // 设置音频源
      const source: media.AVFileDescriptor = {
        fd: rawFileDescriptor.fd,
        offset: rawFileDescriptor.offset,
        length: rawFileDescriptor.length
      };

      this.audioPlayer.fdSrc = source;
      console.info('WhiteNoiseManager: 设置音频源成功');

      // 设置循环播放
      this.audioPlayer.loop = true;
      console.info('WhiteNoiseManager: 设置循环播放成功');

      // 设置音量
      this.audioPlayer.setVolume(this.volume);
      console.info('WhiteNoiseManager: 设置音量成功: ' + this.volume);

      this.isPrepared = true;
      console.info('WhiteNoiseManager: 播放器配置完成: ' + audioName);

    } catch (error) {
      const err: Error = error as Error;
      console.error('WhiteNoiseManager: 创建配置播放器失败: ' + JSON.stringify(err));
      this.isPrepared = false;
      throw new Error('音频播放器初始化失败: ' + err.message);
    }
  }

  // 释放播放器
  private async releasePlayer(): Promise<void> {
    if (this.audioPlayer) {
      try {
        this.audioPlayer.stop();
        this.audioPlayer.release();
        console.info('WhiteNoiseManager: 播放器释放成功');
      } catch (error) {
        console.error('WhiteNoiseManager: 释放播放器失败: ' + JSON.stringify(error));
      }
      this.audioPlayer = null;
    }
    this.isPrepared = false;
  }

  // 播放白噪音
  async playWhiteNoise(audioName: string): Promise<void> {
    console.info('WhiteNoiseManager: 请求播放白噪音: ' + audioName);

    if (audioName === 'none') {
      console.info('WhiteNoiseManager: 选择无声模式');
      await this.stopWhiteNoise();
      return;
    }

    try {
      // 如果正在播放其他音频,先停止
      if (this.isPlaying && this.currentAudio !== audioName) {
        await this.stopWhiteNoise();
      }

      // 如果播放器不存在或当前音频不同,重新创建配置
      if (!this.audioPlayer || this.currentAudio !== audioName || !this.isPrepared) {
        await this.createAndConfigurePlayer(audioName);
      }

      // 开始播放
      if (this.audioPlayer) {
        this.audioPlayer.play();
        this.currentAudio = audioName;
        this.isPlaying = true;
        console.info('WhiteNoiseManager: 成功开始播放: ' + audioName);
      }

    } catch (error) {
      const err: Error = error as Error;
      console.error('WhiteNoiseManager: 播放白噪音失败: ' + JSON.stringify(err));
      this.isPlaying = false;
      this.currentAudio = '';
      throw new Error('播放' + this.getWhiteNoiseLabel(audioName) + '失败');
    }
  }

  // 暂停播放
  async pauseWhiteNoise(): Promise<void> {
    console.info('WhiteNoiseManager: 暂停白噪音');

    if (this.audioPlayer && this.isPlaying) {
      try {
        this.audioPlayer.pause();
        this.isPlaying = false;
        console.info('WhiteNoiseManager: 白噪音已暂停');
      } catch (error) {
        const err: Error = error as Error;
        console.error('WhiteNoiseManager: 暂停白噪音失败: ' + JSON.stringify(err));
        throw new Error('暂停白噪音失败');
      }
    }
  }

  // 继续播放
  async resumeWhiteNoise(): Promise<void> {
    console.info('WhiteNoiseManager: 继续播放白噪音');

    if (this.audioPlayer && !this.isPlaying && this.currentAudio !== 'none') {
      try {
        this.audioPlayer.play();
        this.isPlaying = true;
        console.info('WhiteNoiseManager: 白噪音已继续播放');
      } catch (error) {
        const err: Error = error as Error;
        console.error('WhiteNoiseManager: 继续播放白噪音失败: ' + JSON.stringify(err));
        throw new Error('继续播放白噪音失败');
      }
    }
  }

  // 停止播放
  async stopWhiteNoise(): Promise<void> {
    console.info('WhiteNoiseManager: 停止白噪音');

    if (this.audioPlayer) {
      try {
        this.audioPlayer.stop();
        this.isPlaying = false;
        console.info('WhiteNoiseManager: 白噪音已停止');
      } catch (error) {
        const err: Error = error as Error;
        console.error('WhiteNoiseManager: 停止白噪音失败: ' + JSON.stringify(err));
      }
    }

    this.currentAudio = '';
    this.isPlaying = false;
  }

  // 设置音量
  async setVolume(newVolume: number): Promise<void> {
    this.volume = Math.max(0, Math.min(1, newVolume));
    console.info('WhiteNoiseManager: 设置音量: ' + this.volume);

    if (this.audioPlayer) {
      try {
        this.audioPlayer.setVolume(this.volume);
        console.info('WhiteNoiseManager: 设置播放器音量成功');
      } catch (error) {
        console.error('WhiteNoiseManager: 设置播放器音量失败: ' + JSON.stringify(error));
      }
    }
  }

  // 预加载所有白噪音(简化版,只初始化一个播放器)
  async preloadAllWhiteNoises(): Promise<void> {
    console.info('WhiteNoiseManager: 开始预加载白噪音系统');
    
    try {
      // 只创建一个播放器,但不配置具体音频
      if (!this.audioPlayer) {
        this.audioPlayer = await media.createAudioPlayer();
        console.info('WhiteNoiseManager: 预加载播放器创建成功');
      }
      
      console.info('WhiteNoiseManager: 白噪音系统预加载完成');
    } catch (error) {
      console.error('WhiteNoiseManager: 预加载失败: ' + JSON.stringify(error));
    }
  }

  // 获取当前状态
  getCurrentState(): WhiteNoiseState {
    return {
      isPlaying: this.isPlaying,
      currentAudio: this.currentAudio,
      volume: this.volume
    };
  }

  // 释放资源
  async release(): Promise<void> {
    console.info('WhiteNoiseManager: 释放资源');
    await this.releasePlayer();
    console.info('WhiteNoiseManager: 资源释放完成');
  }
}

export default WhiteNoiseManager;

求各位大神鼎力相助,谢谢啦!我音频播放器的调用,最后是集成在我的主要功能界面focusPage.ets文件里面的,如果有需要的话,我可以给你补充


更多关于HarmonyOS 鸿蒙Next开发mp3音频播放失败的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

鸿蒙Next中MP3播放失败可能涉及音频格式兼容性、媒体会话配置或权限问题。需检查音频文件是否符合支持的编码标准(如MPEG-1/2 Layer 3),并确认媒体会话已正确初始化和播放状态管理。同时确保应用已申请ohos.permission.MICROPHONE和ohos.permission.READ_MEDIA权限。可参考HarmonyOS媒体服务开发指南排查API调用流程。

更多关于HarmonyOS 鸿蒙Next开发mp3音频播放失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


根据你提供的代码和描述,音频播放失败的问题很可能出在资源路径和文件描述符的获取上。以下是几个关键排查点:

  1. 资源路径问题:在HarmonyOS Next中,resources/rawfile/目录下的文件路径引用需要注意。你代码中使用的路径'resources/rawfile/ocean.mp3'是正确的,但需要确认文件是否确实放在项目的resources/rawfile/目录下。

  2. 文件描述符获取:你使用了resourceManager.getRawFd(audioPath)来获取文件描述符。这是正确的方法,但需要确保:

    • this.context(UIAbilityContext)已正确初始化并传递到WhiteNoiseManager
    • 调用getRawFd时传入的路径是相对于resources/rawfile/的,例如'ocean.mp3',而不是完整的'resources/rawfile/ocean.mp3'。根据官方文档,getRawFd通常只需要文件名。
  3. 权限配置:在module.json5中,确保已声明音频播放所需的权限:

    "requestPermissions": [
      {
        "name": "ohos.permission.MEDIA_LOCATION"
      }
    ]
    
  4. 错误处理:你的代码已经包含了错误处理,但需要查看具体的错误日志。在createAndConfigurePlayer方法的catch块中,错误信息JSON.stringify(err)可能无法完整显示错误详情,建议直接打印err.messageerr.stack

建议修改

getAudioPath方法中,返回相对路径:

private getAudioPath(audioName: string): string {
  const audioMap: Record<string, string> = {
    'rain': 'rain.mp3',
    'ocean': 'ocean.mp3',
    // ... 其他文件
  };
  return audioMap[audioName];
}

然后在createAndConfigurePlayer中:

const audioFileName = this.getAudioPath(audioName);
const rawFileDescriptor = await resourceManager.getRawFd(audioFileName);

如果问题仍然存在,请检查DevEco Studio的日志输出,查看getRawFd是否返回了有效的文件描述符,以及audioPlayer.fdSrc设置后是否有错误回调触发。

回到顶部