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

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

相关推荐
THMAIL11 分钟前
深度学习从入门到精通 - 神经网络核心原理:从生物神经元到数学模型蜕变
人工智能·python·深度学习·神经网络·算法·机器学习·逻辑回归
七夜zippoe24 分钟前
AI+Java 守护你的钱袋子!金融领域的智能风控与极速交易
java·人工智能·金融
小关会打代码32 分钟前
深度学习之第八课迁移学习(残差网络ResNet)
人工智能·深度学习·迁移学习
ZHOU_WUYI38 分钟前
FastVLM-0.5B 模型解析
人工智能·llm
非门由也40 分钟前
《sklearn机器学习——多标签排序指标》
人工智能·机器学习·sklearn
XZSSWJS1 小时前
机器学习基础-day06-TensorFlow线性回归
人工智能·机器学习·tensorflow
代码青铜1 小时前
【实战指南】Cursor前端+Zion后端:10分钟打造能收款的AI商业应用MVP
前端·人工智能
程序员陆通1 小时前
用 Cursor AI 快速开发你的第一个编程小程序
人工智能·小程序
Geek 研究僧1 小时前
大疆 Osmo 360:双 1 英寸 + 8K/50fps,改写全景相机市场格局
人工智能·数码相机·智能硬件·相机
Wilber的技术分享1 小时前
【大模型实战笔记 1】Prompt-Tuning方法
人工智能·笔记·机器学习·大模型·llm·prompt