文字转拼音
安装 pinyin4js 三方库
javascript
ohpm install @ohos/pinyin4js
pinyin4js 提供了以下接口:
● 文字转拼音(带声调和不带声调)
● 文字转拼音首字母
● 简体繁体互转
javascript
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)
//风急天高猿萧哀,渚清沙白鸟飞回;
文字转语音
javascript
import { textToSpeech } from '@kit.CoreSpeechKit';
创建引擎
textToSpeech 提供 createEngine 方法来创建引擎
javascript
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 是否支持后台播报。默认不支持后台播报
javascript
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:抢占模式播报。
javascript
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)
停止播报
javascript
this.ttsEngine.stop()
状态监听
设置播报监听,可以收到开始,完成,暂停,播报信息,错误等状态回调
javascript
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内容包含多个单个汉字和拼音。
javascript
@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
}
}
诗词朗读
javascript
@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)
})
}
}
本文的技术设计和实现都是基于作者工作中的经验总结,如有错误,请留言指正,谢谢。