FireRedASR Pro与Node.js环境配置:构建语音交互后端服务

如果你正在用Node.js开发应用,想给产品加上语音识别的能力,比如做个语音助手、会议记录工具,或者让用户能用语音来操作,那FireRedASR Pro是个挺不错的选择。它提供了现成的API,识别准确率不错,接入起来也快。

今天这篇内容,就是带你一步步在Node.js项目里,把FireRedASR Pro的语音转文字功能给接进去。你不用太担心,整个过程不复杂,我会把每一步都拆开讲清楚,从安装必要的库,到写一个能处理音频、调用接口、返回文字结果的服务函数,最后再给你一个能直接用在Web应用里的Express路由例子。跟着走一遍,你就能在自己的项目里用起来了。

1. 开始前的准备工作

在动手写代码之前,我们得先把“舞台”搭好。这里主要就是两件事:确保你的Node.js环境没问题,然后去FireRedASR Pro那边拿到进入的“钥匙”。

1.1 检查你的Node.js环境

首先,打开你的终端或者命令行工具,输入下面这个命令,看看Node.js的版本。

node --version

理想情况下,你应该能看到一个版本号,比如 v18.x.x 或者 v20.x.x。FireRedASR Pro的API调用本身对版本没有特别苛刻的要求,但使用一个比较新的长期支持版本(LTS)会避免很多潜在的兼容性问题。如果你的版本太老(比如低于v16),建议去Node.js官网下载安装一个新版本。

接着,我们创建一个新的项目目录,并初始化它。这就像给你的新项目建立一个专属的文件夹和一份“说明书”。

# 创建一个新的项目文件夹,名字你可以自己定,比如 asr-demo
mkdir asr-demo
# 进入这个文件夹
cd asr-demo
# 初始化一个新的Node.js项目,一路按回车用默认设置就行
npm init -y

执行完 npm init -y 后,你会看到文件夹里多了一个 package.json 文件,它记录了项目的基本信息和依赖。

1.2 获取FireRedASR Pro的API密钥

接下来,你需要去FireRedASR Pro的官方网站注册一个账号。这个过程通常很简单,就是填邮箱、设密码之类的。

注册登录之后,在控制台或者个人中心里,你应该能找到“API密钥”或“Access Key”这类管理页面。点击创建一个新的密钥,系统会生成一串看起来像乱码的字符串,比如 sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx这串密钥非常重要,就像是你的个人密码,千万不要直接写在代码里或者上传到公开的代码仓库(如GitHub)

我们稍后会把它放在一个安全的地方。

2. 安装必要的工具库

我们的Node.js项目需要一些帮手来完成HTTP请求、处理环境变量这些任务。我们来把它们请进来。

在刚才的项目目录下,运行下面的安装命令:

npm install axios dotenv

简单解释一下这两个库是干嘛的:

  • axios:一个非常好用的HTTP客户端库。我们将用它来向FireRedASR Pro的API服务器发送请求和接收响应。它比Node.js原生的 http 模块用起来更简单,功能也更强大。
  • dotenv:一个零依赖的模块。它能帮我们轻松地从项目根目录的 .env 文件里加载环境变量。这样,我们就能把敏感的API密钥放在这个文件里,而不是硬编码在代码中。

安装完成后,你的 package.json 文件里的 dependencies 部分就会看到它们了。

3. 安全地存储API密钥

还记得我们强调不能把密钥写死在代码里吗?现在我们来实践这个安全准则。

在你的项目根目录(和 package.json 同级),创建一个名为 .env 的新文件。注意,文件名前面有一个点。然后在里面写入你的密钥:

FIREREDASR_API_KEY=你的API密钥在这里

请把 你的API密钥在这里 替换成你从控制台拿到的那一串真实密钥。

重要提示

  • 这个 .env 文件必须被添加到 .gitignore 文件中,确保它不会被意外提交到Git仓库。如果你的项目还没有 .gitignore 文件,创建一个,并在里面加上一行 .env
  • 在团队协作时,你可以提供一个 .env.example 文件,里面只写变量名不写真实值(如 FIREREDASR_API_KEY=),让队友根据自己的密钥去填充。

4. 编写核心识别函数

现在进入核心部分,我们来写一个JavaScript函数,它负责把本地的音频文件“送”给FireRedASR Pro,并把“翻译”好的文字带回来。

在你的项目里创建一个新文件,比如叫 asrService.js。我们将在这个文件里编写所有逻辑。

4.1 引入依赖并加载环境变量

文件开头,我们先引入需要的模块,并让 dotenv 读取我们的 .env 文件。

// asrService.js
const axios = require('axios');
const fs = require('fs').promises; // 使用Promise版本的fs模块,方便异步操作
const path = require('path');
require('dotenv').config(); // 加载 .env 文件中的变量到 process.env

// 从环境变量中读取API密钥和基础URL(假设有的话)
const API_KEY = process.env.FIREREDASR_API_KEY;
const API_BASE_URL = process.env.FIREREDASR_API_BASE_URL || 'https://api.fireredasr.example.com'; // 请替换为实际API地址

注意,API_BASE_URL 需要替换成FireRedASR Pro官方提供的真实API端点地址。这里我用了一个示例地址。

4.2 构建一个通用的识别函数

这个函数是主力,它接收一个音频文件的路径,然后完成“读取文件 -> 发送请求 -> 解析结果”的全过程。

/**
 * 使用FireRedASR Pro识别音频文件
 * @param {string} audioFilePath - 本地音频文件的路径
 * @param {object} options - 可选参数,如语言、模型等
 * @returns {Promise<string>} - 识别出的文本
 */
async function transcribeAudio(audioFilePath, options = {}) {
  // 1. 读取音频文件
  let audioBuffer;
  try {
    audioBuffer = await fs.readFile(audioFilePath);
    console.log(`✅ 音频文件读取成功: ${path.basename(audioFilePath)}`);
  } catch (error) {
    console.error(`❌ 读取音频文件失败: ${error.message}`);
    throw new Error(`无法读取文件: ${audioFilePath}`);
  }

  // 2. 准备请求数据
  // 通常API接受FormData格式,在Node.js中我们可以用axios的multipart/form-data方式
  const formData = new FormData();
  // 注意:Node.js环境没有原生的FormData,我们需要使用form-data库或axios的替代方案。
  // 这里我们使用一个更通用的方法:将文件作为Buffer,并设置正确的Content-Type。
  // 假设API接受base64或直接二进制流,我们查看API文档决定。
  // 为了通用性,我们假设API接受一个包含文件的multipart请求。

  // 由于Node.js中没有浏览器环境的FormData,我们使用axios内置的multipart支持
  const requestData = new FormData();
  const fileStream = await fs.createReadStream(audioFilePath); // 创建文件流
  requestData.append('file', fileStream); // 'file'字段名需根据API文档调整
  // 可以追加其他参数
  if (options.language) {
    requestData.append('language', options.language);
  }
  if (options.model) {
    requestData.append('model', options.model);
  }

  // 3. 配置请求头
  const config = {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      ...requestData.getHeaders(), // 获取multipart/form-data的正确头部
    },
    timeout: 30000, // 设置30秒超时,长音频可能需要更久
  };

  // 4. 发送POST请求到识别端点
  const apiUrl = `${API_BASE_URL}/v1/audio/transcriptions`; // 端点路径需根据实际API调整
  console.log(`🚀 正在发送识别请求...`);

  try {
    const response = await axios.post(apiUrl, requestData, config);
    console.log(`🎉 识别请求成功!`);

    // 5. 解析响应
    // 响应结构取决于API,常见的是返回一个JSON,其中包含text字段
    const result = response.data;
    // 假设返回格式为 { text: "识别出的文字", ... }
    if (result && result.text) {
      return result.text;
    } else {
      console.warn('⚠️ API响应格式与预期不符:', result);
      // 尝试其他可能的字段,或者返回原始数据
      return JSON.stringify(result);
    }
  } catch (error) {
    // 6. 错误处理
    console.error(`❌ 识别请求失败:`);
    if (error.response) {
      // 请求已发出,服务器返回了错误状态码(如4xx, 5xx)
      console.error(`   状态码: ${error.response.status}`);
      console.error(`   响应数据:`, error.response.data);
      throw new Error(`API请求失败 (${error.response.status}): ${JSON.stringify(error.response.data)}`);
    } else if (error.request) {
      // 请求已发出,但没有收到响应
      console.error(`   无响应 received: ${error.message}`);
      throw new Error(`网络错误,未收到API响应: ${error.message}`);
    } else {
      // 请求配置出错
      console.error(`   请求配置错误: ${error.message}`);
      throw new Error(`请求配置错误: ${error.message}`);
    }
  }
}

这个函数看起来有点长,但逻辑是清晰的。它做了几件关键事:安全地读取文件、按照API要求格式组装请求、带上密钥去“敲门”、然后处理返回的结果或错误。你需要根据FireRedASR Pro实际的API文档,微调其中的端点URL、请求字段名和响应解析逻辑。

4.3 添加一个便捷的测试函数

为了方便我们立刻测试,可以在同一个文件里加一个简单的测试函数。

/**
 * 快速测试函数
 */
async function quickTest() {
  const testAudioPath = path.join(__dirname, 'test-audio.wav'); // 假设项目根目录有个测试音频
  console.log(`开始测试识别: ${testAudioPath}`);

  try {
    const text = await transcribeAudio(testAudioPath, {
      language: 'zh-CN', // 示例:指定中文
      // model: 'pro' // 示例:指定使用专业模型
    });
    console.log('\n--- 识别结果 ---');
    console.log(text);
    console.log('--- 结束 ---\n');
  } catch (error) {
    console.error('测试失败:', error.message);
  }
}

// 如果这个文件被直接运行(node asrService.js),则执行测试
if (require.main === module) {
  quickTest();
}

// 导出函数,方便其他模块使用
module.exports = {
  transcribeAudio
};

这样,你可以在终端运行 node asrService.js,如果当前目录下有一个 test-audio.wav 文件,它就会尝试识别并打印结果。

5. 集成到Web服务(Express.js示例)

大部分时候,我们的Node.js后端是一个Web服务。下面我们看看如何把上面的识别功能,做成一个HTTP API接口,这样前端或其他服务就能通过网络调用了。

5.1 创建Express应用并安装依赖

首先,确保安装了Express和用于处理文件上传的中间件 multer

npm install express multer

5.2 编写主应用文件

创建一个新文件,比如叫 app.js,作为我们Web服务的入口。

// app.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const { transcribeAudio } = require('./asrService'); // 导入我们写好的识别函数
require('dotenv').config();

const app = express();
const port = process.env.PORT || 3000;

// 配置multer处理文件上传
// 这里简单起见,将上传的文件保存在内存中(适合小文件)
// 对于大文件,你应该配置磁盘存储
const upload = multer({
  storage: multer.memoryStorage(),
  limits: {
    fileSize: 50 * 1024 * 1024, // 限制50MB
  },
  fileFilter: (req, file, cb) => {
    // 只接受音频文件
    const allowedMimes = ['audio/wav', 'audio/mpeg', 'audio/mp4', 'audio/webm'];
    if (allowedMimes.includes(file.mimetype)) {
      cb(null, true);
    } else {
      cb(new Error('不支持的文件类型,请上传音频文件(WAV, MP3等)'), false);
    }
  }
});

// 一个简单的健康检查端点
app.get('/', (req, res) => {
  res.json({ message: 'FireRedASR Pro 语音识别服务运行中', timestamp: new Date().toISOString() });
});

// 核心的语音识别API端点
app.post('/api/transcribe', upload.single('audio'), async (req, res) => {
  // upload.single('audio') 表示接收一个名为‘audio’的文件字段
  if (!req.file) {
    return res.status(400).json({ error: '请提供音频文件' });
  }

  console.log(`收到识别请求,文件名: ${req.file.originalname}, 大小: ${req.file.size} bytes`);

  // 由于我们的transcribeAudio函数接收文件路径,但multer返回的是Buffer。
  // 我们需要先将Buffer写入一个临时文件,或者修改transcribeAudio函数以支持Buffer输入。
  // 这里我们采用临时文件方案(生产环境应考虑更安全的临时文件管理)。
  const temp = require('temp');
  const fs = require('fs').promises;
  temp.track(); // 自动跟踪并清理临时文件

  try {
    // 创建临时文件
    const tempFile = await temp.path({ suffix: path.extname(req.file.originalname) || '.wav' });
    await fs.writeFile(tempFile, req.file.buffer);

    console.log(`创建临时文件: ${tempFile}`);

    // 调用识别函数
    // 你可以从请求体(req.body)中获取其他参数,如语言
    const language = req.body.language || 'zh-CN';
    const transcribedText = await transcribeAudio(tempFile, { language });

    // 返回识别结果
    res.json({
      success: true,
      text: transcribedText,
      filename: req.file.originalname
    });

  } catch (error) {
    console.error('处理请求时出错:', error);
    res.status(500).json({
      success: false,
      error: error.message || '语音识别处理失败'
    });
  }
});

// 全局错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  if (err instanceof multer.MulterError) {
    // Multer相关的错误(如文件大小超限)
    return res.status(400).json({ error: `文件上传错误: ${err.message}` });
  }
  res.status(500).json({ error: '服务器内部错误' });
});

// 启动服务器
app.listen(port, () => {
  console.log(`🚀 语音识别服务已启动,监听端口: ${port}`);
  console.log(`  健康检查: http://localhost:${port}`);
  console.log(`  识别端点: POST http://localhost:${port}/api/transcribe`);
});

这个 app.js 文件创建了一个简单的Express服务器。它提供了两个接口:

  1. GET /:一个简单的状态检查。
  2. POST /api/transcribe:核心接口。它接受一个表单上传的音频文件(字段名需为 audio),可选的 language 参数,然后调用我们之前写好的 transcribeAudio 函数进行处理,最后将识别结果以JSON格式返回。

5.3 运行并测试你的服务

现在,让我们启动这个服务,并模拟一个请求来测试它。

首先,在终端运行:

node app.js

你应该能看到服务启动成功的日志。

然后,我们可以用 curl 命令来测试(假设你有一个叫 test.wav 的音频文件在当前目录):

curl -X POST http://localhost:3000/api/transcribe \
  -F "audio=@./test.wav" \
  -F "language=zh-CN"

如果一切顺利,你会收到一个JSON响应,里面包含了识别出的文字。

6. 总结

走完这一趟,你应该已经成功地在Node.js环境里,把FireRedASR Pro的语音识别能力集成进来了。我们从最基础的安装和配置开始,写了一个健壮的核心识别函数,处理了文件读取、网络请求和错误情况,最后还把它包装成了一个随时可用的Web API。

整个过程的关键,其实就是几个清晰的步骤:准备好环境变量来保护密钥,用axios库去和远程API对话,再根据API的“规矩”(文档)来组装请求和解析响应。当你把它集成到像Express这样的Web框架里时,就变成了一个标准的后端服务接口。

实际用的时候,你可能还会考虑更多,比如怎么处理更长的音频、怎么管理上传的临时文件、怎么加入身份验证、或者怎么把识别任务放到后台队列去处理以防请求超时。这些都可以在你现在搭建好的这个基础上,一步步去完善。希望这个指南能帮你快速起步,在你下一个需要“听见”用户声音的项目里,派上用场。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐