HarmonyOS 鸿蒙Next中SoundPool循环播放有点卡顿,怎么处理?

HarmonyOS 鸿蒙Next中SoundPool循环播放有点卡顿,怎么处理? 我用鸿蒙SoundPool循环播放某个音频,在每次循环结束再开始的时候,会感觉到一点卡顿。感觉没有安卓手机那么丝滑。

这里预加载,优先度我都是加了的,但是还是不行。就是听着有一点点延迟

const playParams: media.PlayParameters = {
  loop:-1, // -1表示循环播放
  rate: audio.AudioRendererRate.RENDER_RATE_NORMAL,
  leftVolume: 1.0,
  rightVolume: 1.0,
  priority: 1,
}

如果想实现循环播放某个音频,用什么方法好?


更多关于HarmonyOS 鸿蒙Next中SoundPool循环播放有点卡顿,怎么处理?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

开发者您好,本地使用手机循环播放一个3秒的音频,未复现问题。本地代码如下:

// Index.ets
import { media } from '@kit.MediaKit';
import { audio } from '@kit.AudioKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct Index {
  private soundPool: media.SoundPool | undefined = undefined;
  private soundId: number = 0;
  private streamId: number = 0;

  async aboutToAppear(): Promise<void> {
    this.create();
  }

  async aboutToDisappear() {
    this.release();
  }

  build() {
    Column() {
      Row() {
        Button('播放RawFile')
          .width(100)
          .height(100)
          .onClick(() => {
            this.PlaySoundPool()
          })
          .type(ButtonType.Circle)
    }
    .height('100%')
    .width('100%')
  }

  async create() {
    try {
      let audioRendererInfo: audio.AudioRendererInfo = {
        usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
        rendererFlags: 1
      }
      // 创建soundPool实例。
      this.soundPool = await media.createSoundPool(14,audioRendererInfo);
      // 注册监听。
      this.loadCallback();
      this.finishPlayCallback();
      this.setErrorCallback();

      // 加载音频资源。
      let context = this.getUIContext().getHostContext();;
      let fileDescriptor = await context!.resourceManager.getRawFd('123.mp3'); // 音频资源
      this.soundId = await this.soundPool!.load(fileDescriptor.fd, fileDescriptor.offset, fileDescriptor.length);
      console.info(`load soundPool soundId: ${this.soundId}`)
    } catch (e) {
      console.error('createSoundPool error: ' + e);
    }
  }

  async loadCallback() {
    // 加载完成回调。
    this.soundPool!.on('loadComplete', (soundId_: number) => {
      this.soundId = soundId_;
      console.info('loadComplete soundId: ' + soundId_);
    })
  }

  // 设置播放完成监听。
  async finishPlayCallback() {
    this.soundPool!.on('playFinished', () => {
      console.info('receive play finished message');
    })
  }

  // 设置错误类型监听。
  async setErrorCallback() {
    this.soundPool!.on('error', (error: BusinessError) => {
      console.error('error happened,message is :' + error.code);
      console.error('error happened,message is :' + error.message);
    })
  }

  async PlaySoundPool() {
    let playParameters: media.PlayParameters = {
      loop: -1,
      rate: audio.AudioRendererRate.RENDER_RATE_NORMAL,
      leftVolume: 1.0,
      rightVolume: 1.0,
      priority: 1,
    };
    this.soundPool!.play(this.soundId, playParameters, (error, streamID: number) => {
      if (error) {
        console.error(`play sound Error: errCode is ${error.code}, errMessage is ${error.message}`)
      } else {
        this.streamId = streamID;
        console.info('play success soundid:' + this.streamId);
      }
    });
  }

  async release() {
    // 终止指定流的播放。
    await this.soundPool!.stop(this.streamId);
    // 卸载音频资源。
    await this.soundPool!.unload(this.soundId);
    // 关闭监听。
    this.setOffCallback();
    // 释放SoundPool。
    await this.soundPool!.release();
  }

  async setOffCallback() {
    this.soundPool!.off('loadComplete');
    this.soundPool!.off('playFinished');
    this.soundPool!.off('error');
  }
}

模拟器与手机播放效果可能存在不同,以手机为准,请使用手机尝试,如果仍然无法解决问题,请提供DevEco Studio版本和设备版本以及复现问题的demo。

更多关于HarmonyOS 鸿蒙Next中SoundPool循环播放有点卡顿,怎么处理?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


开发者您好,本地未复现问题,请提供如下信息:

  1. 请提供循环播放的音频文件。

音频怎么给?就是普通的.mp3文件。3秒的时长,

在HarmonyOS Next中,SoundPool循环播放卡顿可尝试以下方法:

  1. 检查音频文件格式,建议使用较小尺寸的OGG或WAV文件。
  2. 调整SoundPool的加载方式,使用load方法时确保音频已完全加载再播放。
  3. 控制并发播放数量,避免同时播放多个音频流。
  4. 使用setLoop设置循环时,确认参数正确,避免频繁调用。
  5. 确保在UI线程外处理音频播放逻辑,减少主线程阻塞。

在HarmonyOS Next中,SoundPool循环播放出现卡顿,通常与音频解码和缓冲机制有关。针对你描述的循环衔接处卡顿问题,可以尝试以下优化方案:

  1. 使用单次播放配合on(‘finish’)监听实现无缝循环: 这是解决循环卡顿最有效的方法。将loop参数设为0(单次播放),在播放结束时立即触发下一次播放,可以避免系统循环播放时的缓冲间隙。

    let soundId: number; // 存储播放的soundId
    // 加载音频
    // ... soundPool.load(...)
    
    const playParams: media.PlayParameters = {
      loop: 0, // 改为单次播放
      rate: audio.AudioRendererRate.RENDER_RATE_NORMAL,
      leftVolume: 1.0,
      rightVolume: 1.0,
      priority: 1,
    };
    
    soundId = soundPool.play(soundId, playParams);
    
    // 监听播放结束事件
    soundPool.on('finish', (soundId: number) => {
      // 播放结束时立即重新播放
      soundPool.play(soundId, playParams);
    });
    
  2. 预加载优化: 确保音频已完全加载到内存中。在调用play()前,使用load()并确认加载完成。

    // 提前加载音频
    const soundId = await soundPool.load(context, resourceId, priority);
    // 确认加载完成后再播放
    
  3. 检查音频格式: 使用较短、文件大小适中的音频文件(如WAV或OGG格式),避免使用MP3等需要复杂解码的格式,以减少解码延迟。

  4. 调整缓冲区设置: 虽然SoundPool的缓冲区配置选项有限,但可以尝试调整音频流的缓冲区大小(如果API支持),确保足够的数据预加载。

如果上述方法仍无法解决,考虑使用audio.AudioRenderer进行更低延迟的音频播放控制,它提供更细粒度的缓冲区管理,适合对实时性要求高的场景。

回到顶部