discordjs / discord.js

A powerful JavaScript library for interacting with the Discord API
https://discord.js.org
Apache License 2.0
25.36k stars 3.97k forks source link

Dispatcher stalls when playing long opus streams #4007

Closed DontBreakAlex closed 3 years ago

DontBreakAlex commented 4 years ago

The StreamDispatcher never ends (the event finish/end/unpipe never fires). The readable that was passed is still readable, but duration matches the end of the stream (the song has been played completely). I attached a print of both the dispatcher and readable, and a log of all the events they fired. If think the issue comes from discordjs because the readable still has the "readable" property set to true.

obj_print.json.zip dispatcher.log.zip readable-truncated.log.zip

Include a reproducible code sample here, if possible:

    async clone(message: Message, array: string[], channel: TextChannel) {
        let clone = new youtube();
        let video: YoutubeVideo;
        let url = array[2] || array[1]
        if (url.indexOf('https://') == -1) url = `https://${url}`;
        [video, clone.readable] = await Promise.all([
            this.youtube.videos.get(url),
            ytdl(url, { filter: "audioonly", highWaterMark: 1<<25 })
        ])
        clone.title = video.snippet.title;
        message.channel.send(new MessageEmbed({title: "removed"}));
        return clone;
    }

    play(connection: VoiceConnection) {
        let disp = connection.play(<Readable>this.readable, { type: 'opus' })
        setInterval(() => {console.log(disp, this.readable)}, 60_000)
        return disp
    }

Further details:

I will try with master tomorrow, but the stream needs to be more than hour long for the bug to occur.

DontBreakAlex commented 4 years ago

Here is a drop in code the go the bug to trigger:

import ytdl from 'ytdl-core-discord';
import { VoiceConnection, Message, TextChannel } from 'discord.js';
import { Client,  Guild } from 'discord.js'

const bot = new Client();

bot.on('message', async message => {
    if (!message.cleanContent.startsWith('ldt')) return;
    let stream = await ytdl('https://www.youtube.com/watch?v=JYVMnLUZu9Y', { filter: "audioonly", highWaterMark: 1<<25 })
    let connection = await message.member.voice.channel.join()
    let disp = connection.play(stream, { type: 'opus' })
    disp.on('finish', () => {
        message.channel.send('over')
        connection.disconnect();
    })
})

discord.js: 12.0.2, ytdk-core-discord: 1.1.0, node: 13.6.0, typescript: 3.8.3

amishshah commented 4 years ago

I think the issue here is that you have such a high highWaterMark setting (33 megabytes!)

Could you try removing the highWaterMark setting and see if that helps?

DontBreakAlex commented 4 years ago

If I remove the highWaterMark setting, the stream ends way before the ends, as described in this issue: https://github.com/amishshah/ytdl-core-discord/issues/148. I've tried lowering it's value, but either it stops too early over it never stops.

Edit: Shorter musics ~30mins play just fine

DontBreakAlex commented 4 years ago

I experience the same issue using ytdl directly (v2.0.2), without setting highwatermark:

let stream = ytdl('https://www.youtube.com/watch?v=JYVMnLUZu9Y', { filter: "audioonly" })
amishshah commented 3 years ago

Hi there,

We're working on a new implementation of Discord's Voice API that has better playback quality and is more reliable than what we currently support in Discord.js v12 - check it out at https://github.com/discordjs/voice!

The new library solves many of the issues that users are facing, and as part of this, we're dropping built-in support for voice in our next major release. We have a PR (https://github.com/discordjs/discord.js/pull/5402) that adds native support for our new voice library - once this PR is merged, this issue will be closed.

You can still use our new voice library before that PR lands - just take a look at our music bot example to see how to get started upgrading your voice code. By using the boilerplate music player in the example, you can make it even easier to upgrade your code.

Note that the PR above only reduces some of the boilerplate code you'd otherwise have to write - you do not have to wait for the PR to be merged to start using the new voice library.


If you have any questions about this, feel free to: