From 260c3acf932719f621bd47aea59a3593cbfb629c Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 13 Jan 2026 16:37:53 +0100 Subject: add support for internet streams for playing --- cogs/music/play_utils.py | 95 ++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 36 deletions(-) (limited to 'cogs/music/play_utils.py') diff --git a/cogs/music/play_utils.py b/cogs/music/play_utils.py index 8de7543..0614157 100644 --- a/cogs/music/play_utils.py +++ b/cogs/music/play_utils.py @@ -226,34 +226,49 @@ class PlayUtils: return None @staticmethod - async def play(ctx, filepath, delete_after_play=False): + async def play(ctx, source, delete_after_play=False): + """Play audio from a local file or URL. + + Args: + ctx: Discord context + source: Either a local file path or a URL to stream from + delete_after_play: If True, delete the file after playing (only for local files) + """ # Check if user is in a voice channel if not ctx.author.voice or not ctx.author.voice.channel: await ctx.respond("Musisz być na kanale głosowym, żebym mógł dołączyć!", ephemeral=True) - if delete_after_play and os.path.exists(filepath): + if delete_after_play and os.path.exists(source): try: - os.remove(filepath) - logger.info(f"Cleaned up temporary file: {filepath}") + os.remove(source) + logger.info(f"Cleaned up temporary file: {source}") except Exception as e: - logger.error(f"Error cleaning up file {filepath}: {str(e)}") + logger.error(f"Error cleaning up file {source}: {str(e)}") return - - logger.info(f"Attempting to play: {filepath}") - - # Get absolute path and verify file exists - if not os.path.isabs(filepath): - filepath = os.path.abspath(filepath) - logger.debug(f"Converted to absolute path: {filepath}") + + is_url = source.startswith(('http://', 'https://')) - if not os.path.exists(filepath): - error_msg = f"File not found: {filepath}" - logger.error(error_msg) - await ctx.respond("Nie znaleziono pliku do odtworzenia", ephemeral=True) - return + if not is_url: + # Handle local file + logger.info(f"Attempting to play local file: {source}") - filename = os.path.basename(filepath) - logger.info(f"Playing file: {filename} (from: {filepath})") - + # Get absolute path and verify file exists + if not os.path.isabs(source): + source = os.path.abspath(source) + logger.debug(f"Converted to absolute path: {source}") + + if not os.path.exists(source): + error_msg = f"File not found: {source}" + logger.error(error_msg) + await ctx.respond("Nie znaleziono pliku do odtworzenia", ephemeral=True) + return + + filename = os.path.basename(source) + display_name = os.path.splitext(filename)[0] + else: + # Handle URL + logger.info(f"Attempting to play stream from URL: {source}") + display_name = source # Use URL as display name for streams + # Get or create voice client vc = ctx.voice_client target_channel = ctx.author.voice.channel @@ -275,23 +290,31 @@ class PlayUtils: vc.stop() # Play the audio - source = discord.FFmpegPCMAudio(source=filepath) - vc.play(source) - - try: - metadata = mutagen.File(filepath) - title = metadata.get('title', None) - logger.debug(f"Read metadata - title: {title}") - except Exception as e: - logger.warning(f"Could not read metadata from {filepath}: {str(e)}") - title = None - - if title is None: - title = os.path.splitext(os.path.basename(filepath))[0] - logger.debug(f"Using filename as title: {title}") + if is_url: + # For URLs, use FFmpeg with the direct URL + ffmpeg_options = { + 'options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', + 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5' + } + source = discord.FFmpegPCMAudio(source, **ffmpeg_options) + else: + # For local files, use default options + source = discord.FFmpegPCMAudio(source=source) + + # Try to get metadata for local files + try: + metadata = mutagen.File(source) + if metadata: + title = metadata.get('title', [None])[0] if hasattr(metadata, 'get') else None + if title: + display_name = title + logger.debug(f"Read metadata - title: {title}") + except Exception as e: + logger.warning(f"Could not read metadata from {source}: {str(e)}") - logger.info(f"Playing file: {title}") - await ctx.respond(f"grom: {title}") + vc.play(source) + logger.info(f"Playing: {display_name}") + await ctx.respond(f"grom: {display_name}") except Exception as e: logger.error(f"Error in play: {str(e)}", exc_info=True) -- cgit v1.2.3