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!

相关推荐
行走的陀螺仪7 小时前
Vite & Webpack 插件/Loader 封装完全指南
前端·webpack·node.js·vite·前端工程化·打包构建
昨日之日20067 小时前
Fun-ASR - 多语言多方言的高精度语音识别软件 支持50系显卡 一键整合包下载
人工智能·音视频·语音识别
源去_云走8 小时前
自建 Iconfy API 服务:解决国内访问不稳定问题
前端·容器·npm·node.js
第六五10 小时前
语音信号的时域、频域与时频域特征
人工智能·语音识别
小oo呆11 小时前
【学习心得】基于FunASR推理的SenseVoiceSmall模型来实现语音识别
人工智能·语音识别
旧梦星轨13 小时前
掌握 Vite 环境配置:从 .env 文件到运行模式的完整实践
前端·前端框架·node.js·vue·react
Mryan200514 小时前
基于 NAO 机器人的智能语音交互系统的设计与实现
机器人·语音识别
qq_3482318515 小时前
面向初学者到进阶者的 Node.js 学习指南
node.js
大猫和小黄15 小时前
Windows 下使用 NVM 管理多个 Node.js 版本
windows·node.js
Chase_______15 小时前
【保姆级】Node.js 最新安装教程,附环境变量配置
node.js