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音频,实现效果如下!

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

相关推荐
学好statistics和DS1 小时前
【CV】神经网络中哪些参数需要被学习?
人工智能·神经网络·学习
大千AI助手1 小时前
机器学习特征筛选中的IV值详解:原理、应用与实现
人工智能·机器学习·kl散度·roc·iv·信息值·woe
姜—姜1 小时前
通过构建神经网络实现项目预测
人工智能·pytorch·深度学习·神经网络
Ro Jace1 小时前
模式识别与机器学习课程笔记(4):线性判决函数
人工智能·笔记·机器学习
科研小白_2 小时前
基于遗传算法优化BP神经网络(GA-BP)的数据时序预测
人工智能·算法·回归
互联网江湖3 小时前
蓝桥杯出局,少儿编程的价值祛魅时刻?
人工智能·生活
Elastic 中国社区官方博客3 小时前
根据用户行为数据中的判断列表在 Elasticsearch 中训练 LTR 模型
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
paid槮4 小时前
OpenCV图像形态学详解
人工智能·opencv·计算机视觉
点控云4 小时前
点控云智能短信:重构企业与用户的连接,让品牌沟通更高效
大数据·人工智能·科技·重构·外呼系统·呼叫中心
救救孩子把7 小时前
14-机器学习与大模型开发数学教程-第1章 1-6 费马定理与极值判定
人工智能·数学·机器学习