@lucifinil/tts-editor
v1.1.8
Published
## 介绍
Downloads
244
Readme
tts-editor
介绍
- 提供多音、文本、数值、英文、停顿等五种方式的划词选择。
多音
- 对汉字的处理,不同的汉字有多种读音或音调,可对该字指定读法。
文本
- 提供人名、地址、车牌号、标点符号、ID、日期、时间、计量单位等,指定该文本按照什么形式读。
数值
- 提供读数值、读数字、读手机等。
英文
- 提供读字母和读单词。
停顿
- 在某处可停顿 0.5s、1s、2s 等
Install
npm i @lucifinil/tts-editor
Usages
<template>
<div>
<tts-editor
:ref="`ssml${index}`"
:text="show_list[index].value"
:richText="show_list[index].richText"
@ssmlGenerated="ssmlGenerated($event, index)"
@playAudio="playAudio($event, index)"
@input="changeInput($event, index)"
>
<template #btn>
<a-button type="primary" size="small">生成素材</a-button>
</template>
</tts-editor>
</div>
</template>
<script>
import TtsEditor from '@lucifinil/tts-editor'
export default {
name: 'tts',
components: {
TtsEditor
},
data() {
return {
text: '新鲜的微风666吹动我的衣袂,如同爱人的鼻息吹着我的手一样。',
show_list: []
}
},
methods: {
ssmlGenerated(ssml, index) {
this.show_list[index] = {
...this.show_list[index],
ssml
}
this.ssmlList[index] = ssml
},
changeInput(value, index) {
this.show_list[index] = {
...this.show_list[index],
value
}
const domRef = this.$refs[`ssml${index}`][0]?.$el
const targetElement = domRef?.querySelector('.tts-editor-content')
this.show_list[index].richText = this.htmlSerializer(targetElement)
},
htmlSerializer(targetElement) {
if (!targetElement) return
const contentChildren = Array.from(targetElement?.childNodes)
const clone = document.createElement('div')
contentChildren.forEach(child => {
clone.appendChild(child.cloneNode(true))
})
const serializer = new XMLSerializer()
return serializer.serializeToString(clone)
},
async getAudioPath(index) {
try {
const {value} = this.show_list[index]
const {data} = await this.$robot.getBroadcast({
text: `<speak>${value}</speak>`,
voice: 'aixia',
volume: 50,
speechRate: -80,
vendor: 2,
cloudType: 1
})
return `/rbc_web/rest/patter/playVideo?filePath=${data}`
} catch (err) {
return ''
}
},
playAudio(val, index) {
const {isSpeak, audioUrl} = val
const domRef = this.$refs[`ssml${index}`][0]?.$el
const audioElement = domRef?.querySelector('#ssml-audio')
if (!audioElement.paused) {
audioElement.pause()
return
}
if (audioUrl && !isSpeak) {
this.$nextTick(() => audioElement.play())
return
}
this.getAudioPath(index).then(audioUrl => {
if (!audioUrl) {
this.$message.error('播放失败')
return
}
this.$refs[`ssml${index}`][0].audioUrl = audioUrl
this.$nextTick(() => audioElement.play())
})
}
}
}
</script>
可单独使用,也和独立使用,以上为多个编辑器同时使用。使用时注意确保 ref 唯一。
props
- text 文本内容。多行请用
\n
分割。 - richText htmlString 用于编辑时回显。
event
- input 失去焦点时获取当前编辑框输入的内容。
- playAudio 将文字转为语音 试听。
- ssmlGenerated。生成 ssml 代码。
<s>
新
<phoneme alphabet="py" ph="xian1">
鲜
</phoneme>
的微风
<say-as interpret-as="cardinal">
666
</say-as>
吹动我的
<say-as interpret-as="name"> 衣袂 </say-as>,
<say-as interpret-as="address">
如同
</say-as>
爱人的鼻息吹着我
<phoneme alphabet="py" ph="di2">
的
</phoneme>
手一样
<say-as interpret-as="punctuation">
。
</say-as>
<say-as interpret-as="date">
2024-07-25
</say-as>
<say-as interpret-as="time">
12:00:00
</say-as>
</s>
注意事项
- html 标签入库时要去除外层无用的标签
extractInnermostContent(htmlString) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = htmlString;
function getInnermostDiv(element) {
let currentElement = element;
while (currentElement.children.length === 1 && currentElement.firstElementChild.tagName.toLowerCase() === 'div') {
currentElement = currentElement.firstElementChild;
}
return currentElement;
}
const outerDiv = tempDiv.firstElementChild;
if (outerDiv && outerDiv.tagName.toLowerCase() === 'div') {
const innermostDiv = getInnermostDiv(outerDiv);
if (innermostDiv !== outerDiv) {
outerDiv.innerHTML = innermostDiv.innerHTML;
}
return outerDiv.outerHTML;
}
return htmlString;
}
- html 转字符转
htmlSerializer(targetElement) {
if (!targetElement) return;
const contentChildren = Array.from(targetElement?.childNodes);
const clone = document.createElement('div');
contentChildren.forEach(child => {
clone.appendChild(child.cloneNode(true));
});
const serializer = new XMLSerializer();
return serializer.serializeToString(clone);
},
- html 字符转反序列化
parserDomHtml(htmlString) {
const parser = new DOMParser();
const doc = parser.parseFromString(htmlString, 'text/html');
return doc.body.firstChild;
},