1.1.8 • Published 9 months ago

@lucifinil/tts-editor v1.1.8

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

tts-editor

介绍

  • 提供多音、文本、数值、英文、停顿等五种方式的划词选择。 1724981348142 1724981436277

多音

  • 对汉字的处理,不同的汉字有多种读音或音调,可对该字指定读法。

文本

  • 提供人名、地址、车牌号、标点符号、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>

注意事项

  1. 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;
    }
  1. 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);
    },
  1. html 字符转反序列化
 parserDomHtml(htmlString) {
      const parser = new DOMParser();
      const doc = parser.parseFromString(htmlString, 'text/html');
      return doc.body.firstChild;
    },

License

MIT

1.1.8

9 months ago

1.1.7

9 months ago

1.1.6

9 months ago

1.1.5

9 months ago

1.1.4

9 months ago

1.1.1

10 months ago

1.1.0

10 months ago

1.0.9

10 months ago

1.0.8

10 months ago

1.0.7

10 months ago

1.0.6

10 months ago

1.0.5

11 months ago

1.1.3

10 months ago

1.0.4

11 months ago

1.1.2

10 months ago

1.0.3

11 months ago

1.0.2

11 months ago

1.0.1

11 months ago

1.0.0

11 months ago