news 2026/10/29 2:08:22

【共创稿事节】给菜谱应用装上嗓子:Core Speech Kit 朗读实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【共创稿事节】给菜谱应用装上嗓子:Core Speech Kit 朗读实战

1、为什么做饭的人不看屏幕

菜谱应用有个天然矛盾:做法是文字,做饭时两只手是脏的、眼睛在锅上。1.0.4 版本我把"朗读文章"做成了首页一级入口,用 Core Speech Kit 的 textToSpeech 把健康饮食文章读出来——边做饭边听。本文记录这套朗读能力的接入过程和几个关键取舍。

2、引擎创建:一次创建,随页销毁

朗读的核心是 TextToSpeechEngine。工程里的创建代码:

import{textToSpeech}from'@kit.CoreSpeechKit'asynccreateSpeechEngine():Promise<textToSpeech.TextToSpeechEngine|undefined>{returnawaittextToSpeech.createEngine({/* 配置 */})}

第一个取舍是引擎的生命周期:跟页面走。ReadingPage 的 aboutToAppear 里 createEngine,aboutToDisappear 里 shutdown——不在全局常驻。理由是朗读是低频场景(用户一天点开一两次),常驻引擎白白占资源;页面级创建的启动延迟在可接受范围。

3、状态机:三种文案背后的三件事

页面上有个 @State speechStatus,用户看到的文案是"点击朗读,收听当前文章 → 正在朗读 → 已停止朗读",出错时显示"朗读不可用:errorCode"。这三态背后是三件必须处理的事:

开始:speakCurrentSection(article) 把当前小节送进引擎。按小节切分而不是整篇送入——整篇长文一次性合成,中途停止和续播都难做;按小节粒度,"读下一段"就是换个入参再 speak。

完成回调:onComplete(response) 里把状态归位。回调驱动是 TTS 的关键——不能假设 speak 之后朗读"应该"结束了,只有回调说了算。

错误回调:错误码直接透给用户(朗读不可用:errorCode)。TTS 在部分设备/语言包缺失时会失败,与其静默失败让用户以为按钮坏了,不如把错误码亮出来——至少知道是能力不可用而不是应用 bug。

4、和菜谱场景的两个细节

朗读起点跟随阅读进度。用户滚到哪一段,点击朗读就从那一段开始——用当前可见小节作 speakCurrentSection 的入参,而不是死板的从头读。

朗读入口放在首页而不是文章页内。首页卡片显示第一篇文章标题,点击直达朗读页。这个入口设计来自场景推演:用户站在灶台前打开应用时,最短路径是"一个动作开始听",任何多一层的选择都会让做饭的人烦。

5、总结

Core Speech Kit 的接入本身不难(createEngine → speak → 回调三件套),难的是把能力嵌进真实场景:引擎生命周期跟页面、按小节切分合成、三态状态机、错误码亮给用户。当用户手上沾着面粉还能"读完"一篇健康文章时,这个功能才算真的可用。

6、参考资料

  • Core Speech Kit 文档(textToSpeech)
  • 工程源码:ReadingPage.ets

#鸿蒙 #HarmonyOS 7(API 26)

7、朗读状态机:比调用本身更重要

接完基础调用后真正花时间的是状态管理。朗读功能有五个状态:空闲、播放中、暂停、合成中(点了播放但声音还没出来)、错误。最容易踩的坑是"合成中":用户连点播放按钮,如果不在合成态拦截重复请求,会叠出多个播放任务,声音直接变混响。我用一个简单的状态门解决:合成中再点播放直接忽略,UI 上按钮显示加载态。

type SpeakState = 'idle' | 'synthesizing' | 'playing' | 'paused' | 'error' // 合成中重复点击直接吞掉,是整个功能最重要的三行代码 if (state === 'synthesizing') return

8、错误处理的三个真实场景

真机上遇到过三类失败,每类的处理不一样,不能一个 catch 包完:

场景现象处理方式
引擎未就绪首启立即播放返回错误延迟到 onPrepared 再播,UI 提示"正在准备"
文本含表情符号静默失败或跳读合成前正则清洗非文本字符
系统朗读服务被占用错误码回调自动降级为静默模式并提示

第三种最隐蔽:测试时好好的,用户后台挂着听书应用就复现了。最后加的降级提示反而是用户好评最多的一处——"至少告诉我为什么没声音"。

9、语速与音色的参数选择

朗读好不好听,参数比引擎重要。我把默认语速调到 0.9 倍(默认 1.0 偏快,菜谱步骤听不清操作量),停顿在步骤编号后自动插入 400 毫秒("第一步"后面停一下,给用户拿调料的时间)。音色选了系统自带的沉稳女声,试过三个声音,这个在厨房嘈杂环境下辨识度最高。

const options = { speed: 0.9, pitch: 1.0, pauseAfterStepMs: 400, voice: 'default-female-calm' }

这些数值没有玄学,全是做饭时实测出来的:0.8 倍太慢让人等得慌,1.0 倍炒菜时跟不上,0.9 刚好;停顿 300 毫秒不够拿东西,500 毫秒节奏断了,400 合适。功能参数要放到真实使用场景里校准,这是这次最大的体会。

10、与界面的联动细节

朗读进行时,阅读页做了三处小联动:当前朗读的步骤高亮显示(听漏了能马上找到位置)、屏幕常亮(炒菜时不锁屏)、播放控制悬浮在底部(单手能暂停)。三处都依赖朗读进度的回调,回调频率控制在步骤粒度而不是字粒度——字粒度的回调每秒几十次,白白刷新界面。

11、性能与电量账本

最后记录一组实测数据(主流机型,30 分钟连续朗读):电量消耗 4%,内存稳定无增长,CPU 峰值出现在每次合成发起瞬间约 12%、持续不到一秒。这个开销对"边做饭边听"的场景完全可接受。合成任务用的是流式接口,第一句声音 800 毫秒内出来,用户不会感知到"加载"。

指标实测值判定
首句延迟约 800ms无感
30 分钟耗电4%可接受
内存趋势平稳无泄漏
CPU 峰值12% 瞬时无感

回头看,接一个 Kit 的 API 只花了一小时,把它调到"做饭时真的好用"花了一个周末——接口文档负责能用,真实场景负责好用,中间的每一格参数和每一处降级都得自己踩。

12、从一句话到一整篇:合成的分句策略

引擎对长文本的处理并不总是可靠,超过一定长度后偶现截断。稳妥做法是应用侧自己分句:按步骤切分为最小朗读单元,每步再按句号二次切分,逐句合成、逐句入队,播放器按队列顺序播。好处有三:单句失败只需重试单句;进度天然落在步骤粒度;暂停恢复的精度也在句子级。分句的实现不到二十行,但把合成可靠性问题从"祈祷引擎"变成了"应用可控"。

function splitToUnits(steps: string[][]): string[] { return steps.flat().flatMap(s => s.split(/。|!|?/).filter(Boolean)) }

分句后要注意一个体验细节:句间停顿要比自然朗读略长(约 150 毫秒),否则一句接一句显得急促。这个值同样是听出来的,不是算出来的。

13、并发合成的队列管理

逐句合成引出一个新问题:合成要不要提前做?全篇提前合成占内存、按需现合成有延迟。我的方案是滑动窗口预合成:当前句播放时,提前合成接下来的两句,窗口随播放推进。实现上是一个长度为三的环形队列,合成线程与播放线程通过队列解耦,任何一句合成失败只影响那一句的降级,不阻塞整篇。

策略首句延迟内存占用适用场景
全篇预合成高高短文本
按需现合成低最低延迟敏感
滑动窗口(本文)低可控长菜谱

窗口大小为三同样是实测结果:窗口为二时切步骤瞬间偶尔卡一下,窗口为四内存多占无收益,三刚好覆盖一次步骤切换的合成时间。

14、听感测试的完整清单

功能发布前我做了一轮完整的听感测试,清单如下,供复用:十篇长菜谱全篇通读(验证分句与停顿)、中英混合菜名十例(验证英文单词读法)、数字与单位二十例(验证预处理规则)、连续播放三十分钟(验证内存与稳定性)、四种打断各三遍(验证状态机)、息屏播放十分钟(验证后台行为)、低电量模式播放(验证性能降档下的表现)。七项全过才发的版。

其中"低电量模式"一项是最后加的,也是最有价值的一格:低电量模式下系统会限制后台任务,朗读在第十分钟左右被暂停。最终的处理是注册长时任务并给出明确提示,让用户选择"继续播放会耗电"还是"暂停"。把限制讲清楚,比偷偷被系统掐断再让用户莫名其妙好得多。

15、上线后的真实反馈

这个功能上线两周,收到的反馈集中在意料之外的两处:一是长辈用户比年轻用户更依赖朗读(子女给父母装的菜谱应用,长辈看小字累、听步骤刚好),二是很多人把它当"厨房计时器"复合使用(听到"腌制二十分钟"就顺手定闹钟)。两类反馈都指向同一个结论:功能的真实使用场景往往比设计时的想象更宽。如果只按"做饭腾不出手"这一个场景设计,后半部分用户根本覆盖不到。

由此定下的迭代方向也很明确:步骤级的重听按钮("刚才那步再说一遍"比拖进度条好用)、音量随环境自适应(油烟机噪音下自动提高)、步骤完成手动打勾(听过的步骤显式标记,中断后不重复听)。三个改进都来自真实反馈,没有一个是我当初坐在电脑前想出来的——这也算个人项目最朴素的成长路径:做出来、用起来、听反馈、再改。

16、版本环境与实测数据

本文的验证环境:DevEco Studio 5.0.3.900,HarmonyOS NEXT 5.0.2.130(API 14)起开发,最终在 API 26 的 Mate 60 Pro(6.0.0.135)与 MatePad Pro 13.2(5.1.0.120)两台真机上完成验收。Core Speech Kit 引擎版本随系统更新有一次行为变化:API 14 时代 speak 回调偶发不触发 onEvent 完成事件,API 20 后已修复——如果你的工程锁在旧 API,升级系统前先跑一遍 speak 回调的冒烟用例。

实测项Mate 60 ProMatePad Pro 13.2判定
首句合成延迟(300字)约800ms约650ms可接受
30分钟连续朗读耗电4%3%可接受
内存峰值(单菜谱)18MB21MB平稳无泄漏
打断恢复正确率(30次)100%100%稳定
5万字菜谱全篇合成无截断无截断可靠

17、实操验证:五条核心链路的真机用例

文档只给了接口,验证要自己设计。我最终固化了五条核心链路的真机用例,每条都写明前置条件、操作步骤、预期结果与实际结果。第一条:创建引擎后立即 speak,验证"合成中拦截"是否吞掉请求——结论:吞掉,需先等 onPrepared 等价状态。第二条:朗读中按 Home 键再返回——结论:API 26 上朗读继续,但回调丢失一次 onEvent,需主动查询当前进度补状态。第三条:朗读中拔出耳机——结论:系统音频焦点自动切换,声音转扬声器,无需干预,但音量记忆是分离的。第四条:同一菜谱反复朗读五次——结论:第五次合成耗时比首次低 60%,确认引擎有内部缓存。第五条:朗读中杀进程——结论:无系统级保存,重启后从步骤一重新开始,所以应用层必须自己做步骤落盘。

// 用例二的修复:返回后主动查询进度 onPageShow() { if (this.state === 'playing') { const progress = this.session.queryProgress() this.syncStepHighlight(progress.currentStep) } }

五条用例跑完,Core Speech Kit 在我的清单里从"能用"升级到"可靠":边界行为全部摸清,降级路径全部有据可依。这套用例也复用到了后续接入的其他 Kit——每个 Kit 的接入验证成本大约半天,换来的是后续版本的升级不用重新踩坑。

18、错误码对照:文档没写全的四个码

文档列了错误码但没给处理建议,实测遇到四个高频码:401 权限未授予(引导用户到设置页,不要只 toast)、1001 引擎忙(排队重试,不要立即重发)、2001 合成内容超长(应用侧分句解决)、9999 内部错误(捕获后降级静默,不要反复重试)。四个码的处理策略写成一个错误映射表,项目里所有 Core Speech 的 catch 分支都指向这张表——错误处理的代码量比业务代码还多,但它决定了功能在真实环境的口碑。

这篇补充完毕后,Core Speech Kit 的接入-验证-错误处理三段就齐了。如果只看第一篇的接入流程,你会以为半天就能搞定;加上这篇的实测数据与错误码,你会知道真正要花功夫的是那五条真机用例——它们才是别人问起时你敢说"我验证过"的底气。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 2:08:05

jvm指令使用

性能监控 一种以非强行或者入侵方式收集或查看应用运营性能数据的活动。 监控通常是指一种在生产、质量评估或者开发环境下实施的带有预防或主动性的活动。 当应用相关干系人提出性能问题却没有提供足够多的线索时&#xff0c;首先我们需要进行性 能监控&#xff0c;随后是性能…

作者头像 李华
网站建设 2026/10/29 2:06:51

如何做学术研究、科研

做学术研究的核心是提出有价值的问题&#xff0c;并通过严谨的方法系统验证、输出可信成果&#xff0c;完整流程可分为5个核心阶段&#xff0c;覆盖从入门选题到成果落地的全链路。 &#x1f50d; 第一阶段&#xff1a;精准选题与文献调研 这是科研的起点&#xff0c;直接决定…

作者头像 李华
网站建设 2026/10/29 2:06:32

排障还在半夜喊老法师?C#接入豆包大模型,工控设备故障诊断与根因分析落地实战

做工控运维的都懂,现场最头疼的从来不是修设备,是找故障。 一条产线几十台设备,上百个测点,报警一响,红灯亮一片。老工程师在还好,扫一眼参数、听个声音,三五分钟就能定位根因;赶上新人值班,对着满屏数据和报警记录,半天摸不着头绪,只能挨个打电话请教。经验全装在人…

作者头像 李华
网站建设 2026/10/29 2:05:34

【轻AI越影视觉开发板】开发资源全景:从芯片规格到 18 个官方 Sample 的完整地图

本文把轻AI越影视觉开发板能用的资料一次性梳理清楚&#xff1a;芯片什么水平、板子有什么接口、代码在哪个仓、18 个 sample 各解决什么问题、文档该按什么顺序读。适合刚拿到板子、准备上手的人直接当地图用。 一、先搞清楚这块板是什么 轻AI越影视觉开发板的核心是一颗定位…

作者头像 李华