写点什么

高德智慧景区随身听播放器框架设计与实现

  • 2020-08-17
  • 本文字数:2893 字

    阅读完需:约 9 分钟

高德智慧景区随身听播放器框架设计与实现

一、背景

“远看山有色,近听水‘ ”,景区语音导览是智慧景区重点业务之一,以用地图可以边走边听景区各景点的语音介绍为主要诉求,实现高德智慧景区地图不仅可以看,还可以听,从而使用户交互体验得到跨越式提高。


我们想要让“技术有温度”,让讲解更加有感情和内涵,最好可以通过讲解构造一个“UGC 景区讲解生态圈”,并且还能帮助讲解创作者有一定的收益,以达到“生态圈的正向循环”,让线上导游“天下没有难做的生意”。


试想一下,当游客走进故宫,这时,高德地图的语音包可以播放:“故宫有 180 万件宝贝,青铜馆、陶瓷馆……”这段话的讲解人,是著名收藏家、古董鉴赏家马未都,是不是更加吸引你关注?另外,当你漫步到延禧宫,语音包则会立刻讲一讲延禧宫与大热的电视剧《延禧攻略》有什么关系,并且有背景音插入,是多么生动形象。


所以,我们开发选型并没有采用传统的 TTS 技术(由文本内容生成机器语音),而是采用了更加通用音频格式(比如 mp3),作为讲解的音频输入源,方便讲解者进行二次创作。本文将简单回顾高德智慧景区随身听播放器的框架设计与实现。

二、架构设计前思考

“夫未战而庙算胜者,得算多也;未战而庙算不胜者,得算少也”,拉开战斗序幕之前我们应该尽量去“庙算”,提前预防和判断并保证技术风险可控,俗称“防火”。“防火”更能看出本事,而“救火”只是能力。开发应尽量做到“不打无准备之仗”。


首先, 如何提升开发和后续迭代效率? 此问题涉及到是纯 Native 开发还是用跨平台混合技术开发。如果用纯 Native,双端开发人力可能会使工作量翻倍,后期可维护性也差,经常需要双端同步拉齐。但纯 Native 开发声音相关的技术方案成熟且风险较小。而用跨平台混合技术开发,优点和缺点正好与单纯 Native 开发相反。经过小组多次技术讨论,看长远利益,最终确定用跨平台技术方案,用该方案虽然技术挑战和风险大(比如需要和跨平台架构支撑团队一起“无中生有”的去打通 JS 的播放链路和各种音频中断能力回调等),但这个方案有个强有力的好处,就是可以“Write Once, Run Everywhere”(这里的 Everywhere 主要是指移动端操作系统),这样可以天然的拉齐双端业务代码能力,大大节约开发周期和人力,对业务快速功能迭代很有优势,再苦再累再难也值得为此努力。


其次, 如何节省 CPU 和内存资源? 做移动开发的同学都知道,音频播放是耗系统软硬件资源的(比如 CPU、内存还有电量等),另外音频播放不仅仅是涉及到单个 App 的事情,还涉及到第三方 App 音频播放的影响(比如系统来电声音焦点抢占,其他音乐 App 播放焦点抢占问题等)。


所以,业务层开发,要对底层播放器提供的播放能力进行二次封装,一是要控制播放器实例的随意创建。二是要处理各第三方 App 的音频播放焦点的申请和释放等逻辑业务。由此可见,搭建一个通用的业务播放器框架势在必行,受益良多。


再次, 如何使业务与音频本身的播放框架能力隔离? 业务多变,而音频播放能力相对来说是稳定的,其基本能力包括但不局限于(首次 &续接)播放,暂停,抢占,打断,音量调节(渐渐变强),物理(如耳机)按键响应,打断后场景恢复,缓存,预加载,强弱网络和播放异常等。这些音频本身的技术能力,最好应该是和纯业务是解耦的,尽量做到“高内聚,低耦合”。


后来,经过深思熟虑,我们认为设计模式中的“ObserverPattern 观察者模式”,比较切合这一技术背景。纯业务和音频框架本身制定通用的接口协议,然后纯业务自由注册监听器到音频播放框架中,根据关心的回调事件自由处理自己的业务,而音频框架本身只做主要的焦点抢占,现场恢复和事件分发等事情,非常符合 SRP 原则(单一职责),后续调试和维护都很方便。


最后,如何实现跨 Page 播放能力?如下图所示:



随身听很多业务是有跨 Page 播放要求的,如果将播放能力直接提供出来,由各个页面的 Page 自己维护,势必会生出很多的 Audio,混乱而且页面相互通信交换信息成本高。后经过讨论,就有了如下图的架构方式设计:



结合跨平台底层播放器的特性,虚拟出来一个 BizService 放在跨平台框架的 Service 容器(和安卓里面的 Service 概念差不多,提供一个无界面的可以处理公共业务的容器)里面,处理 Page 页面业务管理和信息交换以及缓存管理,BizService 只和 BizVoiceMediaCenter 交互管理音频数据,也就是说 BizVoiceMediaCenter 是通用播放器框架对外一个"门面"(Facade 门面设计模式)。BizVoiceMediaCenter 里面会有且仅有一个 VoiceMediaAlbum 实例(播放专辑,提供“上一曲”,“下一曲”,顺序播放,续播等能力)。

三、架构设计和开发

首先,我们先简单看下跨平台底层播放器的生命周期,如下图所示:



熟悉 Native 开发的同学应该知道,跨平台底层播放器的架构和生命周期,和 Android 本身系统播放器非常相似,差异点是音频焦点被抢占和恢复的回调部分,iOS 设备是 onInterrupted,当音频被其他应用打断开始时回调,如电话铃声响起触发此回调(在此回调中保存播放器状态,以便在 onInterruptedEnd 回调中恢复播放)。onInterruptedEnd,当音频被其他应用打断结束时回调,如挂断后触发此回调。而 Android 是 onFocusChanged,当音频焦点变化后回调。当然还有其它一些细微差别,比如双端,播放错误码不一致,播放异常超时逻辑不一致等。但这些都可以通过在业务层构建自己 VoiceMediaPlayer 来拉齐以及处理通用音频焦点抢占和丢失场景的逻辑。


通过上面分析,我们可以大体搭出如下图业务播放器的整体框架图(图中箭头表示数据流的方向)。



我们可以很容易的看出,业务对跨平台底层播放器 Audio 进行了二次封装为 VoiceMediaPlayer,拉齐和处理通用业务场景(比如抢焦点,播放,现场恢复,播放异常,蓝牙或耳机物理按键响应等)。


VoiceMediaPlayer 再上层是 VoiceMediaAlbum(播放专辑),VoiceMediaAlbum 专辑类,主要是处理顺序播放,上一曲,下一曲,整个专辑播放事件(单曲播放信息和进度,整体播放进度透出,自动切换顺序,循环或业务指定下一曲播放等),VoiceMediaAlbum 和业务层的 BizVoiceMediaCenter 打交道,当然 BizVoiceMediaCenter 也可以直接和 VoiceMediaPlayer 打交道,但我们一般不建议这么做,即便是就播放一首音频,我们也希望,把这首音频当成一个专辑来包装和调用(随身听业务也确实是这么做的),这样更加规范和方便以后扩展。


最后,我们来看看整体架构的详细类设计图,如下图所示:


四、落地产出

高德智慧景区随身听播放器框架完成后,很好的支撑了随身听后续版本的开发。此外,后续因业务需求对产品做了多次迭代和变更,但播放器的架构几乎不需要做很大调整和升级(即使后面又增加了离线播放能力),很好验证了其稳定性和可扩展能力。下面一系列图,我们可以看出这颗“种子”(景区随身听播放器框架),开出的美丽的“花”,如下图所示:



以上各个页面底层都共用了这个播放器框架,很方便的实现了音频的跨页面播放和管理,以及异常中断的统一处理。高效满足了相关音频业务的播放能力要求,也为高德智慧景区随身听业务后续迭代开发打下了坚实的地基。


本文转载自公众号高德技术(ID:amap_tech)。


原文链接


https://mp.weixin.qq.com/s/tXXUIb0lRuqoF5aH50shKQ


2020-08-17 10:002236

评论

发布
暂无评论
发现更多内容

疯狂SQL转换系列- SQL for MongoDB

数由科技

sql mongodb dsl moql

ThinkPHP5中如何实现模板完全静态化

北桥苏

thinkphp 模板静态

Selenium 自动化测试如何优雅的解决图片验证码问题

QE_LAB

自动化测试 图片验证码 selenium 登录验证 测试技术

极客公园对话 Zilliz 星爵:大模型时代,需要新的「存储基建」

Zilliz

Milvus Zilliz AIGC 向量数据库 LLMs

音视频八股文(11)-- ffmpeg 音频重采样

福大大架构师每日一题

音视频 ffmpeg

开源赋能 普惠未来 | 软通动力寄语2023开放原子全球开源峰会

开放原子开源基金会

不要焦虑,要不断超越自己 | 社区征文

于仔学技术

认识自己 驱动力量 职场发展 学会思考 三周年征文

九步排查Gateway-Worker启动失败问题

北桥苏

php Gateway thinkphp workerman

RPA技术简介

IT蜗壳-Tango

三周年连更

TPM — 系统安全的基石

鼎道智联

安全

【技术干货】PCB焊盘设计之问题详解

华秋PCB

工具 PCB PCB设计 焊盘 可焊性

TP5.0使用助手函数model出现\common\Model\类不存在

北桥苏

php thinkphp

3 步集成 Terraform + 极狐GitLab CI ,实现基础设施自动化管理

极狐GitLab

ci DevOps 基础设施 Terraform 极狐GitLab

【报告回顾】精、稳、敏、融,步入人民金融时代

易观分析

金融

蚂蚁实时低代码研发和流批一体的应用实践

Apache Flink

大数据 flink 实时计算

uni-app结合PHP实现单用户登陆

北桥苏

php uni-app 单点登录 thinkphp

盘点漏洞种类和代码审计工具

北桥苏

代码审计 漏洞挖掘

DevOps|AGI : 智能时代研发效能平台新引擎(上)

laofo

DevOps 研发效能 AGI AIGC 平台工程

官宣 | 基金会LOGO全新升级 !

开放原子开源基金会

图片文字识别:揭开数字世界的神秘面纱

数据堂

开源赋能 普惠未来|深开鸿寄语2023开放原子全球开源峰会

开放原子开源基金会

高性能存储SIG月度动态:EROFS支持直接索引容器镜像tar包,io_uring将支持并优化NVMe直通

OpenAnolis小助手

操作系统 容器镜像 高性能存储 anck 龙蜥sig

AI 时代的到来,普通前端如何生存下去? | 社区征文

程序员海军

三周年征文

疯狂 SQL 转换系列-SQL for Milvus

数由科技

sql Milvus moql

2023-05-11:给你一个 m x n 的二进制矩阵 grid, 每个格子要么为 0 (空)要么为 1 (被占据), 给你邮票的尺寸为 stampHeight x stampWidth。 我们想将

福大大架构师每日一题

Go 算法 rust

MobTech MobPush|TCP通道和共享链路通道

MobTech袤博科技

ThinkPHP5.1无法记录SQL日志解决思路

北桥苏

php 日志级别 thinkphp

Thinkphp5.1允许uni-app的H5跨域请求接口解决方法

北桥苏

php uni-app 跨域 thinkphp

Nginx 安装配置

芯动大师

nginx web 容器 三周年连更

ChatGPT 再遭禁用 | 人工智能时代下数据安全如何保障

BinTools图尔兹

人工智能 数据库 ChatGPT CloudQuery

高德智慧景区随身听播放器框架设计与实现_架构_高德技术_InfoQ精选文章