Search code examples
node.jselectrondiscord.jsopus

RangeError when playing audio through opusscript


I've been attempting to use electron to play sounds through a discord bot. However, I've come across three issues with this.

The first is that the code I'd usually use to play a sound file though discord returns an error stating that I am lacking opus.node and opusscript. This shouldn't be happening, as I have @discordjs/opus installed, and running this same code outside of the electron instance works perfectly fine.

message.member.voice.channel.join().then((connection) => {
    const dispatcher = connection.play(ytdl("https://www.youtube.com/watch?v=ZlAU_w7-Xp8", { quality: "highestaudio" }));
    dispatcher.on("finish", () => {
        console.log("Song is finished.");
    });
});

To get around the error, I installed opusscript. However, this is where the second issue comes in. I am able to run the sound - for the first 9 times. After the ninth time, the bot emits the following error:

(node:21064) UnhandledPromiseRejectionWarning: RangeError: offset is out of bounds
at Uint16Array.set (<anonymous>)
at OpusScript.encode (C:\Users\spiralio\Desktop\sb\node_modules\opusscript\index.js:67:16)
at Encoder._encode (C:\Users\spiralio\Desktop\sb\node_modules\prism-media\src\opus\Opus.js:60:25)
at Encoder._transform (C:\Users\spiralio\Desktop\sb\node_modules\prism-media\src\opus\Opus.js:157:30)
at Encoder.Transform._read (_stream_transform.js:191:10)
at Encoder.Transform._write (_stream_transform.js:179:12)
at doWrite (_stream_writable.js:403:12)
at writeOrBuffer (_stream_writable.js:387:5)
at Encoder.Writable.write (_stream_writable.js:318:11)
at VolumeTransformer.ondata (_stream_readable.js:716:22)

This error only occurs if the sound file I'm playing overlaps onto itself 9 times. If I let it finish before this error plays, I can continue playing sounds just fine. However, once the error plays, no matter how long I wait sound no longer plays.

A solution I tried was to have the bot run in the renderer process instead of the main process. However, this prompts me with the issue that the bot can't connect to a voice channel from a browser.


Solution

  • There seem to be a few issues at play here.

    Firstly, the root issue here is that we're encoding a file that's too large. I suspect that the videos are snowballing to such a point where we hit a brick wall.

    I'd try downloading only the audio to avoid sending files too large (see ytdl options).

    message.member.voice.channel.join().then((connection) => {
        const dispatcher = connection.play(ytdl("https://www.youtube.com/watch?v=ZlAU_w7-Xp8", { quality: "highestaudio", filter: "audioonly" }));
        dispatcher.on("finish", () => {
            console.log("Song is finished.");
        });
    });
    

    Electron not detecting @discordjs/opus seems to be a deeper issue with native modules and your builder. Are you experiencing this in production, or do you have a recreation of your Electron setup somewhere?