前端调用阿里云接口语音合成演示
前端页面(html)
<!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) {// 构造代理请求URLconst 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)
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}`);
});
实现原理
-
跨域处理:
- 代理服务器设置CORS响应头(
Access-Control-Allow-Origin: *
) - 处理OPTIONS预检请求
- 代理服务器设置CORS响应头(
-
请求转发:
- 前端调用本地代理接口(http://localhost:3000/tts-proxy)
- 代理服务器转发请求到阿里云API
- 代理服务器将音频数据返回给前端
-
错误处理:
- 捕获代理服务和阿里云API的错误
- 返回详细错误信息给前端
使用步骤
- 安装依赖:
npm install express axios
- 启动代理服务:
node server.js
- 访问前端页面:
http://localhost:3000/index.html
- 输入参数并合成语音