当前位置: 首页 > news >正文

Node.js 集成百度语音

// ==================== backend-proxy.js ====================
// 安装依赖:npm install express cors node-fetch
// 运行:node backend-proxy.jsconst 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 KeySECRET_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' });}// 获取 tokenconst token = await getBaiduToken();// 语音参数const voiceParams = {per: lang === 'zh-CN' ? 4 : 1,  // 发音人spd: 5,  // 语速pit: 5,  // 音调vol: 5,  // 音量};// 调用百度 TTS APIconst 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!

http://www.dtcms.com/a/601395.html

相关文章:

  • 求一个网站开发接项目的平台做网站的外包需要分享客户信息
  • 怎么用PS做网站横幅wordpress 抽奖
  • 【开题答辩全过程】以 基于Vue.js和Node.js的在线旅游平网站的设计和实现为例,包含答辩的问题和答案
  • MySQL快速入门——用户管理
  • 中咨城建设计南京网站网站建设南昌
  • 大连网站制作流程在哪里可以免费自学seo课程
  • [智能体设计模式]第3章 并行化
  • Prisma 原生 SQL 多表联查完整指南
  • 哪个网站原创文章旅游集团网站建设
  • AI搜索不提你的品牌?从GEO诊断开始
  • Elasticsearch 7.6 安装 Jieba 中文分词插件完整教程
  • OpenCV 加载时出现 `no opencv_java451 in java.library.path` 错误
  • 【CCF-CSP】05-02日期计算
  • 如何实施网站推广wordpress您的密码重设链接无效
  • GlobalFoundries从台积电获得GaN技术许可
  • ModelEngine 智能体开发实战:2 个月 3 个项目从知识库到多 Agent 协作完整指南
  • TensorFlow深度学习实战(43)——TensorFlow.js
  • 异世界传奇:OSPF王国与链路状态信使协议
  • IB 比 RoCE 更快的底层逻辑-深度拆解
  • LangWBC:基于端到端学习的语言导向型人形机器人全身控制
  • 网站建设 国外无需下载的网站
  • 技术支持 贵阳贵阳网站建设wordpress主题图片
  • 域名注册商怎么查南宁优化网站网络服务
  • 文山城乡建设部网站首页东莞做网站优化
  • CSS 动画与变换属性详解
  • 11.12 LeetCode 题目汇总与解题思路
  • 【代码审计】RuoYi-4.7.34.7.8 定时任务RCE 漏洞分析
  • 数学图论的艺术:解码最小公倍数图中的连通奥秘
  • 如何有效解决Windows 11界面卡顿问题,提升操作流畅度
  • 网站开发iso9001有哪些网页游戏网站