Made youtube links stream instead of download

This commit is contained in:
G2-Games 2024-08-22 20:11:08 -05:00
parent ddfb0cbc89
commit 4a0bd1f819

View file

@ -1,22 +1,14 @@
import discord import discord, subprocess, glob, os, os.path, urllib.request, ffmpeg
import subprocess import re, time, datetime, yt_dlp, typing, functools
import glob from time import strftime, gmtime
import os
import os.path
import urllib.request
import ffmpeg
import re
import time
import datetime
import yt_dlp
import typing
import functools
from time import strftime
from time import gmtime
from yt_dlp import YoutubeDL from yt_dlp import YoutubeDL
from asyncio import sleep from asyncio import sleep
from discord.ext import commands from discord.ext import commands
from StringProgressBar import progressBar from StringProgressBar import progressBar
import uuid
import logging
logging.basicConfig(level=logging.DEBUG)
intents = discord.Intents.default() intents = discord.Intents.default()
intents.message_content = True intents.message_content = True
@ -45,18 +37,18 @@ async def get_ids(ctx):
user_voice_channel = ctx.author.voice user_voice_channel = ctx.author.voice
return server_id, voice_channel, user_voice_channel return server_id, voice_channel, user_voice_channel
async def prepare_filesave(server_id): async def getFileNames(server_id):
downloading = 1 downloading = 1
# Get the current unix timestamp to the nearest millisecond for the filename # Get the current unix timestamp to the nearest millisecond for the filename
stamp = str(int(str(time.time()).replace('.', ''))) uuid_stamp = uuid.uuid1()
id = "tmp" + stamp + ".flac" audioname = str(uuid_stamp) + "audio"
thumbname = "tmp" + stamp + ".png" thumbname = str(uuid_stamp) + "image"
# Create the id and thumbnail of the attachment as "tmp<timestamp>.flac" and "tmp<timestamp>.png" respectively # Create the id and thumbnail of the attachment as "tmp<timestamp>.flac" and "tmp<timestamp>.png" respectively
# And add the server ID as the path, making it unique # And add the server ID as the path, making it unique
id = os.path.join(str(server_id),id) audioname = os.path.join(str(server_id), audioname)
thumbname = os.path.join(str(server_id),thumbname) thumbname = os.path.join(str(server_id), thumbname)
return id, thumbname return audioname, thumbname
@bot.command() @bot.command()
async def play(ctx, *, query: str = None): async def play(ctx, *, query: str = None):
@ -109,11 +101,13 @@ async def play(ctx, *, query: str = None):
if voice_channel.is_playing(): if voice_channel.is_playing():
await ctx.send("The bot is already playing, adding song to queue", delete_after=3) await ctx.send("The bot is already playing, adding song to queue", delete_after=3)
print("1");
if ctx.message.attachments: if ctx.message.attachments:
downloading = 1 downloading = 1
notice = await ctx.send(":arrow_double_up: Uploading...", suppress_embeds=True) notice = await ctx.send(":arrow_double_up: Uploading...", suppress_embeds=True)
for song in ctx.message.attachments: for song in ctx.message.attachments:
id, thumbname = await prepare_filesave(server_id) filename, thumbname = await getFileNames(server_id)
# Make sure the file is either audio or video # Make sure the file is either audio or video
filetype = song.content_type filetype = song.content_type
@ -121,15 +115,15 @@ async def play(ctx, *, query: str = None):
await notice.edit(content=":no_entry_sign: Not a valid video or audio file...") await notice.edit(content=":no_entry_sign: Not a valid video or audio file...")
continue continue
await song.save(id) await song.save(filename)
# Grab thumbnail from file # Grab thumbnail from file
f = open("tmp", "w") f = open("tmp", "w")
subprocess.run(["ffmpeg", "-y", "-i", id, "-map", "0:v", "-map", "-0:V", "-c", "copy", thumbname], stderr=subprocess.STDOUT, stdout=f) subprocess.run(["ffmpeg", "-y", "-i", filename, "-map", "0:v", "-map", "-0:V", "-c", "copy", thumbname], stderr=subprocess.STDOUT, stdout=f)
# Grab metadata from file # Grab metadata from file
f = open("tmp", "w") f = open("tmp", "w")
subprocess.run(["ffmpeg", "-y", "-i", id, "-f", "ffmetadata", str(server_id) + "/meta.txt"], stderr=subprocess.STDOUT, stdout=f) subprocess.run(["ffmpeg", "-y", "-i", filename, "-f", "ffmetadata", str(server_id) + "/meta.txt"], stderr=subprocess.STDOUT, stdout=f)
file_title = song.filename file_title = song.filename
file_artist = None file_artist = None
@ -159,7 +153,7 @@ async def play(ctx, *, query: str = None):
thumbnail = "assets/unknown.png" thumbnail = "assets/unknown.png"
try: try:
duration = ffmpeg.probe(id)['format']['duration'] duration = ffmpeg.probe(filename)['format']['duration']
except: except:
duration = None duration = None
@ -169,7 +163,7 @@ async def play(ctx, *, query: str = None):
"artist": file_artist.rstrip(), "artist": file_artist.rstrip(),
"album": file_album.rstrip(), "album": file_album.rstrip(),
"url": song.url, "url": song.url,
"id": id, "id": filename,
"thumbnail": thumbnail, "thumbnail": thumbnail,
"duration": duration "duration": duration
} }
@ -180,7 +174,7 @@ async def play(ctx, *, query: str = None):
downloading = 0 downloading = 0
await notice.edit(content=":white_check_mark: Successfully uploaded \"" + song.filename + "\"", delete_after=3) await notice.edit(content=":white_check_mark: Successfully uploaded \"" + song.filename + "\"", delete_after=3)
elif query[0:4] != "http" and query[0:3] != "www": elif query[0:4] != "http" and query[0:3] != "www":
id, thumbname = await prepare_filesave(server_id) filename, thumbname = await getFileNames(server_id)
# Let the user know the bot is searching for a video # Let the user know the bot is searching for a video
notice = await ctx.send(":mag_right: Searching for \"" + query + "\" ...", suppress_embeds=True) notice = await ctx.send(":mag_right: Searching for \"" + query + "\" ...", suppress_embeds=True)
@ -193,21 +187,7 @@ async def play(ctx, *, query: str = None):
thumb_url = info["thumbnail"] thumb_url = info["thumbnail"]
duration = info["duration"] duration = info["duration"]
# Download thumbnail
urllib.request.urlretrieve(thumb_url, thumbname)
# Use yt-dlp to download the audio file from youtube to the "tmp.flac" file
print(str(server_id) + " | " + audio_url) print(str(server_id) + " | " + audio_url)
await notice.edit(content=":arrow_double_down: Downloading \"" + title + "\": " + audio_url, suppress=True)
# Download selected video
ydl_opts = {
'format': 'flac/bestaudio/best',
'outtmpl': id,
'quiet': True
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(audio_url)
# Create the item dictionary # Create the item dictionary
item = { item = {
@ -215,8 +195,9 @@ async def play(ctx, *, query: str = None):
"artist": None, "artist": None,
"album": None, "album": None,
"url": audio_url, "url": audio_url,
"id": id, "id": filename,
"thumbnail": thumbname, "thumbnail": None,
"thumbnail_url": thumb_url,
"duration": duration "duration": duration
} }
@ -224,7 +205,7 @@ async def play(ctx, *, query: str = None):
queue_list[server_id].append(item) queue_list[server_id].append(item)
downloading = 0 downloading = 0
elif query[0:4] == "http" or query[0:3] == "www": elif query[0:4] == "http" or query[0:3] == "www":
id, thumbname = await prepare_filesave(server_id) filename, thumbname = await getFileNames(server_id)
# Let the user know the bot is searching for a video # Let the user know the bot is searching for a video
notice = await ctx.send(":mag_right: Searching for \"" + query + "\" ...", suppress_embeds=True) notice = await ctx.send(":mag_right: Searching for \"" + query + "\" ...", suppress_embeds=True)
@ -241,21 +222,7 @@ async def play(ctx, *, query: str = None):
thumb_url = info["thumbnail"] thumb_url = info["thumbnail"]
duration = info["duration"] duration = info["duration"]
# Download thumbnail
urllib.request.urlretrieve(thumb_url, thumbname)
# Use yt-dlp to download the audio file from youtube to the "tmp.flac" file
print(str(server_id) + " | " + query) print(str(server_id) + " | " + query)
await notice.edit(content=":arrow_double_down: Downloading \"" + title + "\": " + query, suppress=True)
# Download selected video
ydl_opts = {
'format': 'flac/bestaudio/best',
'outtmpl': id,
'quiet': True
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(query)
# Create the item dictionary # Create the item dictionary
item = { item = {
@ -263,12 +230,13 @@ async def play(ctx, *, query: str = None):
"artist": None, "artist": None,
"album": None, "album": None,
"url": query, "url": query,
"id": id, "id": filename,
"thumbnail": thumbname, "thumbnail": None,
"thumbnail_url": thumb_url,
"duration": duration "duration": duration
} }
await notice.edit(content=":white_check_mark: Downloaded \"" + title + "\": " + query, suppress=True, delete_after=3) await notice.edit(content=":white_check_mark: Added \"" + title + "\": " + query, suppress=True, delete_after=3)
queue_list[server_id].append(item) queue_list[server_id].append(item)
downloading = 0 downloading = 0
else: else:
@ -295,6 +263,7 @@ async def play(ctx, *, query: str = None):
song_name = queue_list[server_id][queue_position]['name'] song_name = queue_list[server_id][queue_position]['name']
song_thumb = queue_list[server_id][queue_position]['thumbnail'] song_thumb = queue_list[server_id][queue_position]['thumbnail']
song_duration = queue_list[server_id][queue_position]['duration'] song_duration = queue_list[server_id][queue_position]['duration']
song_thumb_url = queue_list[server_id][queue_position]['thumbnail_url']
song_thumbname = str(int(time.time())) + ".png" song_thumbname = str(int(time.time())) + ".png"
# Create the embed # Create the embed
@ -304,12 +273,30 @@ async def play(ctx, *, query: str = None):
song_desc = "Name: " + song_name + "\nURL: " + song_url song_desc = "Name: " + song_name + "\nURL: " + song_url
embed=discord.Embed(title="▶️ Playing: " + song_name, url=song_url, description=song_desc, color=0x42f5a7) embed=discord.Embed(title="▶️ Playing: " + song_name, url=song_url, description=song_desc, color=0x42f5a7)
await playing.add_files(discord.File(song_thumb, filename=song_thumbname)) if song_thumb is not None:
embed.set_image(url="attachment://" + song_thumbname) await playing.add_files(discord.File(song_thumb, filename=song_thumbname))
embed.set_thumbnail(url="attachment://" + song_thumbname)
elif song_thumb_url is not None:
embed.set_thumbnail(url=song_thumb_url)
await playing.edit(embed=embed) await playing.edit(embed=embed)
song_source = None
pipe = False
if song_url is not None:
song_source = subprocess.Popen(
['yt-dlp', '-q', '-o', '-', '-x', song_url],
stdout=subprocess.PIPE,
).stdout
pipe = True
print("Playing song through yt-dlp")
else:
print("Playing song from file")
song_source = song_id
# Play the converted audio in the voice channel from the temporary file # Play the converted audio in the voice channel from the temporary file
player = voice_channel.play(discord.FFmpegPCMAudio(source=song_id)) # or the FFMPEG stream
player = voice_channel.play(discord.FFmpegOpusAudio(source=song_source, pipe=pipe))
time1 = int(time.time()) time1 = int(time.time())
total = int(float(song_duration)) total = int(float(song_duration))
@ -328,8 +315,17 @@ async def play(ctx, *, query: str = None):
embed=discord.Embed(title="▶️ Playing: " + song_name, url=song_url, description=song_desc, color=0x42f5a7) embed=discord.Embed(title="▶️ Playing: " + song_name, url=song_url, description=song_desc, color=0x42f5a7)
else: else:
embed=discord.Embed(title="⏸ Paused: " + song_name, url=song_url, description=song_desc, color=0x42f5a7) embed=discord.Embed(title="⏸ Paused: " + song_name, url=song_url, description=song_desc, color=0x42f5a7)
embed.set_image(url="attachment://" + song_thumbname)
embed.add_field(name=str(datetime.timedelta(seconds=current)) + "/" + str(datetime.timedelta(seconds=total)), value=bardata[0], inline=False) if song_thumb is not None:
embed.set_thumbnail(url="attachment://" + song_thumbname)
elif song_thumb_url is not None:
embed.set_thumbnail(url=song_thumb_url)
embed.add_field(
name=str(datetime.timedelta(seconds=current)) + "/" + str(datetime.timedelta(seconds=total)),
value=bardata[0],
inline=False
)
await playing.edit(embed=embed) await playing.edit(embed=embed)
if server_info[server_id]["loop"]: if server_info[server_id]["loop"]:
@ -627,4 +623,4 @@ async def on_command_error(ctx, error):
await ctx.send("Unknown command", delete_after=3) await ctx.send("Unknown command", delete_after=3)
# Run the bot using the Discord bot token # Run the bot using the Discord bot token
bot.run("<BOT TOKEN GOES HERE>") bot.run("<>")