DiscordJS bot using Typescript experiences audio playback issues that halt after a short period of time

I am currently experiencing difficulties with playing audio through a discord bot that I created. The bot is designed to download a song from YouTube using ytdl-core and then play it, but for some reason, the song stops after a few seconds of playing.

Below is my "play.ts" file which contains the play command: (sorry for the messy code, I'm still trying to figure things out.)

import { CommandInteraction, SlashCommandBuilder } from "discord.js";
import { getVoiceConnection, createAudioPlayer, createAudioResource, NoSubscriberBehavior } from '@discordjs/voice';
import { join } from "path";
import ytdl from 'ytdl-core';
import fs from 'fs';

export const data = new SlashCommandBuilder()
    .addStringOption(option =>
        option.setName("link")
            .setDescription("Link to the audio source to be played.")
            .setRequired(true)
    )
    .setName("play")
    .setDescription("Plays audio from given URL.");

export async function execute(interaction: CommandInteraction) {
    if (!interaction.guildId) {
        return interaction.reply("Oops! Something went wrong.");
    }

    const url = interaction.options.getString("link");
    const connection = getVoiceConnection(interaction.guildId);

    if (!connection) {
        return interaction.reply("The bot is not in a voice channel. Please join one before using this command.");
    }

    const audioplayer = createAudioPlayer({
        behaviors: {
            noSubscriber: NoSubscriberBehavior.Pause,
        },
    });

    const download = ytdl(url, { filter: 'audioonly' });
    const writestream = fs.createWriteStream('audio.mp4');
    const pathtoresource = join('audio.mp4');

    download.pipe(writestream);

    const resource = createAudioResource(pathtoresource, {
        inlineVolume: true,
        metadata: {
            title: "SONG",
        },
    });

    audioplayer.play(resource);
    connection.subscribe(audioplayer);

    return interaction.reply(`Playing from: ${url}`);
}

The issue seems to be that sometimes the audio doesn't play at all or only plays for a few seconds. It could be due to the download not completing on time for playback, but I'm unsure how to make it wait for the ytdl download.

Any assistance would be greatly appreciated! (once again, sorry for the messy code, I'm still learning)

EDIT: These are the intents:

const client = new Client({
    intents: ["Guilds", "GuildMessages", "DirectMessages", "GuildVoiceStates"],
});

Answer №1

The current situation you're facing is not related to Discord intents at all. The ytdl-core package was not originally intended to maintain open HTTP connections for extended periods of time. This problem arises when streaming media to a device that processes the data slower than it receives it.

An alternative npm package called play-dl addresses this issue effectively (and even offers support for other streaming platforms, which is an added bonus). You can view its example Discord bot code here to see how it works in action.

In my past Discord bot endeavors, I switched to using play-dl after encountering similar problems with ytdl-core, and things ran much more smoothly. If you require further assistance, feel free to reach out to me through a comment on this post.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Maintaining datatype integrity in MongoDB Stitch when decrementing with update statements

Using a MongoDB Stitch function, I have two collections: communities and posts. Whenever a new document is inserted in the post collection, I need to increment the summary.postCount in the communities collection by +1. Similarly, when the status of a post ...

Is your async function lacking a return statement?

After completing the development of a new method for a bug I encountered, I noticed something interesting. Despite the fact that there is a potential scenario where the function may not return anything, the compiler did not flag any errors. It got me think ...

What is the best way to reset Owl Carousel following an ajax request?

I am attempting to reinitialize the owl carousel following a successful ajax call. The ajax call will update the data while retaining the same view. I am encountering an issue where the carousel structure in the view does not reinitialize, and I am unsure ...

Generating consecutive numerical values within the auto table JSPDF column VusJs

columns: [ { header: 'No', dataKey: 'Index', }, { header: 'No Registrasi', dataKey: 'no_register' }, { header: 'Kode Partai', dataKey: 'kode_partai' }, ...

Angular: Maximizing Input and Output

I'm having trouble with the function displaying within the input field. My goal is to simply allow the user to enter a name and have it displayed back to them. HTML: <div ng-app = "mainApp" ng-controller = "studentController"> <tr> < ...

"Enjoying the convenience of a stationary header while browsing on your smartphone

Hey there! I'm currently facing an issue with my website's fixed horizontal nav bar when zooming in on a mobile device. After doing some research, it seems the only solution is to implement some javascript. I came across a jquery fix (see below) ...

What is the process of transferring fetched data to a different module?

I am facing a situation with two modules, module.js and controller.js. In the module file, I have the following code: export class Module { constructor(){ const fetchParams = { method: "GET", mode: "cors", c ...

Generating a JavaScript object based on an array of keys

I'm currently grappling with a task that is proving to be quite challenging. I have a set of arrays structured like this: ['key1', 'key2', 'key3'] ['key1', 'key2', 'key4'] ['key1', ...

How about beginning a JavaScript count with a randomly generated number?

As I work on developing this code, I am faced with a challenge: /** * Increment value with random intervals. * @param {string} id - Id of DOM Element. * @param {number} start - Start counter value. Applied immediately- * @param {number} end - End c ...

Error: The expression `xmlDoc.load` returns a value of undefined, which is not an object

My current challenge involves loading an XML file using Javascript in IE, Firefox, and Safari. I have yet to find a function that works well across all three browsers. The load function I am currently using is similar to the one found in w3schools tutorial ...

Discover the power of lodash's .groupBy method as you learn how to efficiently group objects within another

Utilizing lodash's _.groupBy function, I have generated the following data: { "Generic Drugs":[ { itemDes: "Dulcolax", itemGeneric: "Bisacodyl", pr ...

Can Node.js be utilized to generate an XLS excel file while specifying the cell type?

I've noticed that many libraries have the capability to export to XLSX (Excel > 2007) or CSV formats, but not in XLS (which I assume is due to its outdated file format). I came across something where if you use fs.createOutputStream("filename. ...

Issue with displaying jqplot in a jQuery page

Currently, I'm utilizing jqmobile pages for switching between various pages in an html5 application. One of these pages features a jqplot chart. Below is the code snippet: <div data-role="page" id="page-two" data-title="Page 2"> &l ...

JavaScript code to record the time when a client exits my website by clicking the X button in the top right corner and save it in my database

I need to record in the database the times when users enter and exit my site. Saving the entry time is not an issue, nor is saving the exit time by clicking my "log off" button. However, what about when a client exits by clicking the X in the right corner ...

Using Alpine JS to rotate through images at regular intervals using the window.setInterval() method

Attempting to tackle a simple task using Alpine JS and the standard JS function setInterval. The goal is to create an image selector where images switch every second (1000ms). Here's what I have so far: <div x-data="imgFunc()"> ...

Marionette - Apply a class to the parent ItemView's tagname

I've been working with Bootstrap accordion panels and I'm trying to assign a class to the parent panel of the panel-collapse. Essentially, what I want to achieve is: if (child element) hasClass('panel-collapse.in') { this.addClass ...

Add the component view to the webpage's body section

Using Angular 7 and ngx-bootstrap 4.0.1 Dependencies: "bootstrap": "3.3.7", "bootstrap-colorpicker": "2.5.1", "bootstrap-duallistbox": "3.0.6", "bootstrap-markdown": "2.10.0", "bootstrap-progressbar": "0.9.0", "bootstrap-slider": "9.8.0", "bootstrap-tags ...

Finding the identifier for resources through excluding external influences

I am currently facing an issue with the full calendar plugin. In my set up, I have 3 resources along with some external events. The problem arises when I try to drop an external event onto the calendar - I want to retrieve the resource id from which the ev ...

Is it necessary to insert a thread sleep in HtmlUnit before clicking a button?

I have been experimenting with HtmlUnit to extract scores from the BBC Sports website Upon loading the page, it initially displays Premier League scores. To view scores for other leagues, one must use a dropdown menu and click the 'Update' butto ...

Changing a date format in typescript: Here is how you can easily convert a date from one

Using React with Typescript: I am currently working with a date picker from material-ui version 5. The date picker requires the date value to be in the format "yyyy-MM-dd". However, the API returns a Date object in the format "2022-01-12T00:00:00.000+00:0 ...