HarmonyOS 鸿蒙Next中对音频输入输出设备路由的几点疑问和建议

HarmonyOS 鸿蒙Next中对音频输入输出设备路由的几点疑问和建议 1、在API 20及以前的版本是不支持指定音频输入设备路由的吗?

2、从API 21开始应用可以通过AudioSessionManager的selectMediaInputDevice函数来修改音频输入设备路由,这个是修改整个应用还是整个系统的音频输入设备?能不能单独针对某个AudioCapturer来修改的函数?

3、当AudioCapturer的SourceType为SOURCE_TYPE_VOICE_COMMUNICATION时,AudioSessionManager的selectMediaInputDevice函数不适用,这个限制确实有点奇怪了,因为用这个源主要就是为了使用系统自带的3A算法,而3A算法和具体设备应该关系不大的,最多就是3A算法效果可能差点,但这么一限制应用的灵活度就降低了,所以我觉得可以在开发文档里说明用指定的音频输入设备3A效果可能会差,但系统不应该限制应用使用哪个音频输入设备。

4、从API 12开始应用可以通过AudioRenderer的setDefaultOutputDevice函数来修改音频输出设备路由,但只能修改为听筒或扬声器或系统默认设备,也是无法修改到指定的音频输出设备,确实很不灵活。

综上所述,我认为鸿蒙系统的音频输入输出设备路由很不灵活,存在较大的限制,建议可以参考一下安卓系统的音频输入输出设备路由设计,它可以针对任意一个AudioRecord或AudioTrack设置路由到任意一个指定的音频设备,并且也可以选择让系统去自动路由,也没有3A算法的限制,相对来说还是灵活很多。

以上观点是自己不成熟的一些看法,不当之处请大家批评指正。


更多关于HarmonyOS 鸿蒙Next中对音频输入输出设备路由的几点疑问和建议的实战教程也可以访问 https://www.itying.com/category-93-b0.html

14 回复

开发者你好,

实现音频输出设备切换可以使用AVCastPicker组件,用户通过点击AVCastPicker组件的图标选择音频输出设备。注意,应用在使用AVCastPicker时,需要同时接入AVSession。关于音频输出设备切换的详细介绍请参考:使用通话设备切换组件

更多关于HarmonyOS 鸿蒙Next中对音频输入输出设备路由的几点疑问和建议的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


只能使用AVCastPicker组件吗?我能不能自己去控制呢?相当于自己去实现AVCastPicker组件。

开发者你好,
已连接耳机时,只能通过AVCastPicker切换。

我希望官方能把这个指定音频输入输出设备的api重新规划一下,现在这个音频设备路由感觉非常混乱,不够清晰,我觉得可以这么设计api:

AudioCapturer.setPreferredInputDevice(AudioInputDeviceDescriptor); //设置首选音频输入设备。

AudioCapturer.setPreferredInputDevice(null); //取消首选音频输入设备,改为自动路由。

AudioRenderer.setPreferredOutputDevice(AudioOutputDeviceDescriptor); //设置首选音频输出设备。

AudioRenderer.setPreferredOutputDevice(null); //取消首选音频输出设备,改为自动路由。

AudioRenderer.setDefaultOutputDevice(OutputDevice.*); //修改自动路由的倾向设备。

AudioSessionManager.setPreferredInputDevice(AudioInputDeviceDescriptor); //设置整个应用的首选音频输入设备。

AudioSessionManager.setPreferredInputDevice(null); //取消整个应用的首选音频输入设备,改为自动路由。

AudioSessionManager.setPreferredOutputDevice(AudioInputDeviceDescriptor); //设置整个应用的首选音频输出设备。

AudioSessionManager.setPreferredOutputDevice(null); //取消整个应用的首选音频输出设备,改为自动路由。

开发者你好,

1、是的,selectMediaInputDevice在api21提供可用,之前的版本不可用。

2、selectMediaInputDevice设置的是当前应用,可用来实现当前app某个AudioCapturer流的输入设备。

3、3A算法,指声学回声消除(Acoustic Echo Cancellation, AEC)、背景噪声抑制(Active Noise Control, ANC)、自动增益控制(Automatic Gain Control, AGC)三种音频处理算法。目前系统3A算法在SOURCE_TYPE_VOICE_COMMUNICATION才生效,若有特殊诉求可反馈评估。

4、setDefaultOutputDevice目前只能切换扬声器、听筒、系统默认,切换指定设备可以使用AVCastPicker

如有需求,请问您是在什么样的业务场景中使用该能力,交互流程是怎样的,在哪一个环节遇到了问题?方便说明能力不满足可能带来的影响:什么时间用到?是否高频?有无三方库可以做到?若提供该能力,是否会造成大工作量返工?请您注意提供的内容不要包含您或第三方的非公开信息,如给您带来不便,敬请谅解。

1、我的是在使用3A算法的同时,还可以手动指定音频输入设备。 2、AVCastPicker能控制AudioCapturer和AudioRenderer的路由设备吗?

开发者你好, 感谢您的意见。

  1. selectMediaInputDevice不适用于VoIP通话录音。
  2. AVCastPicker仅支持切换输出设备切换,不支持录音设备切换。

如有需求,请问您是在什么样的业务场景中使用该能力,交互流程是怎样的,在哪一个环节遇到了问题?方便说明能力不满足可能带来的影响:什么时间用到?是否高频?有无三方库可以做到?若提供该能力,是否会造成大工作量返工?请您注意提供的内容不要包含您或第三方的非公开信息,如给您带来不便,敬请谅解。

例如,我在用VoIP通话,我连接了蓝牙耳机,正常应该用蓝牙耳机来录音和播放,中途我可能突然想用听筒或扬声器播放了,但是录音我还是保持用蓝牙耳机,这个要怎么实现呢?

尊敬的开发者,您好!您的问题已受理,请您耐心等待,感谢您的理解与支持!

以下是针对您关于鸿蒙音频设备路由问题的专业解答:

  1. API 20 及更早版本的设备路由支持

在 API 20 及之前的鸿蒙版本中,系统不支持应用主动指定音频输入设备路由。应用只能使用系统默认的音频输入设备,无法通过编程方式干预路由选择。

  1. API 21 的 selectMediaInputDevice 函数作用范围

作用范围:AudioSessionManager.selectMediaInputDevice修改的是当前应用的全局音频输入路由,而非整个系统或其他应用的路由。

设备级控制:目前鸿蒙 没有提供针对单个 AudioCapturer实例设置独立路由的接口。所有通过当前应用创建的音频采集器会共用同一输入设备。

  1. VOICE_COMMUNICATION 源类型的限制

限制机制:当 AudioCapturer的 SourceType设置为 SOURCE_TYPE_VOICE_COMMUNICATION时,系统会强制启用内置的 3A 算法(回声消除/降噪等),该算法与硬件驱动层深度耦合。

设计考量:

3A 算法需要针对特定麦克风的声学特性进行校准,随意切换设备可能导致算法失效

语音通信场景对延迟和稳定性要求极高,统一路由可避免设备切换时的中断

建议方案:

对于需要灵活设备选择的场景,可使用 SOURCE_TYPE_MIC替代(但需自行实现 3A 处理)

通过 AudioDeviceDescriptor获取设备能力信息,动态提示用户设备兼容性

  1. 输出设备路由的灵活性改进

当前限制:AudioRenderer.setDefaultOutputDevice仅支持三种预设路由:

// 可用选项示例
audioRenderer.setDefaultOutputDevice(OutputDevice.SPEAKER); // 扬声器
audioRenderer.setDefaultOutputDevice(OutputDevice.EARPIECE); // 听筒
audioRenderer.setDefaultOutputDevice(OutputDevice.DEFAULT); // 系统默认

扩展建议:可通过监听设备连接事件实现半自动路由:

audioManager.on('deviceChange', (deviceChanged: audio.DeviceChangeAction) => {
  if (deviceChanged.type === audio.DeviceChangeType.CONNECT) {
    // 检测到蓝牙设备自动切换
    if (deviceChanged.device.type === audio.DeviceType.BLUETOOTH_A2DP) {
      audioRenderer.setDefaultOutputDevice(OutputDevice.BLUETOOTH);
    }
  }
});

系统设计对比与演进建议

特性 鸿蒙当前实现 Android 实现
输入设备粒度 应用级全局设置 支持单 AudioRecord 指定
输出设备指定 仅预置设备 支持任意 AudioTrack 路由
3A 算法耦合度 与路由强绑定 可独立配置

演进建议:

在后续 API 版本中开放 AudioCapturer.setInputDevice(deviceId)接口

为 3A 算法增加设备兼容性模式,允许非校准设备降级使用

扩展输出设备枚举值,支持蓝牙/USB 等设备 ID 直选

1、audioRenderer.setDefaultOutputDevice(OutputDevice.BLUETOOTH);这个代码目前是无法使用的。

2、我觉得你的演进建议非常好,希望能得到官方的支持,同时我也希望官方能把这个指定音频输入输出设备的api重新规划一下,现在这个音频设备路由感觉非常混乱,不够清晰,我觉得可以这么设计api:

  • AudioCapturer.setPreferredInputDevice(AudioInputDeviceDescriptor); //设置首选音频输入设备。
  • AudioCapturer.setPreferredInputDevice(null); //取消首选音频输入设备,改为自动路由。
  • AudioRenderer.setPreferredOutputDevice(AudioOutputDeviceDescriptor); //设置首选音频输出设备。
  • AudioRenderer.setPreferredOutputDevice(null); //取消首选音频输出设备,改为自动路由。
  • AudioRenderer.setDefaultOutputDevice(OutputDevice.*); //修改自动路由的倾向设备。
  • AudioSessionManager.setPreferredInputDevice(AudioInputDeviceDescriptor); //设置整个应用的首选音频输入设备。
  • AudioSessionManager.setPreferredInputDevice(null); //取消整个应用的首选音频输入设备,改为自动路由。
  • AudioSessionManager.setPreferredOutputDevice(AudioInputDeviceDescriptor); //设置整个应用的首选音频输出设备。
  • AudioSessionManager.setPreferredOutputDevice(null); //取消整个应用的首选音频输出设备,改为自动路由。

鸿蒙Next的音频路由基于分布式软总线实现,支持动态发现与切换设备。音频框架采用统一的路由策略管理多设备协同,通过AudioRoutingManager接口可查询与选择输入输出节点。系统根据设备优先级、时延及策略自动优选路由,应用可通过监听设备连接状态变化获取路由更新。

  1. 在API 20及以前版本,确实不支持通过公开API指定音频输入设备路由,系统会根据默认策略进行路由。

  2. 从API 21开始,AudioSessionManager.selectMediaInputDevice函数修改的是整个应用的媒体类音频输入路由,而不是整个系统。目前没有针对单个AudioCapturer修改输入设备的独立函数,该设置会作用于应用内同类型的音频采集会话。

  3. 关于SOURCE_TYPE_VOICE_COMMUNICATION源的限制:该源类型与系统通信路由及底层信号处理管线强关联,为确保通话质量的稳定性和3A算法处理的一致性,系统固定了其设备路由策略。这是基于典型通信场景的设计权衡。

  4. AudioRenderer.setDefaultOutputDevice函数的设计主要用于在有限的常用设备(听筒、扬声器、默认设备)间切换,以满足如媒体播放免提切换等常见场景。目前不支持路由到任意指定的音频输出设备。

当前HarmonyOS的音频路由管理更侧重于保障核心场景的稳定体验和系统功耗管理,在设备选择的灵活性上确实有明确边界。你的建议已反映出对更细粒度控制的需求,这对于复杂音频应用开发是合理的。系统后续版本可能会在能力开放与系统管控间做出进一步优化。

回到顶部