HarmonyOS Next 入门实战 - 文字转拼音,文字转语音
文字转拼音
安装 pinyin4js 三方库
ohpm install @ohos/pinyin4js
pinyin4js 提供了以下接口:
● 文字转拼音(带声调和不带声调)
● 文字转拼音首字母
● 简体繁体互转
let rawText = "风急天高猿萧哀,渚清沙白鸟飞回;"
let pinyin1: string =
pinyin4js.convertToPinyinString(rawText, " ", pinyin4js.WITH_TONE_MARK)
//fēng jí tiān gāo yuán xiāo āi , zhǔ qīng shā bái niǎo fēi huí ;
let pinyin2: string = pinyin4js.convertToPinyinString(rawText, " ", pinyin4js.WITHOUT_TONE)
//feng ji tian gao yuan xiao ai , zhu qing sha bai niao fei hui ;
let pinyinFirst: string = pinyin4js.getShortPinyin(rawText)
//fjtgyxa,zqsbnfh;
let sTot: string = pinyin4js.convertToTraditionalChinese(rawText)
//風急天高猿蕭哀,渚清沙白鳥飛回;
let tTos: string = pinyin4js.convertToSimplifiedChinese(sTot)
//风急天高猿萧哀,渚清沙白鸟飞回;
文字转语音
import { textToSpeech } from '@kit.CoreSpeechKit';
创建引擎
textToSpeech 提供 createEngine 方法来创建引擎
function createEngine(createEngineParams: CreateEngineParams): Promise<TextToSpeechEngine>;
CreateEngineParams 包含如下字段
● language:语种,当前仅支持“zh-CN”中文
● person:音色。0为聆小珊女声音色,当前仅支持聆小珊女声音色。
● online:模式。0为在线,目前不支持;1为离线,当前仅支持离线模式
● extraParams:扩展参数
其中 extraParams 扩展参数包含如下字段
● style :string 风格。可选,不设置时默认为“interaction-broadcast”,当前仅支持“interaction-broadcast”广播风格。
● locate:string 区域信息。可选,不设置时默认为“CN”
● name:string 引擎名称。可选,引擎名称,不设置时默认为空
● isBackStage:boolean 是否支持后台播报。默认不支持后台播报
let extraParams: Record<string, Object> = {
"style": 'interaction-broadcast',
"locate": 'CN',
"name": '',
"isBackStage": true
}
let paramsInfo: textToSpeech.CreateEngineParams = {
language: 'zh-CN',
person: 0,
online: 1,
extraParams: extraParams
}
textToSpeech.createEngine(paramsInfo).then((value) => {
this.ttsEngine = value
}).catch((err: BusinessError) => {
})
文本播报
创建引擎后,通过调用引擎对象的 speak 方法进行文本播报
TextToSpeechEngine.speak(text: string, speakParams: SpeakParams): void;
● text:待播报的文本
● speakParams:合成播报音频的相关参数
speakParams 包含如下字段
● requestId:合成播报ID,全局不允许重复
● extraParams
○ speed:语速,可选,支持范围[0.5-2],不传参时默认为1
○ volume:音量,可选,支持范围[0-2],不传参时默认为1,
○ pitch:音调。可选,支持范围[0.5-2],不传参时默认为1,
○ languageContext:语境,播放阿拉伯数字用的语种。可选,当前仅支持“zh-CN”中文,默认“zh-CN”
○ audioType:音频类型。可选,当前仅支持“pcm”且为默认
○ playType:合成类型。0:仅合成不播报,返回音频流。1:合成与播报不返回音频流(默认)
○ soundChannel:播报通道,默认为3语音助手通道
○ queueMode:播报模式。可选,0:排队模式播报(默认)。1:抢占模式播报。
let extraParams: Record<string, Object> = {
"speed": 1,
"volume": 1,
"pitch": 1,
"languageContext": 'zh-CN',
"audioType": 'pcm',
"playType": 1,
"soundChannel": 3,
"queueMode": 1
}
let params: textToSpeech.SpeakParams = {
requestId: util.generateRandomUUID(),
extraParams: extraParams
}
this.ttsEngine?.speak(text, params)
停止播报
this.ttsEngine.stop()
状态监听
设置播报监听,可以收到开始,完成,暂停,播报信息,错误等状态回调
let listener: textToSpeech.SpeakListener = {
//播报开始时,回调此接口
onStart: (requestId: string, response: textToSpeech.StartResponse): void => {
},
//合成或播报结束后分别回调此接口,CompleteResponse.type = 0:合成结束。1:播报结束。
onComplete: (requestId: string, response: textToSpeech.CompleteResponse): void => {
},
//调用stop()方法时,回调此接口
onStop: (requestId: string, response: textToSpeech.StopResponse): void => {
},
//合成播报过程中,出现错误时回调
onError: (requestId: string, errorCode: number, errorMessage: string): void => {
},
//合成播报过程中回调此接口,返回请求ID,音频流信息,音频附加信息如格式、时长等
onData:(requestId: string, audio: ArrayBuffer, response: textToSpeech.SynthesisResponse) :void => {
}
}
this.ttsEngine?.setListener(listener)
播报策略
● 单词播报方式:[hN] (N=0/1/2) 0-智能判断,1-逐个字母播报,2-单词播报 例如:hello[h1] world
● 数字播报策略:[nN] (N=0/1/2) 0-智能判断,1-逐个号码播报,2-作为数值播报 例如:[n2]123[n1]456[n0]
● 静音停顿:[pN] N为无符号整数,单位为ms,例如:你好[p500]小艺
● 指定汉字发音:[=MN] M表示拼音,N表示声调,1~5分别表示阴平、阳平、上声、去声和轻声5个声调。例如:着[=zhuo2]手
诗词拼音展示
创建拼音展示组件
此组件使用Column和Flex组件来实现,每个Flex组件为一个段落,Flex内容包含多个单个汉字和拼音。

@Component
struct PinyinView {
@Prop text: string
@Prop pinyin: string
private textArray: Array<string> = []
private pinyinArray: Array<Array<string>> = []
aboutToAppear(): void {
this.textArray = this.text.split("\n")
let pinyinRow = this.pinyin.split("\n")
for (let row of pinyinRow) {
this.pinyinArray.push(row.trim().split(" "))
}
}
build() {
Column() {
ForEach(this.textArray, (item: string, rowIndex) => {
if (item) {
Flex({
direction: FlexDirection.Row,
wrap: FlexWrap.Wrap,
space: { cross: LengthMetrics.vp(8) }
}) {
ForEach(item.split(""), (item1: string, index) => {
this.WordView(item1, this.pinyinArray[rowIndex][index])
})
}.width('90%').margin({ top: rowIndex == 0 ? 0 : 8 })
} else {
Row().width('100%').height(22)
}
})
}
}
@Builder
WordView(text: string, pinyin: string) {
Column() {
Text(pinyin)
.fontSize(12)
.fontColor(Theme.Color.textSecondary)
.padding({ top: 3, bottom: 3 })
.visibility(this.isHanZi(text) ? Visibility.Visible : Visibility.Hidden)
Text(text)
.fontSize(20)
.fontColor(Theme.Color.textPrimary)
.margin({ top: 3 })
}.width("12.5%")
}
isHanZi(text: string) {
return text.charCodeAt(0) >= 0x4e00 && text.charCodeAt(0) <= 0x9fa5
}
}
诗词朗读
@ComponentV2
export struct PoetryDetailPage {
@Local soundPlayStatus: boolean = false
ttsEngine: textToSpeech.TextToSpeechEngine | null = null
aboutToDisappear(): void {
if (this.ttsEngine) {
this.ttsEngine.stop()
this.ttsEngine.shutdown()
}
}
initEngine(): Promise<void> {
return new Promise((resolve, reject) => {
if (this.ttsEngine == null) {
let extraParams: Record<string, Object> = {
"style": 'interaction-broadcast',
"locate": 'CN',
"name": '',
"isBackStage": true
}
let paramsInfo: textToSpeech.CreateEngineParams = {
language: 'zh-CN',
person: 0,
online: 1,
extraParams: extraParams
}
textToSpeech.createEngine(paramsInfo).then((value) => {
this.ttsEngine = value
resolve()
}).catch((err: BusinessError) => {
Toast.show(err.message)
reject()
})
} else {
resolve()
}
})
}
speak() {
if (this.ttsEngine && this.ttsEngine.isBusy()) {
this.ttsEngine.stop()
return
}
this.initEngine().then(() => {
let listener: textToSpeech.SpeakListener = {
onStart: (requestId: string, response: textToSpeech.StartResponse): void => {
this.soundPlayStatus = true
},
onComplete: (requestId: string, response: textToSpeech.CompleteResponse): void => {
if (response.type == 1) {
this.soundPlayStatus = false
}
},
onStop: (requestId: string, response: textToSpeech.StopResponse): void => {
this.soundPlayStatus = false
},
onError: (requestId: string, errorCode: number, errorMessage: string): void => {
this.soundPlayStatus = false
}
}
this.ttsEngine?.setListener(listener)
let extraParams: Record<string, Object> = {
"speed": 1,
"volume": 1,
"pitch": 1,
"languageContext": 'zh-CN',
"audioType": 'pcm',
"playType": 1,
"soundChannel": 3,
"queueMode": 1
}
let params: textToSpeech.SpeakParams = {
requestId: util.generateRandomUUID(),
extraParams: extraParams
}
let speakText =
`${this.poetry?.title}[p200]
${this.poetry?.dynasty}[p50]${this.poetry?.author}[p200]
${this.poetry?.text}`
this.ttsEngine?.speak(speakText, params)
})
}
}
本文的技术设计和实现都是基于作者工作中的经验总结,如有错误,请留言指正,谢谢。
HarmonyOS Next 入门实战 - 文字转拼音,文字转语音的更多相关文章
- javaScript对文字按照拼音排序
<title>JavaScript对文字按照拼音排序</title> <SCRIPT type="text/javascript"> funct ...
- Atitit s2018.2 s2 doc list on home ntpc.docx \Atiitt uke制度体系 法律 法规 规章 条例 国王诏书.docx \Atiitt 手写文字识别 讯飞科大 语音云.docx \Atitit 代码托管与虚拟主机.docx \Atitit 企业文化 每日心灵 鸡汤 值班 发布.docx \Atitit 几大研发体系对比 Stage-Gat
Atitit s2018.2 s2 doc list on home ntpc.docx \Atiitt uke制度体系 法律 法规 规章 条例 国王诏书.docx \Atiitt 手写文字识别 ...
- 向大家介绍我的新书:《基于股票大数据分析的Python入门实战》
我在公司里做了一段时间Python数据分析和机器学习的工作后,就尝试着写一本Python数据分析方面的书.正好去年有段时间股票题材比较火,就在清华出版社夏老师指导下构思了这本书.在这段特殊时期内,夏老 ...
- css图片+文字浮动(文字包围效果)
css图片+文字浮动(文字包围效果): 在网页中,我们有时想实现这个效果,但是 <div id="test"> <img src="gdimages/0 ...
- Spark入门实战系列--10.分布式内存文件系统Tachyon介绍及安装部署
[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .Tachyon介绍 1.1 Tachyon简介 随着实时计算的需求日益增多,分布式内存计算 ...
- 003-Tuple、Array、Map与文件操作入门实战
003-Tuple.Array.Map与文件操作入门实战 Tuple 各个元素可以类型不同 注意索引的方式 下标从1开始 灵活 Array 注意for循环的until用法 数组的索引方式 上面的for ...
- Scala深入浅出实战经典-----002Scala函数定义、流程控制、异常处理入门实战
002-Scala函数定义.流程控制.异常处理入门实战 Scala函数定义 语句结束无分号 定义无参函数 def 函数名称(参数名称:参数类型)[:Unit=]{ 函数体 } 老师的代码 我的实际代码 ...
- Spark入门实战系列--1.Spark及其生态圈简介
[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .简介 1.1 Spark简介 年6月进入Apache成为孵化项目,8个月后成为Apache ...
- Spark入门实战系列--2.Spark编译与部署(上)--基础环境搭建
[注] 1.该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取: 2.Spark编译与部署将以CentOS 64位操作系统为基础,主要是考虑到实际应用 ...
- Spark入门实战系列--2.Spark编译与部署(中)--Hadoop编译安装
[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .编译Hadooop 1.1 搭建环境 1.1.1 安装并设置maven 1. 下载mave ...
随机推荐
- MyBatisPlus——代码生成器
代码生成器 快速生成各项代码 步骤 创建Generator类,并创建main方法 创建代码生成器 AutoGenerator autoGenerator = new AutoGenerator(); ...
- [OI] 容斥原理拓展
10.容斥原理拓展 10.1 二项式反演 \[P.10.1(1) \] 设 \(U=\{S_1,S_2,S_3...S_n\}\),且任意 \(i\) 个元素的交集都相等 定义 \(g(x)\) 为 ...
- AD域下,环境下办公机系统时间不准确
事件起因: 某部门一同事电脑时间和AD域控时间相差3分钟,虽然说时间相差5分钟内问题不大,但是本着有问题就解决的原则,还是花了点时间去查资料解决. (小小吐槽一下,在我看来域控机是掌管下面所有的办公机 ...
- Android应用启动流程一次看透
1.1.冷启动和热启动 冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,然后再根据启动的参数,启动对应的进程组件,这个启动方式就是冷启动. 热启动:当启动应用时 ...
- axios 常见状态码
'100': 'Continue', '101': 'SwitchingProtocols', '102': 'Processing', '103': 'EarlyHints', '200': 'Ok ...
- kotlin更多语言结构——>解构声明
解构声明 有时把一个对象 解构 成很多变量会很方便,例如: val (name, age) = person 这种语法称为 解构声明 .一个解构声明同时创建多个变量.我们已经声明了两个新变量:name ...
- 游戏推荐业务中基于 sentinel 的动态限流实践
作者:来自 vivo 互联网服务器团队- Gao Meng 本文介绍了一种基于 sentinel 进行二次开发的动态限流解决方案,包括什么是动态限流.为什么需要引入动态限流.以及动态限流的实现原理. ...
- NebulaGraph 的云产品交付实践
作者:乔雷,Vesoft.Inc 云原生技术专家 NebulaGraph 介绍 NebulaGraph 是由杭州悦数科技有限公司自主研发的一款开源分布式图数据库产品,擅长处理千亿节点万亿条边的超大数据 ...
- KubeSphere 网关的设计与实现(解读)
作者:泓舟子,KubeSphere 后端研发工程师,云原生爱好者,现专注于云原生微服务方向. KubeSphere 中为什么需要网关? 如果需要将 K8s 集群内的服务暴露到外部访问有那些方式呢?可以 ...
- 五分钟一百行代码,手写一个vue项目全局通用的toast提示组件
前言: 我们已经分享过如何快速实现自己需要的全局弹框组件: 在开发 Vue 项目时,特别是H5页面的项目,还有一个组件是我们非常常用的,它相对弹框来说没有那么大,并且不需要手动关闭在需要更简洁的提示用 ...