I'm a high school student making a Discord bot as a final project, and I'm having issues finding a working tutorial or baseline for playing YouTube audio in Discordpy Rewrite. If there's a tutorial I'm missing or basic code that can do this, I'd be extremely grateful for that.
I've already looked at some tutorials and tried them, but they don't seem to work for one reason or another. I've spent a lot of project time searching, but I can't seem to find what I'm looking for. Below, I found some code for making a bot play an MP3 file, but I'm unsure how to do it using a YouTube link.
@bot.command()
async def mp3play(context):
user = context.message.author
voice_channel = user.voice.voice_channel
channel = None
if voice_channel != None:
channel=voice_channel.name
vc = await channel.connect()
audio = vc.play("holder.mp3", after=lambda: print("Complete."))
vc.start()
while vc.is_playing():
await asyncio.sleep(1)
vc.stop()
else:
await ctx.send("User must be in a voice channel.")
first, you need to implement a class called YTDLSource
to control yotube_dl
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes
}
ffmpeg_options = {
'options': '-vn'
}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
@classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
# take first item from a playlist
data = data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
use this class in your music command, notice that my def play belongs to other class that i call Voice.
@commands.command(pass_context=True)
async def play(self, ctx, *, url):
print(url)
server = ctx.message.guild
voice_channel = server.voice_client
async with ctx.typing():
player = await YTDLSource.from_url(url, loop=self.bot.loop)
ctx.voice_channel.play(player, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('Now playing: {}'.format(player.title))
before this, just add in your cog and enjoy!