Telegram机器人开发:Node.js保存OGG音频缓冲区至本地并播放
如何在Node.js中正确保存Telegram机器人接收的OGG音频并实现播放
我正在开发带语音转文字功能的Telegram机器人,用户发语音消息时,Node.js服务器会收到OGG格式的音频缓冲区(示例:<Buffer 4f 67 67 53 00 02 00 00 00 00 00 00 00 00 f9 48 6d 42 00 00 00 00 99 20 78 f9 01 13 4f 70 75 73 48 65 61 64 01 01 38 01 80 bb 00 00 00 00 00 4f 67 67 ... 6716 more bytes>)。我需要把这个OGG音频保存到本地,同时实现播放功能,下面是我尝试的代码:
const fileUrl = await bot.getFileLink(msg.voice.file_id); const response = await axios({ url: fileUrl, method: 'GET', responseType: 'arraybuffer' }); const buffer = Buffer.from(response.data); var arrayBuffer = new Uint8Array(buffer).buffer; var blob = new Blob([arrayBuffer], { type: 'audio/ogg' }); var url = URL.createObjectURL(blob); const filePath = './voice/'; const fileName = 'mine.ogg'; fs.writeFile(filePath+fileName, buffer.toString(), (err) => { if (err) { console.error('Error saving OGG file:', err); // Handle error appropriately (send error response to client) } else { console.log('OGG file saved successfully!'); // Send success response to client (optional) } });
问题分析与修复方案
1. 修复文件保存逻辑
你当前代码的核心问题是用buffer.toString()将二进制Buffer转为UTF-8字符串写入文件,这会破坏OGG的二进制结构,导致文件损坏。直接写入原始Buffer即可,同时建议使用Promise风格的文件操作,和你的异步代码保持一致:
const fs = require('fs').promises; const path = require('path'); // 保留前面获取buffer的代码:获取fileUrl、axios请求、生成buffer // 确保保存目录存在 await fs.mkdir('./voice', { recursive: true }); // 拼接路径(用path.join避免跨平台路径问题) const savePath = path.join('./voice', 'mine.ogg'); try { await fs.writeFile(savePath, buffer); console.log('OGG文件保存成功!'); } catch (err) { console.error('保存OGG文件出错:', err); }
2. 实现本地播放功能
Node.js环境中可以通过两种方式实现音频播放:
方式一:依赖系统播放器(简单快捷)
使用play-sound库,它会调用系统默认的音频播放器:
- 安装依赖:
npm install play-sound
- 播放代码:
const player = require('play-sound')({}); player.play(savePath, (err) => { if (err) console.error('播放音频出错:', err); });
方式二:直接在Node.js中解码播放(无需外部播放器)
使用speaker+ogg+vorbis库,直接解码并播放OGG音频:
- 安装依赖:
npm install speaker ogg vorbis
- 播放代码:
const { OggDemuxer } = require('ogg'); const { Decoder } = require('vorbis'); const Speaker = require('speaker'); const fs = require('fs'); const stream = fs.createReadStream(savePath); const oggDemuxer = new OggDemuxer(); const vorbisDecoder = new Decoder(); // 管道流处理:读取文件 -> 解封装OGG -> 解码Vorbis -> 播放 stream.pipe(oggDemuxer); oggDemuxer.on('stream', (oggStream) => { oggStream.pipe(vorbisDecoder); }); vorbisDecoder.pipe(new Speaker({ channels: 1, // Telegram语音通常为单声道 bitDepth: 16, // 位深度 sampleRate: 48000 // Telegram语音采样率多为48kHz })); // 错误处理 vorbisDecoder.on('error', (err) => { console.error('音频解码出错:', err); });
内容的提问来源于stack exchange,提问作者MD. JAHIDUL ISLAM
相关产品推荐
相关产品推荐

