如何修复 Vue + Node 中的 Uncaught (in Promise) DOMException: Failed to load because no supported source was found 错误?

问题描述 投票:0回答:1

我正在构建一个网络应用程序,它可以接收语音并将其转换为文本。然后将文本转换为文本并发送到 openai(chatgpt),以便它返回答案。 aws polly 是我在 chatgpt 返回答案时用于语音输出的工具。

我的问题是我在生产中的 vue 应用程序中遇到以下错误:

/voice/66154949.mp3:1     GET https://jarvis-ruby-rho.vercel.app/voice/66154949.mp3 net::ERR_ABORTED 404 (Not Found)

Uncaught (in promise) DOMException: Failed to load because no supported source was found.

代码在本地运行良好,但我在生产中遇到该错误(vercel 和 netlify)

这是我的节点(express)代码:

const express = require("express");
const app = express();
const cors = require("cors");
const bodyParser = require("body-parser");
const fs = require("fs");
const dotenv = require("dotenv")

dotenv.config()
const PORT = process.env.PORT || 3001;
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({ apiKey: process.env.OPEN_AI_KEY});
const openai = new OpenAIApi(configuration);

app.use(bodyParser.json());
app.use(cors());

const AWS = require("aws-sdk");
AWS.config.loadFromPath("AWS_Credentials.json");

app.post('/api/TTS', async (req, res) => {

    const completion = await openai.createCompletion({
        model: "text-davinci-003",
        prompt: req.body.text,
        max_tokens: 100,
        temperature: 0.5
    })
    console.log(completion)

    let num = (Math.random() * 100000000).toFixed(0);

    const awsPolly = new AWS.Polly({ region: "us-east-1" })
    const params = {
        OutputFormat: "mp3",
        Text: completion.data.choices[0].text,
        VoiceId: "Matthew"
    }

    awsPolly.synthesizeSpeech(params, (err, data) => {
        if (err) {
            console.error(err);
            return;
        }

        let filePath = "../public/voice/";
        let fileName = num + ".mp3";

        if (num) fs.writeFileSync(filePath + fileName, data.AudioStream)
    })

    setTimeout(() => { res.status(200).json(num) }, 4500)
})

app.listen(PORT, () => { 
    console.log(`Listening at ${PORT}`); 
});

我的vue代码:

<script setup>
import { ref } from 'vue';
import { useAVLine } from 'vue-audio-visual';

const player = ref(null);
const canvas = ref(null);
let mySource = ref(null);
let action = ref('');
let output = ref('');

useAVLine(player, canvas, { src: mySource, canvHeight: 300, canvWidth: 1000, lineColor: 'orange' });

const runSpeechRecognition = () => {
  var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
  var recognition = new SpeechRecognition();

  recognition.onstart = () => {
    action.value = "I'm Listening";
  };

  recognition.onspeechend = () => {
    action.value = 'Done';
    recognition.stop();
  };

  recognition.onresult = async (event) => {
    var transcript = event.results[0][0].transcript;
    output.value = transcript;

    try {
      const baseURL = import.meta.env.VITE_BASE_SERVER_URL || 'http://localhost:3001'
      const response = await fetch(`${baseURL}/api/TTS`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          text: event.results[0][0].transcript,
        }),
      });

      if (response.ok) {
        const data = await response.json();
        console.log(data)
        if (data) {
          mySource.value = `${import.meta.env.BASE_URL}voice/${data}.mp3`;
          setTimeout(() => {
            player.value.play();
          }, 500);
        }
      } else {
        console.log('Request failed with status:', response.status);
      }
    } catch (err) {
      console.log(err);
    }
  };
  recognition.start();
};
</script>

<template>
  <div class="show">
    <div class="action" v-if="action">{{ action }}</div>
    <div class="synthesizedSpeech" v-if="output"><b>Question</b>: {{ output }}</div>
  </div>

  <div class="audio-wrapper">
    <audio id="player" ref="player" :src="mySource" type="audio/mp3" controls hidden></audio>
    <canvas ref="canvas" />
    <div class="button-section">
    <button type="button" @click="runSpeechRecognition()">Ask Me Anything</button>
  </div>
  </div>
</template>

<style>
body {
  background-color: rgb(23, 23, 23);
}

.audio-wrapper{
  height: 80vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

canvas {
  display: block;
  width: 800px;
}

.button-section {
  display: flex;
  justify-content: center;
  margin-top: 30px;
}

button {
  padding: 8px 13px;
  border-radius: 5px;
  background-color: orange;
  color: white;
  font-weight: 700;
  font-size: 18px;
  border: none;
  cursor: pointer;
}

.show {
  width: 100%;
  text-align: center;
  color: white;
}

.action {
  margin-top: 10px;
  margin-bottom: 10px;
}

.synthesizedSpeech {
  max-width: 500px;
  padding: 20px;
  border-radius: 10px;
  display: inline-block;
  background: #313131;
  font-weight: bold;
}
</style>

P.S:我的根 vue 代码中有我的后端文件夹(代码)(我的后端文件夹嵌套在前端内部的位置)

node.js amazon-web-services vue.js nuxt.js vuejs3
1个回答
0
投票

您没有正确使用音频标签

<audio  ... >
   <source :src="mySource" type="audio/mp3" />
</audio>

使用'source'标签而不是使用'src'属性,它应该是URL类型。

https://www.w3schools.com/tags/att_audio_src.asp

© www.soinside.com 2019 - 2024. All rights reserved.