1.1.9 • Published 9 months ago

@lucifinil/tts-editor v1.1.9

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.9

9 months ago

1.1.8

1 year ago

1.1.7

1 year ago

1.1.6

1 year ago

1.1.5

1 year ago

1.1.4

1 year ago

1.1.1

1 year ago

1.1.0

1 year ago

1.0.9

1 year ago

1.0.8

1 year ago

1.0.7

1 year ago

1.0.6

1 year ago

1.0.5

1 year ago

1.1.3

1 year ago

1.0.4

1 year ago

1.1.2

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago