Discord music bot joins voice channel successfully but fails to stream audio from YouTube links

I’m working on a Discord bot with music functionality. The bot can connect to voice channels properly, but it won’t actually play any audio when I give it YouTube URLs. Here’s my current implementation:

import asyncio
import discord
import youtube_dl
from discord.ext import commands

class AudioBot(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.currently_playing = False
        self.paused_state = False
        self.song_queue = []
        self.YTDL_CONFIG = {'format': 'bestaudio/best', 'verbose': True}
        self.FFMPEG_CONFIG = {'options': '-vn'}
        self.voice_client = None
        self.downloader = youtube_dl.YoutubeDL(self.YTDL_CONFIG)

    async def start_playback(self, context):
        if self.song_queue:
            self.currently_playing = True
            audio_url = self.song_queue.pop(0)
            self.voice_client.play(discord.FFmpegPCMAudio(audio_url, **self.FFMPEG_CONFIG), after=lambda e: self.next_track(context))

    async def next_track(self, context):
        if self.song_queue:
            audio_url = self.song_queue.pop(0)
            self.voice_client.play(discord.FFmpegPCMAudio(audio_url, **self.FFMPEG_CONFIG), after=lambda e: self.next_track(context))
        else:
            self.currently_playing = False
            asyncio.run_coroutine_threadsafe(self.voice_client.disconnect(), self.bot.loop)

    @commands.command(name='music', aliases=['song', 'audio'])
    async def music_command(self, ctx, *, link=None):
        try:
            if not ctx.author.voice:
                error_msg = discord.Embed(
                    title='Connection Error',
                    description=f'{ctx.author.mention}, you need to be in a voice channel first.',
                    color=discord.Color.red()
                )
                await ctx.send(embed=error_msg)
                return

            if not link:
                error_msg = discord.Embed(
                    title='Missing URL',
                    description=f'{ctx.author.mention}, please include a YouTube link.',
                    color=discord.Color.red()
                )
                await ctx.send(embed=error_msg)
                return

            user_channel = ctx.author.voice.channel
            if self.voice_client is None or not self.voice_client.is_connected():
                self.voice_client = await user_channel.connect()
            else:
                await self.voice_client.move_to(user_channel)

            track_data = self.downloader.extract_info(link, download=False)
            stream_url = track_data['formats'][0]['url']
            track_name = track_data['title']
            self.song_queue.append(stream_url)

            if not self.currently_playing:
                await self.start_playback(ctx)

            success_msg = discord.Embed(
                title='Now Playing',
                description=f'🎵 Track: {track_name}\n🎤 Requested by: {ctx.author.mention}',
                color=discord.Color.green()
            )
            await ctx.send(embed=success_msg)

        except Exception as error:
            print(f'Music command failed: {error}')

async def setup(bot):
    await bot.add_cog(AudioBot(bot))

When I run the command, I get this error message:

ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug
youtube_dl.utils.RegexNotFoundError: Unable to extract uploader id

The bot connects to the voice channel fine, but the audio never starts playing. I tried adding verbose logging and looking into ffmpeg path configuration but nothing worked. Any ideas on how to fix this YouTube extraction issue?

It’s not just the outdated youtube-dl library. Your YTDL_CONFIG is missing key parameters that cause extraction errors. Add these to your config: ‘noplaylist’: True, ‘extractflat’: False, ‘ignoreerrors’: True. Don’t access track_data[‘formats’][0][‘url’] directly - it’ll break. Use track_data.get(‘url’) instead or loop through formats to find the best audio stream. I hit the same issue last month. Some YouTube URLs need specific headers in YTDL_CONFIG. Try adding ‘http_headers’: {‘User-Agent’: ‘Mozilla/5.0’} to fake a browser request. Check your verbose output - it’ll show exactly where extraction fails during the uploader id step.

youtube-dl’s basically dead - that’s your problem. Switch to yt-dlp instead. It’s actively maintained and handles YouTube’s recent changes. Just run pip install yt-dlp and swap out the import. Same API but it actually works with current URLs.

Had this exact problem a few months ago. The issue isn’t just youtube-dl being outdated - it’s how you’re extracting audio URLs. Even with yt-dlp, grabbing track_data['formats'][0]['url'] directly usually gives you video streams, not audio-only ones. You need to filter specifically for audio formats.

Your next_track method has a bigger problem though - it’s not async but you’re calling async operations inside it. The after callback in discord.py runs in a separate thread, so asyncio.run_coroutine_threadsafe creates timing issues. I fixed mine with a proper async queue system and asyncio.create_task for track transitions. Those extraction errors happen because YouTube URLs expire fast - try re-extracting the stream URL right before playing instead of storing it in the queue.

check your ffmpeg path - thats probs the issue. discord.py needs ffmpeg installed and in your system path. try adding the full path like executable='C:\ffmpeg\bin\ffmpeg.exe' to your FFmpegPCMAudio call. also, ditch that try/except block for now since its hiding the actual error details. you need to see the full traceback to figure out what’s wrong.

Yes, while updating youtube-dl is crucial, the bigger issue lies within your next_track method. It’s not async, yet you’re attempting to execute async operations via discord.py’s after callback, which leads to race conditions. I faced a similar challenge when developing a music bot last year and had to redesign the playback structure. Rather than depending on the after callback for track transitions, establish a continuous event loop that monitors voice_client.is_playing() to manage the queue as tracks finish.

Additionally, your FFMPEG_CONFIG lacks important parameters. YouTube streams often require extra buffering to prevent interruptions, so consider adding 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5' to mitigate connection issues.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.