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.1ArkTS侧应用适配, 使用AudioRenderer开发音频播放功能:

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

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

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

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

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

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

2.1.4C侧应用,使用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.1TS侧应用获取当前音频流的音量

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

import { BusinessError } from '@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.2C侧应用获取当前音量

获取当前音频流音量值,其中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.2TS侧应用设置音频流音量的示例代码:

import { BusinessError } from '@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.3C侧应用设置音频流音量的示例代码 :

OH_AudioStream_Result OH_AudioRenderer_SetVolume (OH_AudioRenderer *renderer, float volume)

参数:

renderer

指向OH_AudioStreamBuilder_GenerateRenderer创建的音频流实例。

volume

设置当前音频流音量,音量值的范围是[0.0, 1.0]。

返回:

参考API:OH_AudioRenderer_SetVolume()

2.3音频焦点策略

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

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

参考文档:音频焦点和音频会话介绍

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

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

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.2C侧应用处理音频焦点变化的指导

使用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.1TS侧应用 处理音频设备变更的指导

2.4.1.1指定默认发声设备

import { BusinessError } from '@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;
    }
  });
  • REASON_NEW_DEVICE_AVAILABLE:新设备可用。

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

  • REASON_OLD_DEVICE_UNAVAILABLE:旧设备不可用。

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

  • REASON_OVERRODE:用户强制选择设备。

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

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

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

2.4.2.1指定默认发声设备

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

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

OH_AudioStream_Result OH_AudioRenderer_SetDefaultOutputDevice(OH_AudioRenderer* renderer, OH_AudioDevice_Type deviceType)

2.4.2.2处理音频设备变更

OH_AudioStreamBuilder_SetRendererOutputDeviceChangeCallback() 设置输出音频流设备变更的回调。

//设置输出音频流设备变更的回调 
OH_AudioStream_Result OH_AudioStreamBuilder_SetRendererOutputDeviceChangeCallback(OH_AudioStreamBuilder * builder, OH_AudioRenderer_OutputDeviceChangeCallback callback, void * userData) 
//输出音频流设备变更的回调函数 
//OH_AudioRenderer_OutputDeviceChangeCallback,流设备变更原因,枚举常量 
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;
  }
}

3.规范标准

焦点示例标准:

  

incomming当前来的音频流

inproc

预先的音频流

音频类型

VOICE_COMMUNICATION(VOIP通话)

SYSTEM(锁屏、按键)

MUSIC(音频)

ALARM(闹钟)

VOICE_COMMUNICATION

pause inproc

duck incoming

stop inproc

duck incoming

SYSTEM

play both

play both

play both

play both

MUSIC

pause inproc

play both

play both

pause inproc

ALARM

stop inproc

play both

duck incoming

stop inproc

4.适配文档

TS侧应用完整demo参考基于AudioRenderer的音频播控和多场景交互指导,在audio-interaction-master\entry\src\main\module.json5路径下,修改deviceTypes为2in1,即可在PC端运行demo。

4.1音频焦点控制代码示例及视频演示

private interruptCallback: (interruptEvent: audio.InterruptEvent) => void =   (interruptEvent: audio.InterruptEvent) => {
  if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT_FORCE) {
    switch (interruptEvent.hintType) {
      case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
        this.updateIsPlay(false);
        break;
      case audio.InterruptHint.INTERRUPT_HINT_STOP:
        this.updateIsPlay(false);
        this.pause();
        break;
      case audio.InterruptHint.INTERRUPT_HINT_DUCK:
        break;
      case audio.InterruptHint.INTERRUPT_HINT_UNDUCK:
        break;
      default:
        break;
    }
  } else if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT_SHARE) {
    switch (interruptEvent.hintType) {
      case audio.InterruptHint.INTERRUPT_HINT_RESUME:
        this.start();
        break;
      default:
        break;
    }
  }
}

下述视频展示了音频播放过程中闹钟响起时,暂停音乐播放;闹钟结束后,恢复音乐播放的场景:

4.2音频设备变更代码示例及视频演示

private outputDeviceChangeCallback: (deviceChangeInfo: audio.AudioStreamDeviceChangeInfo) => void =   (deviceChangeInfo: audio.AudioStreamDeviceChangeInfo) => {     
  Logger.info(TAG, `DeviceInfo id: ${deviceChangeInfo.devices[0].id}`);     
  Logger.info(TAG, `DeviceInfo name: ${deviceChangeInfo.devices[0].name}`);     
  Logger.info(TAG, `DeviceInfo address: ${deviceChangeInfo.devices[0].address}`);     
  Logger.info(TAG, `Device change reason: ${deviceChangeInfo.changeReason}`);     
  if (deviceChangeInfo.changeReason === audio.AudioStreamDeviceChangeReason.REASON_OLD_DEVICE_UNAVAILABLE) {       
    Logger.info(TAG, `Device change reason: ${deviceChangeInfo.changeReason}`);       
    this.pause();     
  }   
}

下述视频展示了音频播放过程中插入耳机,音乐自动切换播放;拔出耳机,音乐暂停播放的场景:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐