How can I create an audio resource from a URL? (Trying to code a bot for discord.js v13)

I am trying to code a Discord bot to use search for a song on YouTube using YTDL and then play the song in a Discord voice channel.

I was able to play a song from a file saved on my PC so I know that it works and the volume is fine. Anytime I try to pass the Audio Player a YTDL result I get an error. And if I try the video URL directly, I don’t get an error but nothing still plays.

Here is my code for the player:

const ytdl = require('ytdl-core-discord');
const ytSearch = require('yt-search');
const { createAudioPlayer, createAudioResource, joinVoiceChannel, AudioResource, StreamType } = require('@discordjs/voice');

module.exports = {

    name: 'play',
    description: 'joins and plays music',
    async execute(message, args) {

        const voiceChannel = message.member.voice.channel;

        //if command is empty
        if(!args.length) return message.channel.send('You need to provide a URL!');       

        //If user is in VC, join same channel
        if (voiceChannel) {
            const player = createAudioPlayer();
            const connection = joinVoiceChannel({
                        channelId: voiceChannel.id,
                        guildId: voiceChannel.guild.id,
                        adapterCreator: voiceChannel.guild.voiceAdapterCreator,
                    }).subscribe(player);

            //Search for vid and return first result
            const vidFind = async (query) =>{
                const vidRes = await ytSearch(query);
                return (vidRes.videos.length > 1) ? vidRes.videos[0]:null;
            }
            const video = await vidFind(args.join(''));

            //If there is a video result, save it as an audio resource and play it through audio player
            if(video){
               const stream = ytdl(video.url, {filter: "audioonly"})
                const resource = createAudioResource(stream);
                player.play(resource);
            }           
        } else {
            message.channel.send('You need to be in a VC first!');
            
        }
    }

}

And here is the error I get:

TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of WebmDemuxer
    at new NodeError (node:internal/errors:371:5)
    at _write (node:internal/streams/writable:312:13)
    at Socket.Writable.write (node:internal/streams/writable:334:10)
    at Duplexify.ondata (node:internal/streams/readable:754:22)
    at Duplexify.emit (node:events:394:28)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at Duplexify.Readable.push (node:internal/streams/readable:228:10)
    at node:internal/streams/duplexify:180:13
    at runMicrotasks (<anonymous>) {
  code: 'ERR_INVALID_ARG_TYPE'

I have tried using the creatReadStream function but I found that only works on local files. I have tried looking at other Discord v13 bots and they don’t seem to use the createAudioResource at all and instead create their own custom function to create an audio resource.

Any help at all would be much appreciated!

Answer

I can think of a few reasons you may be running into some of the issues you are.

First of all, just a disclaimer that I have never used ytdl-core-discord. I have only worked with ytdl-core, but the npmjs page of the former states that the function call (I.e. ytdl(video.url, {filter: "audioonly"})) must be ‘await’-ed. So try putting ‘await’ before that call and see what happens.

Secondly, you should check your intents. In order to stream audio you require the GUILD_VOICE_STATES intent. This may be the reason that using the URL directly does not do anything.

If neither of those options fix it I would recommend switching from library. From what I can see ytdl-core-discord is not updated to work with Discord.jsV13. A lot of things changed about audio in version 13 so I wouldn’t be surprised if it no long works until being updated. You can go to the regular ytdl-core version which I have seen work with v13 or, as I would recommend, you can try play-dl. It does virtually the same thing, but it does not come with some of the problems and bugs that I have seen people and myself get with ytdl-core. Also, play-dl has great examples on its npmjs page that can help you along.