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 ...
随机推荐
- C#上位机与PLC通信心跳的实现方法
-Begin- 大家好!我是付工.众所周知,在工业自动化控制系统中,上位机与下位机之间的通信是实现自动化生产的关键环节之一.为了确保通信的稳定性和可靠性,我们通用会采用一种被称为[心跳机制]的方法,它 ...
- C# 开源浏览器性能提升,体验Chrome级速度
前言 使用 C# 和 CefSharp 开发的全功能网页浏览器. 项目介绍 SharpBrowser 是目前最快的开源 C# 网页浏览器! 采用了轻量级的 CEF 渲染器,在呈现网页时甚至比 Goog ...
- [OI] 可持久化数据结构
学了一年 OI 才看懂这句话: \(\log n\) 是以什么为底的? 其实没什么区别 因为我们自动忽略常数,因此 \(\log_{a}n=\frac{\log_{x}n}{\log_{x}a}=\l ...
- [OI] 珂朵莉树
对于一个序列,它有较多重复元素,并且题目需要维护区间修改,维护区间信息,维护整块值域信息的,那么就可以考虑珂朵莉树解决. 主要思想 珂朵莉树将全部相同的颜色块压缩为一组,如对于下述序列: 1 1 1 ...
- request和response请求包中的各项解释
Request Response
- uniapp中前端canvas合成图片使用详解
项目开发中用到了定位打卡,保存当前位置到上传图片的功能.刚开始想着后端人员合成,前端上传经纬度.位置信息和图片就OK,没想到后端人员以使用项目中现有的组件为借口,让前端合成图片,造成前端工作量大增,再 ...
- ios中文件夹文件的创建和删除
//1.文件夹.文件的创建和删除 NSFileManager *fileManager=[NSFileManager defaultManager]; NSString *filePath=@&quo ...
- 如何让img图片居中
说明:img是行内块元素,用一个盒子(父元素)嵌套img(子元素) text-align:center;可以让父元素为块元素的行内块或行内元素水平居中: vaertical-align:middle; ...
- 我们如何在 vue 应用我们的权限
权限可以分为用户权限和按钮权限: 用户权限,让不同的用户拥有不同的路由映射 ,具体实现方法: 1. 初始化路由实例的时候,只把静态路由规则注入 ,不要注入动态路由规则 : 2. 用户登录的时候,根据返 ...
- 10 Self-Attention(自注意力机制)
博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...