Decoding Opus packets from `AudioReceiveStream` using @discordjs/opus

I have a problem with decoding Opus packets received from AudioReceiveStream using OpusEncoder from @discordjs/opus. When I try to save decoded samples and play them, every player says they are corrupted. I know provided example is using prism-media for that, but this would be an overkill for me.
9 Replies
d.js toolkit
d.js toolkit4d ago
- What are your intents? GuildVoiceStates is required to receive voice data! - Show what dependencies you are using -- generateDependencyReport() is exported from @discordjs/voice. - Try looking at common examples: https://github.com/discordjs/voice-examples. - Consider reading #how-to-get-help to improve your question! - Explain what exactly your issue is. - Post the full error stack trace, not just the top part! - Show your code! - Issue solved? Press the button! - Marked as resolved by OP
pat
pat4d ago
2nd last bullet point 👍
ivirtex
ivirtexOP4d ago
Opus decoder returns 16-bit PCM buffer, so I collect these buffers and save them to a .pcm file Then using FFmpeg I convert it to a .wav file, but it says that pcm file is corrupted Well, I might did something wrong with saving them
const voiceBuffers: Buffer[] = [];
const encoder = new OpusEncoder(48000, 1);
encoder.setBitrate(48000);

for (const voiceChannelMember of vc.members.values()) {
console.log(voiceChannelMember.user.username);

const stream = voiceConnection.receiver.subscribe(voiceChannelMember.id);
stream.on("data", async (data) => {
const decoded = encoder.decode(data);
console.log(`Decoded ${decoded.length} bytes of data`);

// Append the decoded data to the buffer
voiceBuffers.push(decoded);
});
}
const voiceBuffers: Buffer[] = [];
const encoder = new OpusEncoder(48000, 1);
encoder.setBitrate(48000);

for (const voiceChannelMember of vc.members.values()) {
console.log(voiceChannelMember.user.username);

const stream = voiceConnection.receiver.subscribe(voiceChannelMember.id);
stream.on("data", async (data) => {
const decoded = encoder.decode(data);
console.log(`Decoded ${decoded.length} bytes of data`);

// Append the decoded data to the buffer
voiceBuffers.push(decoded);
});
}
.on(VoiceConnectionStatus.Disconnected, async (error) => {
console.log("Voice Connection disconnected");

await Bun.write("voice.pcm", voiceBuffers);
})
.on(VoiceConnectionStatus.Disconnected, async (error) => {
console.log("Voice Connection disconnected");

await Bun.write("voice.pcm", voiceBuffers);
})
pat
pat4d ago
ah thats what ur doing check the link in the bot message there's a code example for this exact thing dont save data without user consent btw
ivirtex
ivirtexOP4d ago
the example is using some alpha 4 years old version of prism-media is there any other example not using prism-media?
duck
duck4d ago
We don't have one, but I also have to ask how are you playing the decoded samples? pcm is just raw data with no headers, so even if a media player is equipped to handle pcm, it usually requires a separate means of playing the file since you need to specify the format of the data So with that in mind most media players aren't equipped to play pcm and therefore mark them as corrupted since they can't just probe and determine what format the audio file is Sorry I missed this, but I also have to ask what options you're using when converting
ivirtex
ivirtexOP4d ago
ffmpeg .\output.pcm -f s16le -ac 1 -ar 48000 voice.wav decoder is set to the same settings what's interesting, I just have tried importing it into Audacity and it actually plays without any problems so I guess I must be doing something wrong with ffmpeg this is what ffmpeg has to say about this file:
[in#0 @ 00000290aeb99700] Error opening input: Invalid data found when processing input
Error opening input file .\output.pcm.
Error opening input files: Invalid data found when processing input
[in#0 @ 00000290aeb99700] Error opening input: Invalid data found when processing input
Error opening input file .\output.pcm.
Error opening input files: Invalid data found when processing input
duck
duck4d ago
afaik those format options apply to the file after the flags, so it should look more like ffmpeg -f s16le -ac 1 -ar 48000 -i ./output.pcm voice.wav but it sounds like this issue is leaving the scope of this channel since you've confirmed the actual audio samples are being recorded and decoded
ivirtex
ivirtexOP4d ago
wow, yeah, you are right it works now thanks! ffmpeg has the best user experience

Did you find this page helpful?