HarmonyOS 鸿蒙Next PC音频控制最佳实践

HarmonyOS 鸿蒙Next PC音频控制最佳实践

1. API 使用指导

系统提供了多样化的API,根据不同的开发语言以及不同的音频使用场景,主要介绍以下三种API:

  • AudioRenderer:用于音频输出的ArkTS/JS API,仅支持PCM格式,需要应用持续写入音频数据进行工作。应用可以在输入前添加数据预处理,如设定音频文件的采样率、位宽等。
  • OHAudio:用于音频输出的Native API,此API在设计上实现归一,同时支持普通音频通路和低时延通路。仅支持PCM格式,适用于依赖Native层实现音频输出功能的场景。
  • AVPlayer:用于音频播放的ArkTS/JS API,集成了流媒体和本地资源解析、媒体资源解封装、音频解码和音频输出功能。可用于直接播放mp3、m4a等格式的音频文件,不支持直接播放PCM格式文件。

参考链接:音频播放开发概述

2. 音频控制及示例

2.1 选择合适的音频流

音频流类型是定义音频数据播放和录制方式的关键属性。对于音频流,其类型由StreamUsage确定。

下表中列举常用的播放音频流类型,由StreamUsage定义:

音频流使用类型(StreamUsage) 适用场景
STREAM_USAGE_MOVIE 适用于播放短视频、电影、电视剧等各类视频内容。
STREAM_USAGE_AUDIOBOOK 适用于播放有声读物、新闻、播客等。
STREAM_USAGE_GAME 适用于游戏内配乐、配音,游戏类型音频流播放时,后台播放的音乐不会被打断;游戏内语音,建议使用STREAM_USAGE_VOICE_COMMUNICATION。
STREAM_USAGE_NAVIGATION 适用于导航场景的语音播报功能。
STREAM_USAGE_VOICE_MESSAGE 适用于播放语音短消息。
STREAM_USAGE_VOICE_COMMUNICATION 适用于VoIP语音通话。
STREAM_USAGE_ALARM 适用于播放闹铃。
STREAM_USAGE_RINGTONE 适用于VoIP来电响铃等。
STREAM_USAGE_NOTIFICATION 适用于播放通知音、提示音。

参考链接:播放音频流类型

2.1.1 ArkTS侧应用适配, 使用AudioRenderer开发音频播放功能:

可以在调用createAudioRenderer获取音频渲染器时,传入对应的StreamUsage。

createAudioRenderer的参数options类型为AudioRendererOptions,包含AudioRendererInfo渲染器信息,使用AudioRendererInfo.usage可指定StreamUsage音频流类型。

2.1.2 C侧应用适配,使用OHAudio开发音频播放功能:

可以在调用OH_AudioStreamBuilder_SetRendererInfo()接口时,传入对应的OH_AudioStream_Usage指定音频流类型。

2.1.3 ArkTS侧应用,使用AVPlayer开发全量的音频播放功能:

可以通过设置AVPlayer的属性audioRendererInfo来实现。AVPlayer.audioRendererInfo的类型为audio.AudioRendererInfo。使用AudioRendererInfo.usage可指定StreamUsage音频流类型。

2.1.4 C侧应用,使用AVPlayer开发全量的音频播放功能:

可以在调用OH_AVPlayer_SetAudioRendererInfo接口时,传入对应的OH_AudioStream_Usage指定音频流类型。

参考链接:设置音频流类型

2.2 音量控制

播放流类型(StreamUsage)决定了音频流所属的音量类型(AudioVolumeType),各类音量类型(如媒体、铃声、闹钟、通话等)拥有独立的音量值,在用户界面上可独立调节,相互之间不会影响。

常见的播放流类型与音量类型的对应关系为:

音频流使用类型(StreamUsage) 音量类型(AudioVolumeType)
MUSIC、MOVIE、AUDIOBOOK、GAME 媒体音量(MEDIA)
RINGTONE、NOTIFICATION 铃声音量(RINGTONE)
VOICE_COMMUNICATION 通话音量(VOICE_CALL)
ALARM 闹钟音量(ALARM)

2.2.1 应用获取音量大小

2.2.1.1 TS侧应用获取当前音频流的音量

获取当前音量值,同步返回音量大小,音量范围[0.0-1.0],默认值为1.0,非系统音量。

import { BusinessError } from '[@kit](/user/kit).BasicServicesKit'; 
try { 
  let value: number = audioRenderer.getVolume(); 
  console.info(`Indicate that the volume is obtained ${value}.`); 
} catch (err) { 
  let error = err as BusinessError; 
  console.error(`Failed to obtain the volume, error ${error}.`); 
}

参考API:getVolume

2.2.1.2 C侧应用获取当前音量

获取当前音频流音量值,其中volume为指向一个获取当前音频流音量值的指针,音量值的范围是[0.0, 1.0]。

OH_AudioStream_Result OH_AudioRenderer_GetVolume(OH_AudioRenderer *renderer, float *volume)

参考API:OH_AudioRenderer_GetVolume()

2.2.2 应用调整应用音量大小

2.2.2.1 使用AVPlayer设置音频流音量的示例代码如下:

let volume = 1.0;  // 指定的音量大小,取值范围为[0.00-1.00],1表示最大音量
avPlayer.setVolume(volume);

2.2.2.2 TS侧应用设置音频流音量的示例代码:

import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';

audioRenderer.setVolume(0.5).then(() => {  // 音量范围为[0.0-1.0]。
  console.info('Invoke setVolume succeeded.');
}).catch((err: BusinessError) => {   
  console.error(`Invoke setVolume failed, code is ${err.code}, message is ${err.message}`);
});

参考文档:音频流音量

2.2.2.3 C侧应用设置音频流音量的示例代码 :

OH_AudioStream_Result OH_AudioRenderer_SetVolume (OH_AudioRenderer *renderer, float volume)

参数:

参数名 描述
renderer 指向OH_AudioStreamBuilder_GenerateRenderer创建的音频流实例。
volume 设置当前音频流音量,音量值的范围是[0.0, 1.0]。

返回:

104.png


参考API:[OH_AudioRenderer_SetVolume()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiorenderer-h#oh_audiorenderer_setvolume)。

## 2.3 音频焦点策略

系统预设了默认的音频焦点策略,根据音频流的类型及启动的先后顺序,对所有播放和录制音频流进行统一管理。

在启动播放或录制功能前,应用需要先申请音频焦点;而在播放或录制结束后,应适时释放音频焦点。在播放或录制的过程中,可能会因其他音频流的介入而失去焦点,此时,应用需要采取相应措施处理音频焦点变化。

- 在启动播放或录制操作前,应根据音频的具体用途,选择并使用合适的音频流类型,即准确设置StreamUsage或SourceType。
- 在播放或录制的过程中,需监听音频焦点事件,并在接收到音频焦点中断事件(InterruptEvent)时,采取相应的处理措施。
- 若应用程序有意主动管理音频焦点,可使用音频会话(AudioSession)相关的接口进行操作。

参考文档:[音频焦点和音频会话介绍](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/audio-playback-concurrency)。

### 2.3.1 TS侧应用处理音频焦点变化的指导

使用AudioRenderer开发音频播放功能,可以调用on('audioInterrupt')接口,监听音频焦点事件InterruptEvent。

```typescript
audioRenderer.on('audioInterrupt', (interruptEvent: audio.InterruptEvent) => {
  switch (interruptEvent.hintType) {
    case audio.InterruptHint.INTERRUPT_HINT_PAUSE: // 音频流已被暂停,临时失去焦点,应用更新UX界面状态
      break;
    case audio.InterruptHint.INTERRUPT_HINT_STOP: // 音频流已被停止,永久失去焦点,若想恢复渲染,需用户主动触发
      break;
    case audio.InterruptHint.INTERRUPT_HINT_RESUME: // 音频已经恢复,应用更新UX界面状态等
      break;
    case audio.InterruptHint.INTERRUPT_HINT_DUCK:
      break;
    case audio.InterruptHint.INTERRUPT_HINT_UNDUCK:
      break;
  }
})

参考API:on(‘audioInterrupt’)

2.3.2 C侧应用处理音频焦点变化的指导

使用OHAudio开发音频播放功能(C/C++),可以调用OH_AudioStreamBuilder_SetRendererCallback接口,监听音频焦点事件OH_AudioRenderer_OnInterruptEvent。

int32_t MyOnInterruptEvent(OH_AudioRenderer* renderer, void* userData, OH_AudioInterrupt_ForceType type,OH_AudioInterrupt_Hint hint) {
  switch(hint) {
    case AUDIOSTREAM_INTERRUPT_HINT_RESUME:             // 音频已经恢复,应用更新UX界面状态等             
      break;
    case AUDIOSTREAM_INTERRUPT_HINT_PAUSE:             // 音频流已被停止,永久失去焦点,若想恢复渲染,需用户主动触发             
      break;
    case AUDIOSTREAM_INTERRUPT_HINT_STOP:             // 音频流已被暂停,临时失去焦点,应用更新UX界面状态             
      break;
    case AUDIOSTREAM_INTERRUPT_HINT_DUCK:              
      break;
    case  AUDIOSTREAM_INTERRUPT_HINT_UNDUCK:              
      break;
  }
}

2.4 音频设备变更

系统会根据音频流的类型,指定默认的输出设备,典型的场景如下:

  • 音乐(Music)类型音频流的默认输出设备为扬声器。
  • 语音通话(VoiceCommunication)类型音频流的默认输入设备为麦克风,默认输出设备为听筒。
  • 闹铃(Alarm)类型音频流的默认输出设备为扬声器。若先连接蓝牙耳机,再开始播放Alarm音频,则扬声器和蓝牙耳机会同时播放。

2.4.1 TS侧应用 处理音频设备变更的指导

2.4.1.1 指定默认发声设备

import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';

// 可注明下本接口主要服务于语音消息和语音通话场景,允许在AudioRenderer创建以后的任何时间被调用。
// 未播放时调用,系统会记录应用设置的默认本机内置发声设备,当应用启动播放时从设置的默认本机内置发声设备发声。
// 正在播放时调用,在没有外接设备如蓝牙耳机/有线耳机,系统会立即切换到设置的默认本机内置发声设备发声;否则系统会先记录应用设置的默认本机内置发声设备,等外接设备移除后再切换到设置的默认本机内置发声设备发声。
audioRenderer.setDefaultOutputDevice(audio.DeviceType.SPEAKER).then(() => {
  console.info('setDefaultOutputDevice Success!');
}).catch((err: BusinessError) => {
  console.error(`setDefaultOutputDevice Fail: ${err}`);
});

参考API:setDefaultOutputDevice

2.4.1.2 处理音频设备变更

(audioRenderer as audio.AudioRenderer).on('outputDeviceChangeWithInfo', 
  async (deviceChangeInfo: audio.AudioStreamDeviceChangeInfo) => {
    switch (deviceChangeInfo.changeReason) {
      case audio.AudioStreamDeviceChangeReason.REASON_OLD_DEVICE_UNAVAILABLE:
        // 响应设备不可用事件,如果应用处于播放状态,应暂停播放,更新UX界面。
        // await audioRenderer.pause();
        break;
      case audio.AudioStreamDeviceChangeReason.REASON_NEW_DEVICE_AVAILABLE:
        // 应用根据业务情况响应设备可用事件。
        break;
      case audio.AudioStreamDeviceChangeReason.REASON_OVERRODE:
        // 应用根据业务情况响应设备强选事件。
        break;
      case audio.AudioStreamDeviceChangeReason.REASON_UNKNOWN:
        // 应用根据业务情况响应未知原因事件。
        break;
    }
  });

触发场景:普通蓝牙设备(耳机、眼镜、音箱、车机等)连接、支持佩戴检测的蓝牙设备(耳机、眼镜等)佩戴、有线设备(3.5mm耳机、Type-C耳机、USB耳机、USB音箱等)插入、分布式设备上线等。

触发场景:普通蓝牙设备(耳机、眼镜、音箱、车机等)断开、支持佩戴检测的蓝牙耳机双耳摘下、支持佩戴检测的蓝牙眼镜摘下、有线设备(3.5mm耳机、Type-C耳机、USB耳机、音箱等)拔出、分布式设备下线等。

触发场景:用户从界面选择切换音频流输出设备、从外设选择接听蜂窝或VoIP来电。

参考文档:音频流输出设备信息

2.4.2 C侧应用 处理音频设备变更的指导

2.4.2.1 指定默认发声设备

OH_AudioStream_Result OH_AudioRenderer_SetDefaultOutputDevice(OH_AudioRenderer* renderer, OH_AudioDevice_Type deviceType)

接口仅适用于音频流为语音消息、VoIP语音通话或者VoIP视频通话的场景使用,可选默认发声设备类型为听筒、扬声器和系统默认设备。

在应用启动播放时,若有外接设备如蓝牙耳机/有线耳机接入,系统优先从外接设备发声;否则系统遵循应用设置的默认本机内置发声设备发声。

2.4.2.2 处理音频设备变更

OH_AudioStream_Result OH_AudioStreamBuilder_SetRendererOutputDeviceChangeCallback(OH_AudioStreamBuilder * builder, OH_AudioRenderer_OutputDeviceChangeCallback callback, void * userData)

// 输出音频流设备变更的回调函数
void (*OH_AudioRenderer_OutputDeviceChangeCallback)(OH_AudioRenderer *renderer, void *userData, OH_AudioStream_DeviceChangeReason reason) {
  switch (reason) {
    case REASON_OLD_DEVICE_UNAVAILABLE: // 旧设备不可用。当报告此原因时,应用程序应考虑暂停音频播放。
    break;
    case REASON_NEW_DEVICE_AVAILABLE: // 新设备可用。
    break;
    case REASON_OVERRODE: // 用户或系统强制选择切换。
    break;
    case REASON_UNKNOWN: //未知原因
    break;
  }
}

更多关于HarmonyOS 鸿蒙Next PC音频控制最佳实践的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

鸿蒙Next PC音频控制可通过AudioManager API实现。关键操作包括:

  1. 获取音频管理器:audioManager.getAudioManager()
  2. 控制音量:audioManager.setVolume(AudioVolumeType.MEDIA, level)
  3. 静音控制:audioManager.mute(AudioVolumeType.MEDIA, muteState)
  4. 监听音频变化:注册VolumeEvent监听器

示例代码片段:

let audioManager = audio.getAudioManager()
audioManager.setVolume(audio.AudioVolumeType.MEDIA, 50)
audioManager.mute(audio.AudioVolumeType.MEDIA, false)

注意音频权限声明: ohos.permission.ACCESS_NOTIFICATION_POLICY

更多关于HarmonyOS 鸿蒙Next PC音频控制最佳实践的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对HarmonyOS Next PC音频控制的最佳实践,以下是关键要点总结:

  1. API选择
  • 对于PCM格式音频输出,推荐使用AudioRenderer(ArkTS/JS)或OHAudio(Native API)
  • 播放MP3/M4A等压缩格式,使用AVPlayer更高效
  1. 音频流管理
  • 根据场景选择正确的StreamUsage类型(如STREAM_USAGE_MUSIC用于媒体播放)
  • 示例:创建AudioRenderer时指定流类型:
let options = {
  rendererInfo: {
    usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
    // 其他参数...
  }
};
audio.createAudioRenderer(options);
  1. 音量控制
  • 音量类型与流类型自动关联(如MEDIA对应音乐流)
  • 设置音量范围0.0-1.0:
audioRenderer.setVolume(0.5).then(() => {
  console.info('Volume set successfully');
});
  1. 焦点管理
  • 必须处理中断事件:
audioRenderer.on('audioInterrupt', (event) => {
  if(event.hintType === audio.InterruptHint.INTERRUPT_HINT_PAUSE) {
    // 处理暂停逻辑
  }
});
  1. 设备切换
  • 监听设备变更:
audioRenderer.on('outputDeviceChangeWithInfo', (info) => {
  if(info.changeReason === audio.AudioStreamDeviceChangeReason.REASON_OLD_DEVICE_UNAVAILABLE) {
    // 处理设备断开
  }
});
  1. Native开发
  • 使用OH_AudioRenderer_SetVolume()等C接口实现相同功能
  • 设备回调通过OH_AudioStreamBuilder_SetRendererOutputDeviceChangeCallback设置

完整示例可参考官方Demo,关键是要根据音频场景选择合适的流类型,并正确处理中断和设备变更事件以保证用户体验。

回到顶部