如何播放Amazon Lex SDK识别话语返回的audioStream音频流
播放Amazon Lex返回audioStream的实现方案
返回的audioStream本质是Node.js的可读流(Http2Stream),你打印出来的只是流的状态元信息,不是实际音频二进制内容,需要先读取流内的音频数据,再根据你的运行环境选择播放方式。
场景1:Node.js服务端本地直接播放
第一步:读取流中的音频数据
Node.js 16+ 可以直接用内置的流工具把音频流转成二进制Buffer:
const { buffer: streamToBuffer } = require('node:stream/consumers'); // 在你拿到Lex响应的位置添加 const response = await client.send(command); // 等待流读取完成,拿到完整mp3音频Buffer const audioBuffer = await streamToBuffer(response.audioStream);
低版本Node可以手动监听流事件拼接数据:
const audioChunks = []; for await (const chunk of response.audioStream) { audioChunks.push(chunk); } const audioBuffer = Buffer.concat(audioChunks);
第二步:播放音频
最易落地的方案是借助play-sound调用系统默认播放器播放,先安装依赖:
npm i play-sound
播放逻辑:
const fs = require('node:fs'); const player = require('play-sound')(); // 临时存为mp3文件 const tempAudioPath = './temp-lex-response.mp3'; fs.writeFileSync(tempAudioPath, audioBuffer); // 调用系统播放器播放,播完自动删除临时文件 player.play(tempAudioPath, (playErr) => { if (playErr) console.error('播放出错:', playErr); fs.unlinkSync(tempAudioPath); });
注意:桌面版Windows/macOS默认自带支持mp3播放的组件,Linux服务器环境需要提前安装
mpg123或ffmpeg才能正常播放。
场景2:Node.js作为后端,给前端网页返回音频播放
这是搭建聊天机器人的最常用场景,不需要在服务端播放,直接把音频流转发给前端即可,延迟更低还省服务端内存:
如果用Express这类Web框架,直接把Lex返回的音频流通过pipe转发给HTTP响应:
// 后端接口示例(Express) app.get('/api/lex/chat', async (req, res) => { // 原有Lex参数构造、请求发送逻辑 const command = new RecognizeUtteranceCommand(lexparams); const response = await client.send(command); // 设置正确的音频响应头 res.set({ 'Content-Type': 'audio/mpeg', 'Transfer-Encoding': 'chunked' }); // 直接把音频流 pipe 到前端响应,支持边接收边传输 response.audioStream.pipe(res); });
前端调用接口直接用原生Audio对象播放即可:
// 前端页面代码 const lexAudio = new Audio('/api/lex/chat'); // 触发播放(注意需要在用户交互事件里调用play,避免被浏览器自动播放策略拦截) lexAudio.play();
常见踩坑点
- 你当前参数里
responseContentType设为audio/mpeg,返回的是mp3格式音频,兼容性最好;如果改成audio/pcm会返回原始PCM数据,播放时需要手动指定16k采样率、单声道参数,配置错误会出现杂音,新手不建议修改。 - 不需要等整个音频流全部接收完成再播放,不管是服务端本地播放还是转发给前端,都可以做边收边播的流式处理,能大幅降低对话响应延迟。
- 不要直接操作返回的Http2Stream实例对象,它只是流的控制句柄,实际音频内容要从流中读取才能拿到。
内容的提问来源于stack exchange,提问作者Felix Christo
相关产品推荐
相关产品推荐

