SPIRNGBOOT+VUE实现浏览器播放音频流并合成音频

一、语音合成支持流式返回,通过WS可以实时拿到音频流,那么我们如何在VUE项目中实现合成功能呢。语音合成应用非常广泛,如商家广告合成、驾校声音合成、新闻播报、在线听书等等场景都会用到语音合成。

二、VUE下实现合成并使用浏览器播放代码如下:

<template>
  <div class="Login-container">
    <div class="allClass">
      <div class="titleClass"><b>在线语音合成流式版</b></div>
      <hr/>
      <textarea style=" width: 310px;height: 100px;">
     {{ttsText}}
      </textarea>
      <el-button type="primary" @click="clickTts">立即合成</el-button>
      <el-button type="primary" @click="clickWav">DOWN WAV</el-button>
    </div>
  </div>
</template>


<script src="../js_util/index.js"></script>
<script src="../js_util/index.umd.js"></script>
<script>
import * as base64 from 'js-base64'
import CryptoJS from '../js_util/crypto-js/crypto-js.js'
import AudioPlayer from '../../public/player'

const audioPlayer = new AudioPlayer(""); // 播放器
export default {
  name: "Login",
  data() {
    return {
      APPID: "",
      API_SECRET: "",
      API_KEY: "",
      ttsWs: "", // 合成ws链接
      ttsText: "锦瑟无端五十弦,一弦一柱思华年。庄生晓梦迷蝴蝶,望帝春心托杜鹃。沧海月明珠有泪,蓝田日暖玉生烟。" +
          "此情可待成追忆,只是当时已惘然。",
      vcn: "xiaoyan",

    }
  },
  methods: {
    clickTts() {
      const url = this.getWebSocketUrl(this.API_KEY, this.API_SECRET);
      if ("WebSocket" in window) {
        this.ttsWS = new WebSocket(url);
      } else if ("MozWebSocket" in window) {
        this.ttsWS = new MozWebSocket(url);
      } else {
        alert("浏览器不支持WebSocket");
        return;
      }
      this.ttsWS.onopen = (e) => {
        console.log("链接成功...")
        audioPlayer.start({
          autoPlay: true,
          sampleRate: 16000,
          resumePlayDuration: 1000
        });
        let text = this.ttsText;
        let tte = document.getElementById("tte") ? "unicode" : "UTF8";
        let params = {
          common: {
            app_id: this.APPID,
          },
          business: {
            aue: "raw",
            auf: "audio/L16;rate=16000",
            vcn: this.vcn,
            bgs: 1,
            tte,
          },
          data: {
            status: 2,
            text: this.encodeText(text, tte),
          },
        };
        this.ttsWS.send(JSON.stringify(params));
        console.log("发送成功...")
      };
      this.ttsWS.onmessage = (e) => {
        let jsonData = JSON.parse(e.data);
        console.log("合成返回的数据" + JSON.stringify(jsonData));
        // 合成失败
        if (jsonData.code !== 0) {
          console.error(jsonData);
          return;
        }
        audioPlayer.postMessage({
          type: "base64",
          data: jsonData.data.audio,
          isLastData: jsonData.data.status === 2,
        });
        if (jsonData.code === 0 && jsonData.data.status === 2) {
          this.ttsWS.close();
        }
      };
      this.ttsWS.onerror = (e) => {
        console.error(e);
      };
      this.ttsWS.onclose = (e) => {
        console.log(e + "链接已关闭");
      };
    },
    getWebSocketUrl(apiKey, apiSecret) {
      let url = "wss://tts-api.xfyun.cn/v2/tts";
      let host = location.host;
      let date = new Date().toGMTString();
      let algorithm = "hmac-sha256";
      let headers = "host date request-line";
      let signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/tts HTTP/1.1`;
      let signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret);
      let signature = CryptoJS.enc.Base64.stringify(signatureSha);
      let authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
      let authorization = btoa(authorizationOrigin);
      url = `${url}?authorization=${authorization}&date=${date}&host=${host}`;
      return url;
    },
    // 文本编码
    encodeText(text, type) {
      if (type === "unicode") {
        let buf = new ArrayBuffer(text.length * 4);
        let bufView = new Uint16Array(buf);
        for (let i = 0, strlen = text.length; i < strlen; i++) {
          bufView[i] = text.charCodeAt(i);
        }
        let binary = "";
        let bytes = new Uint8Array(buf);
        let len = bytes.byteLength;
        for (let i = 0; i < len; i++) {
          binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
      } else {
        return base64.encode(text);
      }
    },
    clickPcm() {

    },
    clickWav() {
      const blob = audioPlayer.getAudioDataBlob("wav")
      if (!blob) {
        return
      }
      let defaultName = new Date().getTime();
      let node = document.createElement("a");
      node.href = window.URL.createObjectURL(blob);
      node.download = `${defaultName}.wav`;
      node.click();
      node.remove();
    }
  }
}
</script>

<style scoped>
.Login-container {
  height: 100vh;
  background-image: linear-gradient(to bottom right, deepskyblue, darkcyan);
  overflow: hidden;
}

.allClass {
  margin: 200px auto;
  background-color: #ffffff;
  width: 350px;
  height: 390px;
  padding: 20px;
  border-radius: 10px;
}

.titleClass {
  margin: 20px 0;
  text-align: center;
  font-size: 24px;
}

.inputOneClass {
  margin: 10px 0;
}

.buttonClass {
  margin: 10px 0;
  text-align: right;
}
</style>

三、除了调用浏览器麦克风播报,我们还可以一键下载为WAV音频,实现效果如下!

四、感兴趣的可以加我获取源码!

相关推荐
Point__Nemo21 分钟前
深度学习Day-33:Semi-Supervised GAN理论与实战
人工智能·深度学习
魔力之心25 分钟前
人工智能与机器学习原理精解【20】
人工智能·机器学习
SEU-WYL3 小时前
基于深度学习的因果发现算法
人工智能·深度学习·算法
Tunny_yyy4 小时前
李宏毅2023机器学习HW15-Few-shot Classification
人工智能·机器学习
Francek Chen4 小时前
【机器学习-监督学习】朴素贝叶斯
人工智能·机器学习·分类·数据挖掘·scikit-learn·朴素贝叶斯·naive bayes
中式代码美式咖啡5 小时前
记录开发一个英语听力训练网站
java·spring boot·bootstrap·音视频·语音识别
jndingxin6 小时前
OpenCV运动分析和目标跟踪(1)累积操作函数accumulate()的使用
人工智能·opencv·目标跟踪
文艺倾年6 小时前
【大模型专栏—进阶篇】语言模型创新大总结——“后起之秀”
人工智能·pytorch·语言模型·自然语言处理·大模型
DA树聚6 小时前
大语言模型之ICL(上下文学习) - In-Context Learning Creates Task Vectors
人工智能·学习·程序人生·ai·语言模型·自然语言处理·easyui
一支王同学6 小时前
论文解读《LaMP: When Large Language Models Meet Personalization》
人工智能·语言模型·自然语言处理