Node.js 集成百度语音

复制代码
// ==================== backend-proxy.js ====================
// 安装依赖:npm install express cors node-fetch
// 运行:node backend-proxy.js

const express = require('express');
const cors = require('cors');
const fetch = require('node-fetch');

const app = express();
const PORT = 3001;

// 百度 API 配置
const BAIDU_CONFIG = {
  API_KEY: "YOUR_API_KEY",        // 替换为你的 API Key
  SECRET_KEY: "YOUR_SECRET_KEY",  // 替换为你的 Secret Key
};

// 允许跨域
app.use(cors());
app.use(express.json());

// Token 缓存
let cachedToken = null;
let tokenExpireTime = 0;

// 获取百度 Access Token
async function getBaiduToken() {
  if (cachedToken && Date.now() < tokenExpireTime) {
    return cachedToken;
  }

  try {
    const response = await fetch(
      `https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${BAIDU_CONFIG.API_KEY}&client_secret=${BAIDU_CONFIG.SECRET_KEY}`,
      { method: 'POST' }
    );

    const data = await response.json();

    if (data.access_token) {
      cachedToken = data.access_token;
      tokenExpireTime = Date.now() + (data.expires_in - 60) * 1000;
      return cachedToken;
    } else {
      throw new Error('Failed to get token: ' + JSON.stringify(data));
    }
  } catch (error) {
    console.error('Token request error:', error);
    throw error;
  }
}

// 代理接口:获取语音
app.post('/api/tts', async (req, res) => {
  try {
    const { text, lang = 'zh-CN' } = req.body;

    if (!text) {
      return res.status(400).json({ error: 'Text is required' });
    }

    // 获取 token
    const token = await getBaiduToken();

    // 语音参数
    const voiceParams = {
      per: lang === 'zh-CN' ? 4 : 1,  // 发音人
      spd: 5,  // 语速
      pit: 5,  // 音调
      vol: 5,  // 音量
    };

    // 调用百度 TTS API
    const response = await fetch('https://tsn.baidu.com/text2audio', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: new URLSearchParams({
        tex: text,
        tok: token,
        cuid: 'web_client',
        ctp: 1,
        lan: lang === 'zh-CN' ? 'zh' : 'en',
        ...voiceParams,
      }),
    });

    if (response.ok) {
      // 返回音频流
      const audioBuffer = await response.buffer();
      res.set('Content-Type', 'audio/mp3');
      res.send(audioBuffer);
    } else {
      const errorText = await response.text();
      res.status(500).json({ error: 'Baidu TTS error', details: errorText });
    }
  } catch (error) {
    console.error('TTS request error:', error);
    res.status(500).json({ error: error.message });
  }
});

// 健康检查
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

app.listen(PORT, () => {
  console.log(`✅ Baidu TTS Proxy running at http://localhost:${PORT}`);
  console.log(`   API endpoint: http://localhost:${PORT}/api/tts`);
});

完成!现在给你完整的部署步骤:

📦 完整部署方案

1️⃣ 创建后端代理服务

创建文件 backend-proxy.js(代码已在上面的 artifact 中)

bash

复制代码
# 初始化项目
npm init -y

# 安装依赖
npm install express cors node-fetch

# 修改 backend-proxy.js 中的 API_KEY 和 SECRET_KEY

# 启动服务
node backend-proxy.js

2️⃣ 前端配置

在前端代码中,确保 PROXY_URL 指向你的后端:

javascript

复制代码
const BAIDU_TTS_CONFIG = {
  PROXY_URL: "http://localhost:3001/api/tts",  // 开发环境
  // 生产环境改为: "https://your-domain.com/api/tts"
};
```

### 3️⃣ 工作流程
```
前端调用 speak()
    ↓
尝试浏览器在线语音 (Google/Microsoft)
    ↓
网络正常?
├─ 是 → ✅ 使用在线语音(不访问百度)
└─ 否 → 检测到失败(3秒超时)
    ↓
尝试本地语音
    ↓
有本地语音?
├─ 是 → ✅ 使用本地语音(不访问百度)
└─ 否 → 🎤 调用后端代理
    ↓
后端代理 → 百度 API → 返回音频
    ↓
前端播放音频 ✅

🚀 生产环境部署

选项 A:部署到 Vercel/Railway(推荐)

javascript

复制代码
// vercel.json 或 railway.json
{
  "version": 2,
  "builds": [
    {
      "src": "backend-proxy.js",
      "use": "@vercel/node"
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "backend-proxy.js"
    }
  ]
}

选项 B:使用 Serverless 函数

如果你使用的是 Next.js,可以创建 API 路由:

javascript

复制代码
// pages/api/tts.js
export default async function handler(req, res) {
  // 后端代理逻辑
}

✅ 优势

  1. 无 CORS 问题 - 通过后端代理解决
  2. API 密钥安全 - 密钥保存在后端
  3. 完整降级机制 - 在线语音 → 本地语音 → 百度 TTS
  4. 网络正常时不影响 - 只在必要时才调用百度

🧪 测试

bash

复制代码
# 测试后端代理
curl -X POST http://localhost:3001/api/tts \
  -H "Content-Type: application/json" \
  -d '{"text":"你好世界","lang":"zh-CN"}' \
  --output test.mp3

# 播放测试
# macOS: open test.mp3
# Linux: xdg-open test.mp3
# Windows: start test.mp3

这样就完美解决了 CORS 问题,并且只在真正需要时才使用百度 TTS!

相关推荐
q***0562 小时前
使用Node.js搭配express框架快速构建后端业务接口模块Demo
node.js·express
哆啦A梦15882 小时前
40 token
前端·vue.js·node.js
喜欢踢足球的老罗3 小时前
Sequelize vs Prisma:现代 Node.js ORM 深度技术解析与实战指南
node.js·prisma·sequelize
xiaoxue..3 小时前
用 Node.js 手动搭建 HTTP 服务器:从零开始的 Web 开发之旅!
服务器·前端·http·node.js
哆啦A梦15884 小时前
46 修改购物车数据
前端·vue.js·node.js
孟陬4 小时前
在浏览器控制台中优雅地安装 npm 包 console.install('lodash')
javascript·node.js
q***97915 小时前
从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CICD)
docker·容器·node.js
2503_9284115616 小时前
11.11 Express-generator和文件上传和身份认证
数据库·node.js·express