当前位置: 首页 > news >正文

鸿蒙(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'; // 导入BusinessErrorlet 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 万款的应用。那么这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行! 自↓↓↓拿

相关文章:

  • 【电路笔记】-无源衰减器
  • websocket投送
  • Go语言本机多版本管理
  • 鸿蒙AI功能开发【hiai引擎框架-人脸比对】 基础视觉服务
  • 【OpenCV C++20 学习笔记】霍夫圆形变换-Hough Circle Transform
  • Can‘t import openai in Node
  • 2024 某公司python 面试真题
  • C# Unity 面向对象补全计划 泛型约束
  • 代码随想录算法训练营第三十九天 | 322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包理论基础、背包问题总结
  • 到底是低度还是高度的白酒对身体的伤害更大?
  • Linux网络编程3
  • 20240807 每日AI必读资讯
  • UNI-APP_点击,长按,触摸,结束触摸事件
  • 【C/C++笔记】:易错难点3 (二叉树)
  • Redis哨兵集群部署 一主两从三哨兵以及持久化
  • php的引用
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • Git初体验
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Java 内存分配及垃圾回收机制初探
  • JAVA 学习IO流
  • JavaScript实现分页效果
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 学习Vue.js的五个小例子
  • 因为阿里,他们成了“杭漂”
  • 优秀架构师必须掌握的架构思维
  • 源码安装memcached和php memcache扩展
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • 容器镜像
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • $refs 、$nextTic、动态组件、name的使用
  • (C语言)逆序输出字符串
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (pycharm)安装python库函数Matplotlib步骤
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (三十)Flask之wtforms库【剖析源码上篇】
  • (十二)Flink Table API
  • (转)VC++中ondraw在什么时候调用的
  • (转)拼包函数及网络封包的异常处理(含代码)
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • .bat批处理(一):@echo off
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .Net Core 中间件与过滤器
  • .NET Core跨平台微服务学习资源
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .NET 的程序集加载上下文
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .NET/C# 使用反射注册事件
  • .net中的Queue和Stack
  • [ CTF ]【天格】战队WriteUp- 2022年第三届“网鼎杯”网络安全大赛(青龙组)
  • [ 数据结构 - C++] AVL树原理及实现