查看: 299|回复: 3

鸿蒙6.1 Audio Kit 系统音效与音量感知实战

[复制链接]
发表于 8 小时前 | 显示全部楼层 |阅读模式
HarmonyOS NEXT 6.1(API 23)对音频套件 Audio Kit 进行了多项实用升级,其中 ArkTS 层可以直接调用的三个新特性——音量变化事件新增 previousVolume 字段、系统音效播放器 SystemSoundPlayer、以及音频渲染器的路由预估时延 getLatency,为音量感知、系统音效管理和音视频同步提供了更精确的控制能力。本文通过一个完整的控制台示例,演示这三个特性的集成方法与关键细节。

项目结构与环境

示例工程 AudioKitDemo 基于 Stage 模型构建,主页面 AudioKitDemo.ets 集中实现了三大交互模块:音量变化监听舱、路由时延诊断舱和系统音效播放舱。工程需要 DevEco Studio 搭配 HarmonyOS SDK API 23,语言使用 ArkTS。项目路由表 main_pages.json 注册了两个页面入口。

核心模块对应三个独立 @Builder 子卡片,数据流通过组件的 @State 变量和私有方法串联。

实战一:音量变化感知(previousVolume)

此前应用监听音量变化只能获得当前音量值,若要知道变化方向和幅度,必须在外部维护上一次音量值。API 23 的 StreamVolumeEvent 新增了可选字段 previousVolume,在回调中直接携带变化前的音量。

注册监听的典型代码如下:
  1. import { audio } from '@kit.AudioKit';
  2. const volMgr: audio.AudioVolumeManager = audio.getAudioManager().getVolumeManager();
  3. volMgr.on('streamVolumeChange', audio.StreamUsage.STREAM_USAGE_MUSIC,
  4.   (event: audio.StreamVolumeEvent) => {
  5.     const prevVol = event.previousVolume ?? -1;
  6.     const currVol = event.volume;
  7.     const direction = (currVol > (event.previousVolume ?? currVol)) ? '⬆️' : '⬇️';
  8.     console.info(`音量变化 ${direction} 旧=${prevVol} 新=${currVol}`);
  9.   }
  10. );
复制代码

要点:previousVolume 可能为 undefined(例如快速设置静音时),建议用空值合并运算符提供默认值。回调参数 updateUi 标记系统是否已显示音量 UI,应用可根据此字段决定是否自行弹窗。

在控制台页面中,我们将上一音量和当前音量分别以紫色和绿色大字显示,并自动附加方向箭头,让开发者直观体验新字段的效果。

实战二:系统音效播放器(SystemSoundPlayer)

系统音效播放器是 API 23 全新引入的能力,专门用于管理拍照快门、录制开始/结束等系统提示音。它提供了完整的生命周期:预加载→播放→卸载→释放,开发者必须在调用 play() 之前调用 load(),使用完毕后依次调用 unload() 和 release() 才能正确释放资源。

创建播放器并播放快门音效的示例:
  1. import { systemSoundManager } from '@kit.AudioKit';
  2. let soundPlayer: systemSoundManager.SystemSoundPlayer | null = null;
  3. try {
  4.   soundPlayer = await systemSoundManager.createSystemSoundPlayer();
  5.   if (!soundPlayer) {
  6.     console.error('createSystemSoundPlayer 返回 null');
  7.     return;
  8.   }
  9.   // 预加载
  10.   await soundPlayer.load(systemSoundManager.SystemSoundType.PHOTO_SHUTTER);
  11.   // 播放
  12.   await soundPlayer.play(systemSoundManager.SystemSoundType.PHOTO_SHUTTER);
  13.   console.info('快门音效播放成功');
  14.   // 卸载并释放
  15.   await soundPlayer.unload(systemSoundManager.SystemSoundType.PHOTO_SHUTTER);
  16.   await soundPlayer.release();
  17.   soundPlayer = null;
  18. } catch (err) {
  19.   console.error(`系统音效异常: ${err.code} - ${err.message}`);
  20. }
复制代码

需要注意:SystemSoundType 目前包含 PHOTO_SHUTTER、RECORD_START、RECORD_STOP 三种类型。load() 和 play() 都是异步操作,建议在初始化页面时预加载,避免用户点击时出现首次加载延迟。如果连续播放同一音效,只需加载一次,但每次播放前确保未卸载。release() 必须最后调用,否则后续无法再使用该实例。

实战三:路由预估时延(getLatency)

音视频精确同步需要知道音频渲染链路的延迟。AudioRenderer 新增的 getLatency 方法可同步返回全链路、纯软件层和纯硬件层的预估时延(毫秒级)。

使用时需注意:仅 Stage 模型可用;必须先调用 start() 后查询;无线设备返回值误差较大;建议只在播放开始时查询一次,避免高频轮询。

集成示例:
  1. import { audio } from '@kit.AudioKit';
  2. async function queryLatency() {
  3.   const opt: audio.AudioRendererOptions = {
  4.     streamInfo: {
  5.       samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
  6.       channels: audio.AudioChannel.CHANNEL_2,
  7.       sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
  8.       encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
  9.     },
  10.     rendererInfo: {
  11.       usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
  12.       rendererFlags: 0
  13.     }
  14.   };
  15.   const renderer = await audio.createAudioRenderer(opt);
  16.   await renderer.start();
  17.   try {
  18.     const latencyAll = renderer.getLatency(audio.AudioLatencyType.LATENCY_TYPE_ALL);
  19.     const latencySW = renderer.getLatency(audio.AudioLatencyType.LATENCY_TYPE_SOFTWARE);
  20.     const latencyHW = renderer.getLatency(audio.AudioLatencyType.LATENCY_TYPE_HARDWARE);
  21.     console.info(`全链路:${latencyAll}ms  软件:${latencySW}ms  硬件:${latencyHW}ms`);
  22.   } catch (err) {
  23.     console.error(`getLatency 失败: ${err.code} - ${err.message}`);
  24.   }
  25. }
复制代码

若未调用 start() 直接查询,会抛出 6800103 错误。此外,精确的 A/V 同步还应配合 getAudioTimestampInfo() 或 getAudioTimestampInfoSync() 接口使用。

总结

本文演示了 HarmonyOS NEXT 6.1 Audio Kit 在 ArkTS 层的三个实用新特性。previousVolume 减少了音量状态管理的复杂度;SystemSoundPlayer 规范了系统音效的生命周期;getLatency 为音视频同步调优提供了数据底座。同时还提及了 NDK 层新增的变声效果 C API,供有 Native 编创需求的开发者参考。这些能力均可直接集成到现有应用中,提升音频特性的精准度和开发效率。
回复

使用道具 举报

发表于 8 小时前 | 显示全部楼层

Re: 鸿蒙6.1 Audio Kit 系统音效与音量感知实战

感谢楼主的详细分享!这三个新特性都很实用,尤其是 `previousVolume` 字段,之前确实需要在外部手动记录上一音量值来做变化方向判断,现在 API 直接带出来方便多了。还有 `SystemSoundPlayer` 的生命周期管理提醒很关键,没接触过的话容易漏掉 `load` 和 `release` 的顺序。 想请教一个问题:在实际项目中,如果频繁切换系统音效(比如连续拍照),你是倾向于每次调用前都 `load` 一次,还是预先加载好所有类型、只播放不卸载?频繁的 `load`/`unload` 会不会对低端设备的性能有明显影响?
回复 支持 反对

使用道具 举报

发表于 8 小时前 | 显示全部楼层

Re: 鸿蒙6.1 Audio Kit 系统音效与音量感知实战

感谢楼主分享这么详细的实战经验!之前一直苦恼于音量变化只能拿到当前值,需要自己存旧值,现在有了previousVolume确实方便多了。系统音效播放器的生命周期管理写得非常清楚,之前自己尝试时总是忘记release导致资源泄漏。getLatency的注意事项也很有用。另外想请教一下,如果连续播放同一系统音效(比如连拍),是否需要每次play前都先load呢?还是可以只加载一次然后多次play?多谢!
回复 支持 反对

使用道具 举报

发表于 8 小时前 | 显示全部楼层

Re: 鸿蒙6.1 Audio Kit 系统音效与音量感知实战

感谢楼主分享的实战经验!鸿蒙6.1 Audio Kit这三个新特性确实很实用,特别是 `previousVolume` 字段,之前做音量变化追踪时还得自己维护旧值,现在直接回调里就能拿到,省事多了。系统音效播放器那个生命周期(load→play→unload→release)的提醒也很关键,之前我试过忘了 release 导致后续播放报错,血的教训😂。另外 `getLatency` 对于音视频同步场景应该能省不少调试功夫,不过楼主提到无线设备误差大,这个有没有什么更稳定的替代方案?期待后续更多类似的技术分享!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-21 18:51 , Processed in 0.025845 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部