Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V12 Master Receiver not Decoding Opus #3550

Closed
Xilophinum opened this issue Oct 24, 2019 · 14 comments · Fixed by #3555
Closed

V12 Master Receiver not Decoding Opus #3550

Xilophinum opened this issue Oct 24, 2019 · 14 comments · Fixed by #3555

Comments

@Xilophinum
Copy link

Please describe the problem you are having in as much detail as possible:

It looks like a change happened with voice packets and it seems they cannot be decoded. Voice packets are still being sent, but when attempting to convert them, or even change the receiver to PCM instead of Opus, they become corrupt. I cannot decode the frames with Opusdec either. Below is code I used for v12 to make a quick idea of whats happening.

Include a reproducible code sample here, if possible:

require("dotenv").config();
const { CLIENT_TOKEN } = process.env;
const { Client } = require("discord.js");
const Silence = require("./Silence");
const client = new Client();

client.on("ready", () => {

    console.log("ready");

    let voiceChannel = client.channels.get("channel-id-here");

    voiceChannel.join().then(connection => {
      connection.play(new Silence(), { type: "opus" });
        connection.on("speaking", (user, speaking) => {
            let chunks = [];

            if (speaking.bitfield === 1) {
              const receiver = connection.receiver.createStream(user, { mode: "pcm", end: "silence" });
              receiver.on("data", chunk => {
                chunks.push(chunk);
              });
            }

        });

    }).catch(console.error);
  });

client.login(CLIENT_TOKEN);

--------------------------
Console:
ready
/home/john/testing/node_modules/prism-media/src/opus/Opus.js:58
    return this.encoder.decode(buffer, Opus.name !== 'node-opus' ? this._options.frameSize : null);
                        ^

TypeError: The compressed data passed is corrupted
    at Decoder._decode (/home/john/testing/node_modules/prism-media/src/opus/Opus.js:58:25)
    at Decoder._transform (/home/john/testing/node_modules/prism-media/src/opus/Opus.js:183:20)
    at Decoder.Transform._read (_stream_transform.js:190:10)
    at Decoder.Transform._write (_stream_transform.js:178:12)
    at doWrite (_stream_writable.js:410:12)
    at writeOrBuffer (_stream_writable.js:394:5)
    at Decoder.Writable.write (_stream_writable.js:294:11)
    at Readable.ondata (_stream_readable.js:689:20)
    at Readable.emit (events.js:189:13)
    at addChunk (_stream_readable.js:284:12)
    at readableAddChunk (_stream_readable.js:265:11)
    at Readable.push (_stream_readable.js:220:10)
    at PacketHandler.push (/home/john/testing/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js:87:12)
    at Socket.socket.on.buffer (/home/john/testing/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js:131:76)
    at Socket.emit (events.js:189:13)
    at UDP.onMessage [as onmessage] (dgram.js:628:8)



--------------------------

Further details:

  • discord.js version: v12
  • Node.js version: 10.5.3
  • Operating system: Linux Deepin
  • Priority this issue should have – please be realistic and elaborate if possible:
  • [x ] I have also tested the issue on latest master, commit hash: 16db92e
@njohns67
Copy link

I'm getting the same bug on Stable

@sillyfrog
Copy link
Contributor

I'm getting a similar issue, I have just updated to the latest build. I'm not sure if it was happening before that (a build several months old), but I suspect it was, so maybe a change on the discord end.

@1-max-1
Copy link

1-max-1 commented Oct 25, 2019

This seems to be happening with my bot as well (on stable). I've tried streaming the audio back to discord and playing it in a voice channel but the sound just comes out like someone is pouring water. lol :-) . I don't get any errors but I'm guessing the packets could be corrupted as E0HH said?

@amishshah
Copy link
Member

Please note that Discord does not support receiving audio, so while we can do our best to support it within the library, it is likely to break. In this case, Discord must have made some breaking changes.

@sillyfrog
Copy link
Contributor

Thanks @amishshah, that explains a lot in my (unsuccessful) search through their docs for the current API version and what may have changed! :/

This is the Discord feature request: discord/discord-api-docs#365 - I'm assuming (hoping) the more +1 they get the more likely they are to do something about it, so if everyone can please click on it that would be great.

@dragonbane0
Copy link
Contributor

Yeah I can unfortunately confirm this it seems like. After fixing the fact that speaking updates no longer came through properly, I encountered this next. I can still decode the packages to PCM occasionally, but it all comes out as corrupted noise when played back

@dragonbane0
Copy link
Contributor

I figured it out! For the latest master:

In "src/client/voice/receiver/PacketHandler.js" at L66

Replace:
while (packet[offset] === 0) offset++;

With:
offset++;

Explanation:
As far as I can tell the point of that while loop was to go past all empty bytes that might be between the end of the RTP headers and the Opus packet. Since we have no discord documentation on this we don't really know what these bytes do officially.

I assume the assumption was that this was just padding, since every packet used to have one zero byte there. However as it turns out that is no longer the case! This byte in question is now 0x02 for most regular packages and 0 for empty/silent packages as far as I can tell.

So instead of padding it is probably some additional information byte for the discord client, which previously wasn't used and was merely a placeholder, but now is used.

Just reading over it seems to work out fine for now. With the old code it would read over the byte correctly if it was 0, but not if it was 2, which is now the case for most voice packages. This made Opus incorrectly interpret the 0x02 as the TOC byte, which doesn't really make sense. Reading up on the Opus TOC byte made me realize this error.

@1-max-1
Copy link

1-max-1 commented Oct 26, 2019

@dragonbane0 how and why are you so smart!? This makes two annoying problems you've solved for me now. Thanks :-). Anyway, for anyone wanting to fix this problem on stable instead of master, follow the instructions of @dragonbane0 above, but instead of editing src/client/voice/receiver/PacketHandler.js, edit src/client/voice/receiver/VoiceReceiver.js. The broken code is also on line 177 in stable instead of line 66 in the master branch.

@Xilophinum
Copy link
Author

Fantastic work @dragonbane0 you sir are a legend. Would of never caught that. Hydra, should someone create a pull request for the change? Code is now working for me on master with the fix above.

@amishshah
Copy link
Member

Great find @dragonbane0! Do you want to make a PR for it? :)

@dragonbane0
Copy link
Contributor

@amishshah sure! Will get on it in a bit

@ghost
Copy link

ghost commented Jul 8, 2020

Help me pls:v

2020-07-08T04:13:34.473464+00:00 app[worker.1]: Uncaught Exception:  TypeError: The compressed data passed is corrupted
2020-07-08T04:13:34.473484+00:00 app[worker.1]:     at Decoder._decode (/app/node_modules/prism-media/src/opus/Opus.js:64:25)
2020-07-08T04:13:34.473485+00:00 app[worker.1]:     at Decoder._transform (/app/node_modules/prism-media/src/opus/Opus.js:189:20)
2020-07-08T04:13:34.473486+00:00 app[worker.1]:     at Decoder.Transform._read (_stream_transform.js:191:10)
2020-07-08T04:13:34.473487+00:00 app[worker.1]:     at Decoder.Transform._write (_stream_transform.js:179:12)
2020-07-08T04:13:34.473488+00:00 app[worker.1]:     at doWrite (_stream_writable.js:403:12)
2020-07-08T04:13:34.473488+00:00 app[worker.1]:     at writeOrBuffer (_stream_writable.js:387:5)
2020-07-08T04:13:34.473488+00:00 app[worker.1]:     at Decoder.Writable.write (_stream_writable.js:318:11)
2020-07-08T04:13:34.473489+00:00 app[worker.1]:     at Socket.ondata (_stream_readable.js:717:22)
2020-07-08T04:13:34.473489+00:00 app[worker.1]:     at Socket.emit (events.js:315:20)
2020-07-08T04:13:34.473490+00:00 app[worker.1]:     at addChunk (_stream_readable.js:295:12)

@MTGPROD
Copy link

MTGPROD commented Jul 11, 2020

I got the same error, that's weird what happens these days 😔

@sillyfrog
Copy link
Contributor

@MTGPROD @Ettokun I have just tested with the latest build using my example here: https://github.com/sillyfrog/discord.js-listenexample and things are working as expected. So maybe there is some other library conflict causing issues? I would suggest starting with that example (in Docker) and seeing if you can reproduce from there.
Remember also that the receive API is not an official one from Discord, so it could change at any time.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants
@sillyfrog @amishshah @dragonbane0 @MTGPROD @njohns67 @Xilophinum @1-max-1 and others