使用discord.js录制Discord语音生成损坏Opus文件求助
解决Discord.js录制语音生成损坏Opus文件的问题
问题根源
你直接将Discord语音接收器返回的Opus帧写入文件,但Opus编码的音频需要封装在Ogg容器中才能被播放器(如VLC)识别。原始Opus帧没有文件头信息,导致播放器无法解析数据,最终表现为文件损坏、无有效内容。另外你引入了OpusEncoder但并未实际使用——Discord语音流本身已经是Opus编码的,不需要二次编码。
修复方案
使用@discordjs/voice包提供的OggOpusWriter来封装Opus帧,它会自动处理Ogg容器的头信息和帧封装。如果未安装该包,先执行安装:
npm install @discordjs/voice
修改后的代码
const { OggOpusWriter } = require('@discordjs/voice'); const fs = require('fs'); function transcriptionDevice(userID, voiceConn, talkingUser, time) { console.log('1. Start speaking event triggered'); // 确保录音目录存在 if (!fs.existsSync('./recordings')) { fs.mkdirSync('./recordings'); } const opusPath = `./recordings/${userID}_${time}.opus`; const fileStream = fs.createWriteStream(opusPath); // 初始化OggOpusWriter,匹配Discord语音格式:48kHz采样率、2声道 const oggWriter = new OggOpusWriter({ channelCount: 2, sampleRate: 48000, }); console.log('2. Created Ogg Opus writer and file stream'); const { receiver } = voiceConn; const audioStream = receiver.subscribe(userID, { end: { behavior: 'manual' // 手动控制流结束,避免提前断开 } }); console.log('3. Subscribed to user audio stream'); // 通过管道自动处理流数据传递与封装 audioStream.pipe(oggWriter).pipe(fileStream); audioStream.on('end', () => { console.log("5. Audio stream ended"); // 结束OggWriter以完成容器尾部信息写入 oggWriter.end(); }); fileStream.on("finish", () => { console.log("6. File write finished"); }); audioStream.on('error', (err) => { console.error('7. An error occurred:', err); oggWriter.end(); fileStream.end(); }); }
关键修改说明
- 用
OggOpusWriter替代原始文件写入流,负责将Opus帧封装为标准Ogg容器格式 - 使用管道(
pipe)简化流处理逻辑,自动完成数据传递与错误转发 - 设置
subscribe的end.behavior为manual,确保完整接收用户语音流后再结束写入 - 音频流结束时优先关闭
OggOpusWriter,保证容器结构完整
内容的提问来源于stack exchange,提问作者Dem Snip
相关产品推荐
相关产品推荐

