鸿蒙(API 12 Beta2版)媒体开发【处理音频焦点事件】

音频打断策略

多音频并发,即多个音频流同时播放。此场景下,如果系统不加管控,会造成多个音频流混音播放,容易让用户感到嘈杂,造成不好的用户体验。为了解决这个问题,系统预设了音频打断策略,对多音频播放的并发进行管控,只有持有音频焦点的音频流才可以正常播放,避免多个音频流无序并发播放的现象出现。

当应用开始播放音频时,系统首先为相应的音频流申请音频焦点,获得焦点的音频流可以播放;若焦点申请被拒绝,则不能播放。在音频流播放的过程中,若被其他音频流打断,则会失去音频焦点。当音频流失去音频焦点时,只能暂停播放。在应用播放音频的过程中,这些动作均由系统自行完成,无需应用主动触发。但为了维持应用和系统的状态一致性,保证良好的用户体验,推荐应用[监听音频打断事件],并在收到音频打断事件([InterruptEvent])时做出相应处理。

为满足应用对多音频并发策略的不同需求,音频打断策略预设了两种焦点模式,针对同一应用创建的多个音频流,应用可通过设置[焦点模式],选择由应用自主管控或由系统统一管控。

音频打断策略决定了应该对音频流采取何种操作,如暂停播放、继续播放、降低音量播放、恢复音量播放等,这些操作可能由系统或应用来执行。音频打断策略预置了两种[打断类型],用于区分音频打断事件(InterruptEvent)的执行者。

焦点模式

音频打断策略预设了两种焦点模式([InterruptMode]):

  • 共享焦点模式(SHARE_MODE):由同一应用创建的多个音频流,共享一个音频焦点。这些音频流之间的并发规则由应用自主决定,音频打断策略不会介入。当其他应用创建的音频流与该应用的音频流并发播放时,才会触发音频打断策略的管控。
  • 独立焦点模式(INDEPENDENT_MODE):应用创建的每一个音频流均会独立拥有一个音频焦点,当多个音频流并发播放时,会触发音频打断策略的管控。

应用可以按需选择合适的焦点模式,在创建音频流时,系统默认采用共享焦点模式,应用可主动设置所需的模式。

设置焦点模式的方法:

  • 若[使用AVPlayer开发音频播放功能],则可以通过修改AVPlayer的[audioInterruptMode]属性进行设置。
  • 若[使用AudioRenderer开发音频播放功能],则可以调用AudioRenderer的[setInterruptMode]函数进行设置。
  • 若[使用OHAudio开发音频播放功能(C/C++)],则可以调用[OH_AudioStreamBuilder_SetRendererInterruptMode]函数进行设置。

打断类型

音频打断策略(包括两种焦点模式)决定了应该对各个音频流采取何种操作,如暂停播放、继续播放、降低音量播放、恢复音量播放等。而针对这些操作的执行过程,根据执行者的不同,可以分为两种打断类型([InterruptForceType]):

  • 强制打断类型(INTERRUPT_FORCE):由系统进行操作,强制打断音频播放。
  • 共享打断类型(INTERRUPT_SHARE):由应用进行操作,可以选择打断或忽略。

对于音频打断策略的执行,系统默认采用强制打断类型(INTERRUPT_FORCE),应用无法更改。但对于一些策略(如继续播放等),系统无法强制执行,所以这两种打断类型均可能出现。应用可根据音频打断事件(InterruptEvent)的成员变量forceType的值,获取该事件采用的打断类型。

在应用播放音频的过程中,系统自动为音频流执行申请焦点、持有焦点、释放焦点等动作,当发生音频打断事件时,系统强制对音频流执行暂停、停止、降低音量、恢复音量等操作,并向应用发送音频打断事件(InterruptEvent)回调。由于系统会强制改变音频流状态,为了维持应用和系统的状态一致性,保证良好的用户体验,推荐应用[监听音频打断事件],并在收到音频打断事件(InterruptEvent)时做出相应处理。

对于一些系统无法强制执行的操作(例如音频流继续播放的场景),会向应用发送包含了共享打断类型的音频打断事件,由应用自行执行相应操作,此时应用可以选择执行或忽略,系统不会干涉。

监听音频打断事件

在应用播放音频时,推荐应用监听音频打断事件,当音频打断事件发生时,系统会根据预设策略,对音频流做出相应的操作,并针对状态发生改变的音频流,向所属的应用发送音频打断事件。

应用收到音频打断事件后,需根据其内容提示,做出相应的处理,避免出现应用状态与预期效果不一致的问题。

监听音频打断事件的方法:

  • 若[使用AVPlayer开发音频播放功能],则可以调用AVPlayer的[on('audioInterrupt')]函数进行监听,当收到音频打断事件(InterruptEvent)时,应用需根据其内容,做出相应的调整。
  • 若[使用AudioRenderer开发音频播放功能],则可以调用AudioRenderer的[on('audioInterrupt')]函数进行监听,当收到音频打断事件(InterruptEvent)时,应用需根据其内容,做出相应的调整。
  • 若[使用OHAudio开发音频播放功能(C/C++)],则可以调用[OH_AudioStreamBuilder_SetRendererCallback]接口注册监听焦点回调事件,当收到音频打断事件(OH_AudioRenderer_OnInterruptEvent)时,应用需根据其内容,做出相应的调整。

为了带给用户更好的体验,针对不同的音频打断事件内容,应用需要做出相应的处理操作。此处以使用AudioRenderer开发音频播放功能为例,展示推荐应用采取的处理方法,提供伪代码供开发者参考(若使用AVPlayer开发音频播放功能或者使用OHAudio接口开发音频播放器功能,处理方法类似),具体的代码实现,开发者可结合实际情况编写,处理方法也可自行调整。

import { audio } from '@kit.AudioKit';  // 导入audio模块
import { BusinessError } from '@kit.BasicServicesKit'; // 导入BusinessError

let isPlay: boolean; // 是否正在播放,实际开发中,对应与音频播放状态相关的模块
let isDucked: boolean; //是否降低音量,实际开发中,对应与音频音量相关的模块
let started: boolean; // 标识符,记录"开始播放(start)"操作是否成功

async function onAudioInterrupt(): Promise<void> {
  // 此处以使用AudioRenderer开发音频播放功能举例,变量audioRenderer即为播放时创建的AudioRenderer实例。
  audioRenderer.on('audioInterrupt', async(interruptEvent: audio.InterruptEvent) => {
    // 在发生音频打断事件时,audioRenderer收到interruptEvent回调,此处根据其内容做相应处理
    // 1. 可选:读取interruptEvent.forceType的类型,判断系统是否已强制执行相应操作。
    // 注:默认焦点策略下,INTERRUPT_HINT_RESUME为INTERRUPT_SHARE类型,其余hintType均为INTERRUPT_FORCE类型。因此对forceType可不做判断。
    // 2. 必选:读取interruptEvent.hintType的类型,做出相应的处理。
    if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT_FORCE) {
      // 强制打断类型(INTERRUPT_FORCE):音频相关处理已由系统执行,应用需更新自身状态,做相应调整
       switch (interruptEvent.hintType) {
        case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
          // 此分支表示系统已将音频流暂停(临时失去焦点),为保持状态一致,应用需切换至音频暂停状态
          // 临时失去焦点:待其他音频流释放音频焦点后,本音频流会收到resume对应的音频打断事件,到时可自行继续播放
          isPlay = false; // 此句为简化处理,代表应用切换至音频暂停状态的若干操作
          break;
        case audio.InterruptHint.INTERRUPT_HINT_STOP:
          // 此分支表示系统已将音频流停止(永久失去焦点),为保持状态一致,应用需切换至音频暂停状态
          // 永久失去焦点:后续不会再收到任何音频打断事件,若想恢复播放,需要用户主动触发。
          isPlay = false; // 此句为简化处理,代表应用切换至音频暂停状态的若干操作
          break;
        case audio.InterruptHint.INTERRUPT_HINT_DUCK:
          // 此分支表示系统已将音频音量降低(默认降到正常音量的20%),为保持状态一致,应用需切换至降低音量播放状态
          // 若应用不接受降低音量播放,可在此处选择其他处理方式,如主动暂停等
          isDucked = true; // 此句为简化处理,代表应用切换至降低音量播放状态的若干操作
          break;
        case audio.InterruptHint.INTERRUPT_HINT_UNDUCK:
          // 此分支表示系统已将音频音量恢复正常,为保持状态一致,应用需切换至正常音量播放状态
          isDucked = false; // 此句为简化处理,代表应用切换至正常音量播放状态的若干操作
          break;
        default:
          break;
      }
    } else if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT_SHARE) {
      // 共享打断类型(INTERRUPT_SHARE):应用可自主选择执行相关操作或忽略音频打断事件
      switch (interruptEvent.hintType) {
        case audio.InterruptHint.INTERRUPT_HINT_RESUME:
          // 此分支表示临时失去焦点后被暂停的音频流此时可以继续播放,建议应用继续播放,切换至音频播放状态
          // 若应用此时不想继续播放,可以忽略此音频打断事件,不进行处理即可
          // 继续播放,此处主动执行start(),以标识符变量started记录start()的执行结果
          await audioRenderer.start().then(() => {
            started = true; // start()执行成功
          }).catch((err: BusinessError) => {
            started = false; // start()执行失败
          });
          // 若start()执行成功,则切换至音频播放状态
          if (started) {
            isPlay = true; // 此句为简化处理,代表应用切换至音频播放状态的若干操作
          } else {
            // 音频继续播放执行失败
          }
          break;
        default:
          break;
      }
   }
  });
}

典型场景

以下列举一些典型的焦点适配场景。

先播应用类型 推荐流类型 后播应用类型 推荐流类型 推荐体验 适配方案
视频 STREAM_USAGE_MOVIE 闹铃 STREAM_USAGE_ALARM 闹铃响起后,视频暂停播放;闹钟结束后,视频继续播放。 注册焦点事件监听,接收到INTERRUPT_HINT_PAUSE事件时,直接暂停视频播放,并更新UI界面。当闹铃结束后,视频应用接收到INTERRUPT_HINT_RESUME事件,重新启动播放。
音乐 STREAM_USAGE_MUSIC 电话铃声 STREAM_USAGE_RINGTONE 电话响铃后,音乐暂停播放;不接通或者接通再挂断后,音乐恢复播放。 注册焦点事件监听,接收到INTERRUPT_HINT_PAUSE事件时,直接暂停音乐播放,并更新UI界面。当电话结束后,视频应用接收到INTERRUPT_HINT_RESUME事件,重新启动播放。
音乐 STREAM_USAGE_MUSIC 音乐 STREAM_USAGE_MUSIC 后播音乐正常播放,先播音乐应用停止播放,UI变成停止播放状态。 先播应用注册焦点事件监听,接收到INTERRUPT_HINT_STOP事件时,停止音乐播放,并更新UI界面。

最后呢

很多开发朋友不知道需要学习那些鸿蒙技术?鸿蒙开发岗位需要掌握那些核心技术点?为此鸿蒙的开发学习必须要系统性的进行。

而网上有关鸿蒙的开发资料非常的少,假如你想学好鸿蒙的应用开发与系统底层开发。你可以参考这份资料,少走很多弯路,节省没必要的麻烦。由两位前阿里高级研发工程师联合打造的《鸿蒙NEXT星河版OpenHarmony开发文档 》里面内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点

如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。下面是鸿蒙开发的学习路线图。

针对鸿蒙成长路线打造的鸿蒙学习文档。话不多说,我们直接看详细鸿蒙(OpenHarmony )手册(共计1236页)与鸿蒙(OpenHarmony )开发入门视频,帮助大家在技术的道路上更进一步。

  • 《鸿蒙 (OpenHarmony)开发学习视频》
  • 《鸿蒙生态应用开发V2.0白皮书》
  • 《鸿蒙 (OpenHarmony)开发基础到实战手册》
  • OpenHarmony北向、南向开发环境搭建
  • 《鸿蒙开发基础》
  • 《鸿蒙开发进阶》
  • 《鸿蒙开发实战》

总结

鸿蒙---作为国家主力推送的国产操作系统。部分的高校已经取消了安卓课程,从而开设鸿蒙课程;企业纷纷跟进启动了鸿蒙研发。

并且鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,未来将会支持 50 万款的应用。那么这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行! 自↓↓↓拿

相关推荐
安静读书2 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
佑华硬盘拷贝机2 小时前
音频档案批量拷贝:专业SD拷贝机解决方案
音视频
EasyNVR2 小时前
NVR管理平台EasyNVR多个NVR同时管理:全方位安防监控视频融合云平台方案
安全·音视频·监控·视频监控
Random_index3 小时前
#Uniapp篇:支持纯血鸿蒙&发布&适配&UIUI
uni-app·harmonyos
鸿蒙自习室6 小时前
鸿蒙多线程开发——线程间数据通信对象02
ui·harmonyos·鸿蒙
SuperHeroWu78 小时前
【HarmonyOS】鸿蒙应用接入微博分享
华为·harmonyos·鸿蒙·微博·微博分享·微博sdk集成·sdk集成
xcLeigh9 小时前
HTML5超酷响应式视频背景动画特效(六种风格,附源码)
前端·音视频·html5
韩曙亮11 小时前
【FFmpeg】FFmpeg 内存结构 ③ ( AVPacket 函数简介 | av_packet_ref 函数 | av_packet_clone 函数 )
ffmpeg·音视频·avpacket·av_packet_clone·av_packet_ref·ffmpeg内存结构
zhangjr057511 小时前
【HarmonyOS Next】鸿蒙实用装饰器一览(一)
前端·harmonyos·arkts
Industio_触觉智能12 小时前
如何在开源鸿蒙OpenHarmony开启SELinux模式?RK3566鸿蒙开发板演示
openharmony·selinux·开源鸿蒙·鸿蒙开发板·rk3566开发板