discord.py

Discord music bot suddenly stops playing when close to the end of a song


I tested the bot by playing the song Yesterday. It suddenly stopped playing at 1:48 while the entire thing was 2:32. When it stops playing, if there iis another song in the queue it starts playing that instantly but doesnt finish that one either. Here is the code

import discord
from discord.ext import commands
import yt_dlp
import asyncio
import os
from dotenv import load_dotenv
from pathlib import Path
from random import randint

intents = discord.Intents.default()
intents.members = True
intents.message_content = True
intents.voice_states = True

dotenv_path = Path('C:/Users/tr/OneDrive/phytoncinali/discordbot/venv/bot/.env')
load_dotenv(dotenv_path=dotenv_path)
TOKEN = os.getenv('DISCORD_TOKEN')

FFMPEG_OPTIONS = {'options' : '-vn'}
YDL_OPTIONS = {'format' : 'bestaudio', 'noplaylist' : True}

class MusicBot(commands.Cog):
    def __init__(self, client):
        self.client = client
        self.queue = []

    @commands.command()
    async def play(self, ctx, *, search):
        voice_channel = ctx.author.voice.channel if ctx.author.voice else None
        if not voice_channel:
            return await ctx.send("Seste değilsin gerizekalı")
        if not ctx.voice_client:
            await voice_channel.connect()

        async with ctx.typing():
            with yt_dlp.YoutubeDL(YDL_OPTIONS) as ydl:
                info = ydl.extract_info(f"ytsearch:{search}", download=False)
                if 'entries' in info:
                    info = info['entries'][0]
                url = info['url']
                title = info['title']
                self.queue.append((url, title))
                await ctx.send(f'birazdan **{title}** söyleyeceğim')
        if not ctx.voice_client.is_playing():
            await self.play_next(ctx)

    async def play_next(self, ctx):
        if self.queue:
            url, title = self.queue.pop(0)
            source = await discord.FFmpegOpusAudio.from_probe(url, **FFMPEG_OPTIONS)
            ctx.voice_client.play(source, after=lambda _:self.client.loop.create_task(self.play_next(ctx)))
            await ctx.send(f'şimdi **{title}** söyleyeceğim')
        elif not ctx.voice_client.is_playing():
            await ctx.send("söylenecek şarkı kalmmadı")

    @commands.command()
    async def skip(self, ctx):
        if ctx.voice_client and ctx.voice_client.is_playing():
            ctx.voice_client.stop()
            await ctx.send("geçtim bunu o zaman")

bot = commands.Bot(command_prefix='!', intents=intents)

async def main():
    await bot.add_cog(MusicBot(bot))
    await bot.start(TOKEN)    

asyncio.run(main())

> [youtube:search] Extracting URL: ytsearch:yesterday  [download]
> Downloading playlist: yesterday  [youtube:search] query "yesterday":
> Downloading web client config [youtube:search] query "yesterday" page
> 1: Downloading API JSON  [youtube:search] Playlist yesterday:
> Downloading 1 items of 1  [download] Downloading item 1 of 1 
> [youtube] Extracting URL: https://www.youtube.com/watch?v=wXTJBr9tt8Q
> [youtube] wXTJBr9tt8Q: Downloading webpage [youtube] wXTJBr9tt8Q:
> Downloading tv client config  [youtube] wXTJBr9tt8Q: Downloading
> player 9fe2e06e-main  [youtube] wXTJBr9tt8Q: Downloading tv player API
> JSON  [youtube] wXTJBr9tt8Q: Downloading ios player API JSON 
> [youtube] wXTJBr9tt8Q: Downloading m3u8 information  [download]
> Finished downloading playlist: yesterday

The last part is the terminal and it doesnt show any errors afterwards.


Solution

  • Youtube streams can expire, you need to handle those if you aren't downloading the file directly. You can try reconnect or retry options in youtube_dl or ffmpeg, or you can create a function/method that will handle it. Some examples from old answers, may be outdated: stackoverflow.com/questions/66610012/…

    – Benjin

    Commented Jun 24 at 8:18

    yes this works