fent / node-ytdl-core

YouTube video downloader in javascript.
MIT License
4.54k stars 803 forks source link

ytdl stop stream after few minute #994

Open Nyako01 opened 3 years ago

Nyako01 commented 3 years ago

i am using ytdl to stream youtube video on my discord bot. after few minute ytdl stop streaming with error

Error: aborted
    at connResetException (node:internal/errors:691:14)
    at TLSSocket.socketCloseListener (node:_http_client:407:19)
    at TLSSocket.emit (node:events:406:35)
    at node:net:672:12
    at TCP.done (node:_tls_wrap:580:7) {
  code: 'ECONNRESET'
}

I think the error is caused by my slow internet connection. so I try to run my bot on hosting [heroku]. but still got the same error

i am using ytdl v4.9.1, discordJs v13.1.0 and nodeJs v16.6.1

here the code i use to start streaming

const option = {
        filter: "audioonly",
        highWaterMark: 1048576 / 4,
    };
const stream = await ytdl(streamUrl, option);

and here the code i use to play stream in bot with discordJs v13.1.0 and discordJs/voice v0.6.0

const player = createAudioPlayer();
const resource = createAudioResource(stream);

player.play(resource);
const connection = await joinVoiceChannel({ channelId: song.voiceChannel.id, guildId: song.voiceChannel.guild.id, adapterCreator: song.voiceChannel.guild.voiceAdapterCreator });
try {
        await entersState(connection, VoiceConnectionStatus.Ready, 30_000);
        connection.subscribe(player);
    } catch (error) {
        connection.destroy();
        throw error;
    }
redbrain commented 3 years ago

We think this issue is caused by recent versions of NodeJS. We're trying to find a fix. Can someone determine if this is a duplicate ticket?

GaryCraft commented 3 years ago

902 Is at least a related Bug.

Nyako01 commented 3 years ago

i just updated my nodejs to the latest version which is 16.6.2 and tried to test ytdl again but as an mp3 downloader. here the code i used to test

const ytdl = require('ytdl-core')
const fs = require('fs')
const streamUrl = 'http://www.youtube.com/watch?v=05s6wxQS6Ag'
const idvideo = streamUrl.slice(streamUrl.indexOf('v=') + 2)
const option = {
      filter: "audioonly",
      highWaterMark: 1048576 / 4,
    };

const stream = ytdl(streamUrl, option);
stream.on("error", (err) => {
      console.log("ytdl error\n", err);
    });
stream.pipe(fs.createWriteStream(`./song_temp_cache/${idvideo}.mp3`));

is work fine. but still getting the same error when used for discord music bot

I also tried the discordjs/voice to play directly from the mp3 file url and the local mp3 file. and the result is works fine

do i have to download the youtube audio first in mp3 format. then stream to my discord bot?

*sorry for my bad english

InfiniteMarcus commented 3 years ago

I'm having the same issue with Discord music bots, but for some reason, I receive this Error: aborted every day around 7 AM (in Brazil). This regularity probably is related to Heroku dyno restart system of my application or something like that.

I'm using node-ytdl for a few months and this thing only appeared when I migrated to Node V16. I can still play some music, but sometimes the stream suddenly ends without throwing any visible errors

Nyako01 commented 3 years ago

i try to find solution on discordjs/voice/issue. and i found this

the developer said. the error is from ytdl-core. and he suggested using youtube-dl for stream audio data to discord bot so i try using youtube-dl-exec based on example here (line 47). and it works. until streaming is over here my code

const yt-dl = require('youtube-dl-exec').raw
const stream = yt-dl(streamUrl, {
    o: '-',
    q: '',
    f: 'bestaudio[ext=webm+acodec=opus+asr=48000]/bestaudio',
    r: '100K',
  }, { stdio: ['ignore', 'pipe', 'ignore'] })

const player = createAudioPlayer();
const connection = await joinVoiceChannel({
      channelId: song.voiceChannel.id,
      guildId: song.voiceChannel.guild.id,
      adapterCreator: song.voiceChannel.guild.voiceAdapterCreator,
    });
const resource = createAudioResource(stream.stdout);
player.play(resource);

try {
    await entersState(connection, VoiceConnectionStatus.Ready, 30_000);
    connection.subscribe(player);
  } catch (error) {
    connection.destroy();
    throw error;
  }

maybe for now we should use youtube-dl-exec to stream audio data to discord bot (only on discordjs v13). until ytdl can fix this problem

Error: aborted
    at connResetException (node:internal/errors:691:14)
    at TLSSocket.socketCloseListener (node:_http_client:407:19)
    at TLSSocket.emit (node:events:406:35)
    at node:net:672:12
    at TCP.done (node:_tls_wrap:580:7) {
  code: 'ECONNRESET'
}
PedroLopes65777 commented 3 years ago

@Oky12 that works great thanks! However, do you know if it's possible to play age-restricted videos? Like in ytdl we had the cookies option, I can't seem to find anything in youtube-dl-exec

Nyako01 commented 3 years ago

@MrPedrinho I have no idea about that. and because "youtube-dl-exec" is a simple Node.js wrapper for youtube-dl. so maybe only the essentials of youtube-dl are available in "youtube-dl-exec". btw i found a github repository issue that talking about youtube-dl cookies. maybe it will help you

TimeForANinja commented 3 years ago

can you provide full example code to test / reproduce the problem? i can ofc fill in voicechannel id's + bot token myself

mtripg6666tdr commented 3 years ago

can reproduce it (without discord.js library) by piping it to ffmpeg and opus encoder through pipeline to convert into ogg/opus format Example: https://github.com/mtripg6666tdr/ytdl-test/blob/d130f03679f628d692760be27694eedd22c3a9c4/src/index.js#L33 An error will occur in about 30-40 minutes later after starting playing (and this is the same way to use Readable stream in @discordjs/voice)

AkatGabrielGoncalves commented 3 years ago

This might be related to audio bitrate, try to use quality: 'lowestaudio'. Discord channels default to 32 bitrate, if your video exceeds this limit it will close your connection and return an error.

const stream = await ytdl(song.url, {
              filter: 'audioonly',
              quality: 'lowestaudio',
              requestOptions: {
                headers: {
                  cookie: process.env.YOUTUBE_LOGIN_COOKIE,
                },
              },
            });
mtripg6666tdr commented 3 years ago

It depends on actual data size in PassThrough. When quality set lower, the audio stored in buffer becomes long By setting actually quality low or setting highWaterMark high help to be longer to when the error occurs in addition to that, this error will occur also without discord.js

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

mtripg6666tdr commented 2 years ago

This error is unresolved also on node.js v17

PatricNox commented 2 years ago

@Nyako01 i've been battling this issue with Error: aborted all day until I saw your suggestion to try youtube-dl-exec. however, I can't get it to work either as when using .raw it complains of not being a function

 const youtubedl = require("youtube-dl-exec").raw;
  const stream = youtubedl(
    data.queue[0].url,
    {
      o: "-",
      q: "",
      f: "bestaudio[ext=webm+acodec=opus+asr=48000]/bestaudio",
      r: "100K",
    },
    { stdio: ["ignore", "pipe", "ignore"] }
  )

"youtubedl is not a function"

Trying without, i get a promise but i cant use the then() scope due to it seeming to never be reached

What am i missing here?

AkatGabrielGoncalves commented 2 years ago

@PatricNox Try using exec instead of raw.

import { exec as ytdlexec } from 'youtube-dl-exec';

const stream = ytdlexec(
  url,
  {
    output: '-',
    format:
      'bestaudio[ext=webm+acodec=opus+tbr>100]/bestaudio[ext=webm+acodec=opus]/bestaudio/best',
    limitRate: '1M',
    rmCacheDir: true,
    verbose: true,
  },
  { stdio: ['ignore', 'pipe', 'ignore'] }
);

const audioResource = createAudioResource(stream.stdout!);
this.player.play(audioResource);

It is an example with typescript but you get the idea and you don't actually need to await if you are going to create a stream from it.

I have the whole code from my example here, its a mess but if it can help you its good enough 😂

DanielBUBU commented 1 year ago

Same problem here here's the full code I tested

// Install discord.js, ffmpeg, node-opus and ytdl-core before running this!

const ytdl = require('ytdl-core');
const {
    StreamType,
    createAudioResource,
    NoSubscriberBehavior,
    AudioPlayerStatus,
    createAudioPlayer,
    joinVoiceChannel,
    VoiceConnectionStatus,
    entersState,
} = require('@discordjs/voice');

const fluentffmpeg = require('fluent-ffmpeg')
const { Client, GatewayIntentBits, Partials } = require('discord.js');
const url = 'https://www.youtube.com/watch?v=uvwCf4jkgrs';
const clientToken = 'token';

const client = new Client({
    intents: [GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.GuildMessageReactions,
        GatewayIntentBits.GuildVoiceStates,
        GatewayIntentBits.MessageContent
    ],
    partials: [Partials.Channel],

    disableMentions: 'everyone',
});
client.on('ready', () => {
    console.log('discord.js client ready');
});

client.on('messageCreate', async message => {

    console.log('in Event');
    if (!message.content.startsWith('++play')) return;

    console.log('Got a song request!');
    const voiceChannel = message.member.voice.channel;
    if (!voiceChannel) {
        message.reply('Please be in a voice channel first!');
        return;
    }
    play(message);

});

function play(message) {
    const player = createAudioPlayer({
        behaviors: {
            noSubscriber: NoSubscriberBehavior.Pause,
        },
    });
    const connection = joinVoiceChannel({
        channelId: message.member.voice.channel.id,
        guildId: message.guild.id,
        adapterCreator: message.guild.voiceAdapterCreator,
    })

    const subscribe = connection.subscribe(player);
    const stream = ytdl(url);
    player.once('error', (error) => {
        console.log("Catched:" + error + error.resource.playbackDuration)
        play(message);
    });

    //const ffmpeg_audio_stream = fluentffmpeg({ source: stream }).toFormat('wav');

    const audio_resauce = createAudioResource(stream, { inputType: StreamType.Arbitrary });

    player.play(audio_resauce);
}

client.login(clientToken);

here's how console looks like

PS D:\PD_maid> node test.js
discord.js client ready
in Event
Got a song request!
in Event
Catched:Error: aborted165700
Catched:Error: aborted140740
in Event
Catched:Error: aborted135720
in Event
Catched:Error: aborted140740
Catched:Error: aborted130740
in Event
Catched:Error: aborted160700

here are my dependencies

"dependencies": {
    "@appland/appmap-agent-js": "^12.0.0",
    "@discordjs/voice": "^0.13.0",
    "avconv": "^3.1.0",
    "cli-progress": "^3.11.2",
    "discord-api-types": "^0.36.1",
    "discord-rich-presence": "^0.0.8",
    "discord.js": "^14.6.0",
    "ffmpeg": "^0.0.4",
    "fluent-ffmpeg": "^2.1.2",
    "html-metadata-parser": "^2.0.4",
    "libsodium-wrappers": "^0.7.10",
    "node-ffprobe": "^3.0.0",
    "ws": "^8.8.0",
    "ytdl-core": "^4.11.2",
    "ytpl": "^2.3.0"

now I using error.resource.playbackDuration and ffmpeg to hadle the error, because the begin option in ytdl is not working well https://github.com/DanielBUBU/PD_maid

richiedevs commented 1 year ago

Can confirm the issue, experiencing it myself.

eugabrielsilva commented 1 year ago

Same problem, input stream aborted

0xAnakin commented 1 year ago

Have a look at https://github.com/fent/node-ytdl-core/issues/902#issuecomment-1460991438 in case you are getting an aborted error.

LeGeek01 commented 1 year ago

can reproduce in NodeJS v19...

luca-naujoks commented 7 months ago

I had the same problem with my discord bot. After some testing I reduced the LiveBuffer down to 2 sec witch solved the problem. My guess is that the error occurs because the buffer gets too big for some default or hardcoded limit of nodeJS.

const stream = ytdl(song.url, {filter: 'audioonly', liveBuffer: 2000, highWaterMark: 1 << 25});
const resource = createAudioResource(stream);
player.play(resource);
LeGeek01 commented 7 months ago

yeah good job it works now! @Nyako01 can you try it out? @redbrain any news on a fix?