前端调用阿里云接口语音合成演示

前端页面(html)

javascript 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>阿里云语音合成演示</title>
    <style>
        /* 样式代码保持不变(见原始代码) */
    </style>
</head>
<body>
    <div class="container">
        <!-- 页面结构保持不变(见原始代码) -->
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const synthesizeBtn = document.getElementById('synthesize');
            const audioPlayer = document.getElementById('audioPlayer');
            const statusDiv = document.getElementById('status');

            synthesizeBtn.addEventListener('click', async () => {
                // 获取输入参数
                const params = {
                    appkey: document.getElementById('appkey').value.trim(),
                    token: document.getElementById('token').value.trim(),
                    text: document.getElementById('text').value.trim(),
                    voice: document.getElementById('voice').value,
                    volume: document.getElementById('volume').value,
                    speed: document.getElementById('speed').value
                };

                // 参数验证逻辑...

                synthesizeBtn.disabled = true;
                showStatus('正在合成语音,请稍候...', 'info');

                try {
                    // 调用代理服务
                    const audioData = await fetchAudio(params);
                    const audioBlob = new Blob([audioData], { type: 'audio/wav' });
                    audioPlayer.src = URL.createObjectURL(audioBlob);
                    showStatus('语音合成成功!', 'success');
                } catch (error) {
                    showStatus(`语音合成失败: ${error.message}`, 'error');
                } finally {
                    synthesizeBtn.disabled = false;
                }
            });

            async function fetchAudio(params) {
                // 构造代理请求URL
                const proxyUrl = 'http://localhost:3000/tts-proxy';
                const query = new URLSearchParams({
                    ...params,
                    text: params.text // 自动编码
                }).toString();
                
                const response = await fetch(`${proxyUrl}?${query}`);
                
                if (!response.ok) {
                    const errorText = await response.text();
                    throw new Error(`请求失败: ${response.status} ${errorText}`);
                }
                
                return await response.arrayBuffer();
            }

            function showStatus(message, type) {
                /* 状态显示逻辑 */
            }
        });
    </script>
</body>
</html>

前端直接调用阿里云语音合成API时,通常会遇到跨域请求限制(CORS)。浏览器出于安全考虑会阻止这类跨域请求。

解决方案

搭建Node.js代理服务器作为前端和阿里云API之间的中转层,解决跨域问题。以下是完整实现:

代理服务器实现(Node.js)
javascript 复制代码
const express = require("express");
const axios = require("axios");
const app = express();

// 请求日志中间件
app.use((req, res, next) => {
  console.log(`${new Date().toLocaleString()} - ${req.method} ${req.url}`);
  next();
});

// 处理预检请求
app.options("/tts-proxy", (req, res) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
  res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, Content-Length, X-Requested-With");
  res.sendStatus(204);
});

// 语音合成代理接口
app.get("/tts-proxy", async (req, res) => {
  res.header("Access-Control-Allow-Origin", "*");
  
  try {
    const { appkey, token, text, voice, volume, speed } = req.query;
    const apiUrl = `https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts?appkey=${appkey}&token=${token}&text=${encodeURIComponent(text)}&voice=${voice}&volume=${volume}&speech_rate=${speed}&format=wav`;
    
    const response = await axios({
      method: "post",
      url: apiUrl,
      responseType: "arraybuffer",
    });

    res.set("Content-Type", "audio/wav");
    res.send(response.data);
  } catch (error) {
    console.error("代理错误:", error);
    
    if (error.response) {
      console.error("阿里云错误状态:", error.response.status);
      console.error("阿里云错误数据:", error.response.data.toString());
    }

    res.status(500).json({
      error: "语音合成失败",
      details: error.message,
    });
  }
});

// 启动服务
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`代理服务运行在 http://localhost:${PORT}`);
});

实现原理

  1. 跨域处理

    • 代理服务器设置CORS响应头(Access-Control-Allow-Origin: *
    • 处理OPTIONS预检请求
  2. 请求转发

  3. 错误处理

    • 捕获代理服务和阿里云API的错误
    • 返回详细错误信息给前端

使用步骤

  1. 安装依赖:

    javascript 复制代码
    npm install express axios
  2. 启动代理服务:

    javascript 复制代码
    node server.js
  3. 访问前端页面:

    javascript 复制代码
    http://localhost:3000/index.html
  4. 输入参数并合成语音

相关推荐
前端雾辰25 分钟前
Uniapp APP 端实现 TCP Socket 通信(ZPL 打印实战)
前端
无羡仙32 分钟前
虚拟列表:怎么显示大量数据不卡
前端·react.js
云水边37 分钟前
前端网络性能优化
前端
用户516816614584142 分钟前
[微前端 qiankun] 加载报错:Target container with #child-container not existed while devi
前端
东北南西1 小时前
设计模式-工厂模式
前端·设计模式
HANK1 小时前
ECharts高效实现复杂图表指南
前端·vue.js
入秋1 小时前
Linux服务器安装部署 Nginx、Redis、PostgreSQL、Docker
linux·前端
acocosum1 小时前
毫米波雷达基础知识学习报告
前端
程序员鱼皮1 小时前
这套 Java 监控系统太香了!我连夜给项目加上了
java·前端·ai·程序员·开发·软件开发
Juchecar1 小时前
Vue3 响应式 ref 和 reactive 原理详解及选择建议
前端·vue.js