从零开始开发纯血鸿蒙应用之语音朗读

news/2025/3/3 8:23:20/

从零开始开发纯血鸿蒙应用

  • 〇、前言
  • 一、API 选型
    • 1、基本情况
    • 2、认识TextToSpeechEngine
  • 二、功能集成实践
    • 1、改造右上角菜单
    • 2、实现语音播报功能
      • 2.1、语音引擎的获取和关闭
      • 2.2、设置待播报文本
      • 2.3、speak 目标文本
      • 2.4、设置语音回调
  • 三、总结

〇、前言

中华汉字洋洋洒洒何其多,难免会遇到不知怎么读的字,这时候,如果应用本身就能够进行文本朗读,那么就可以快速知道对应的发音,而不用跑到浏览器上搜索相关资料。

再者,众多用户之中,难免有喜欢听书而不喜欢读书,或者限于自身经历而不识字的,总而言之,作为文本文件浏览和编辑的软件,TxtEdit 有必要提供语音朗读的功能,这一点,在鸿蒙NEXT API 的自身 AI 功能助力下,实现起来并不是很困难,下面就为大家介绍,如何在自己的纯血鸿蒙应用中,集成语音朗读文本的功能。

一、API 选型

1、基本情况

在这里插入图片描述
我相信,任何一个有认真阅读华为开发者平台上的鸿蒙API参考文档的人,都应该知道鸿蒙 NEXT API 里面有专门提供 AI 能力的,而其中,就有一个Core Speech Kit(基础语音服务) 模块,而这就是实现我们的目标所需的;毕竟只是简单的文本转语音,所以,无需太高级的AI能力的,基础的就已经足够了。

2、认识TextToSpeechEngine

Core Speech Kit ,有两大能力,一是文本转语音,二是语音转文本即语音识别。文本转语音 API,名为 textToSpeech,它包含了 TextToSpeechEngine 在内的众多与文本转语音相关的方法或功能类。

TextToSpeechEngine,顾名思义,是一个语音引擎,获取引擎实例需要用对应的构建方法,而不是直接 new 出来。有了引擎实例之后,就可以用它将目标文本转换成语音信息,并播放出来,也就是 speak 出来。
在这里插入图片描述
当我们不在需要语音引擎了,出于节约资源的考量,我们应该及时 shutdown,这个关闭动作,可以放在生命周期函数,如 aboutToDisappear 里面。

speak 的方法原型如下:
在这里插入图片描述
如图所示,speak 一共有两个参数,第一个参数就是待进行语音播报的文本内容,第二个则是进行语音播报所必须设置的参数,该参数一共包含两个设置项:
1)请求 ID,要求每次都不同,最好全局唯一
2)语音参数,主要包括语速、音量、音调、合成类型等,使用 Record<string, Object> 结构封装:

  • <‘speed’, number> 语速。可选,支持范围[0.5-2],不传参时默认为1,使用一倍语速合成音频流。
  • <‘volume’, number> 音量。可选,支持范围[0-2],不传参时默认为1,使用一倍音量合成音频流。
  • <‘pitch’, number> 音调。可选,支持范围[0.5-2],不传参时默认为1,使用正常音调合成音频流。
  • <‘languageContext’, string> 语境,播放阿拉伯数字用的语种。可选,当前仅支持“zh-CN”中文,不传参时默认“zh-CN”。设置为zh-CN时,也可对英语进行语音播报
  • <‘audioType’, string> 音频类型。可选,当前仅支持“pcm”,不传参时默认为“pcm”(PCM 即脉冲编码调制 (Pulse Code Modulation))。
  • <‘playType’, number> 合成类型。可选,不传参时默认为1。0,仅合成不播报,返回音频流。1,合成与播报不返回音频流。
  • <‘soundChannel’, number> 播报通道。可选,参数范围请参考音频流使用来选择适合自己的音频场景,范围之外会播报异常。不传参时默认为3,语音助手通道。
  • <‘queueMode’, number> 播报模式。可选,不传参时默认为0。0:排队模式播报。1:抢占模式播报。

通常,只需要对语速、音量、音调、语境和音频类型进行设置即可。

二、功能集成实践

下面,开始将 TextToSpeechEngine 集成到 TxtEdit 中,

1、改造右上角菜单

我将语音播报功能的触发入口,放在之前的右上角菜单中:
在这里插入图片描述
相对应的,PageTitleBar 里新增一个字段作为功能载入通道:
在这里插入图片描述

2、实现语音播报功能

在使用 PageTitleBar 的 ViewFilePage 中,编写实现语言播报功能的相关代码,并载入到 PageTitleBar 中。

2.1、语音引擎的获取和关闭

首先,在 ViewFilePage 中声明一个字段用于持有语音引擎实例,不放就将该字段取名为 textSpeechEngine,为了关闭语音引擎后进行内存释放,该字段的类型需要声明为 textToSpeech.TextToSpeechEngine|null

语音引擎的关闭动作,由 aboutToDisappear 完成:
在这里插入图片描述
那么,语音引擎的实例创建,就自然地由 aboutToAppear 来完成:
在这里插入图片描述
语音引擎实例的创建,同样需要初始化参数:
在这里插入图片描述

2.2、设置待播报文本

在使用语音引擎进行文本播报之前,需要将目标文本进行确定,我采用的处理逻辑如下:
1)当用户有进行文本选择时,只播报选择的那些文本;
2)当用户没有进行文本选择时,播报整个文件内容;
3)如果文件内容为空,则固定播报“没有可以播报的内容”。

针对第一种情况,需要利用 Text 组件的 onTextSelectionChange 事件处理函数:

onTextSelectionChange((start, end) => {this.copyStart = start;this.copyEnd = end;if (this.fileContent) {this.selectedText = this.fileContent.slice(this.copyStart, this.copyEnd);}
})

2.3、speak 目标文本

最后,在 PageTitleBar 的使用处,新增如下的一段代码:
在这里插入图片描述
为了保证请求ID的唯一性,我使用了 NANOID 方法,对应的实现代码如下:

function nanoid(size = 21) {let id = '';const urlAlphabet = 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW';const mask = urlAlphabet.length - 1;const step = Math.log(urlAlphabet.length) / Math.log(256);const random = () => Math.random() * 256;while (size--) {id += urlAlphabet[Math.floor(random() * step) & mask];}return id;
}export default nanoid;

这个 NANOID 的实现代码,我是放在了 lib_util 模块中,所以,想要其他模块中也可以使用,还必须在 lib_util 模块的 index.ets 文件中,更新一句代码:export { default as NANOID } from "./src/main/ets/NANOID"

2.4、设置语音回调

TextToSpeechEngine 还提供了一个 setListener 设置语音回调,通过语音回调方法,可以监测语音播报的状态,比如播报开始、播报结束。语音回调不是必须的,如果想要实现,可以参考如下代码:
在这里插入图片描述
我这里是直接将语音播报的相关状态,简单地记录到日志当中。

三、总结

经过上面的学习,我相信屏幕前的你,已经懂得如何在自己的鸿蒙应用中,集成语音播报内容,不过,我还想多说一点,对于 TextArea 这种文本编辑组件,选择文本后进行播报的功能,需要调整为拷贝文本后进行播报,这是因为当我点击右上角菜单时,编辑框会自然而然的失去焦点,结果就是原本选中的文本不再被选中。


http://www.ppmy.cn/news/1576245.html

相关文章

final 关键字在不同上下文中的用法及其名称

1. final 变量 名称&#xff1a;final 变量&#xff08;常量&#xff09;。 作用&#xff1a;一旦赋值后&#xff0c;值不能被修改。 分类&#xff1a; final 实例变量&#xff1a;必须在声明时或构造函数中初始化。 final 静态变量&#xff1a;必须在声明时或静态代码块中初…

Hive-05之查询 分组、排序、case when、 什么情况下Hive可以避免进行MapReduce

一、目标 掌握hive中select查询语句中的基本语法掌握hive中select查询语句的分组掌握hive中select查询语句中的join掌握hive中select查询语句中的排序 二、要点 1. 基本查询 注意 SQL 语言大小写不敏感SQL 可以写在一行或者多行关键字不能被缩写也不能分行各子句一般要分行…

【再谈设计模式】备忘录模式~对象状态的守护者

一、引言 在软件开发过程中&#xff0c;我们常常会遇到需要保存对象状态以便在之后恢复的情况。例如&#xff0c;在文本编辑器中&#xff0c;我们可能想要撤销之前的操作&#xff1b;在游戏中&#xff0c;玩家可能希望恢复到之前的某个游戏状态。备忘录模式&#xff08;Memento…

NIM平台开发基于提示工程的大语言模型(LLM)应用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1 课程介绍1.1 Goals1.2 content 2 提示词简介2.1 NVIDIA NIMs 用于提示工程2.2 OpenAI API 交互2.3 与 LangChain 交互实现聊天2.4 流式处理和批处理2.5 迭代式提示…

《白帽子讲 Web 安全:点击劫持》

目录 摘要&#xff1a; 一、点击劫持概述 二、点击劫持的实现示例&#xff1a;诱导用户收藏指定淘宝商品 案例 构建恶意页面&#xff1a; 设置绝对定位和z - index&#xff1a; 控制透明度&#xff1a; 三、其他相关攻击技术 3.1图片覆盖攻击与 XSIO 3.2拖拽劫持与数据…

大白话实战docker

为什么有docker 假设有这么一个场景,作为新时代的全栈工程师,某一天你接手一个项目,搭建好项目以后,还需要一台服务器,在它上面安装mysql、redis等项目中常用的中间件,于是你网上搜索Linux如何安装mysql、redis,照着网上的资料进行复制粘贴,结果发现老是运行不成功,好…

23种设计模式一览【设计模式】

文章目录 前言一、创建型模式&#xff08;Creational Patterns&#xff09;二、结构型模式&#xff08;Structural Patterns&#xff09;三、行为型模式&#xff08;Behavioral Patterns&#xff09; 前言 设计模式是软件工程中用来解决特定问题的一组解决方案。它们是经过验证…

vector 面试点总结

ps&#xff1a;部分内容使用“AI”查询 一、入门 1、什么是vector 动态数组容器&#xff0c;支持自动扩容、随机访问和连续内存存储。 2、怎么创建-初始化vector std::vector<int> v; // 创建空vectorstd::vector<int> v {1, 2, 3}; // 直接初始化std::vec…