|
114 | 114 | gemini_client = genai.Client(api_key=GEMINI_API_KEY) if GEMINI_API_KEY else None |
115 | 115 |
|
116 | 116 | ytdl_format_options = { |
117 | | - "format": "bestaudio/best", |
118 | | - "extractaudio": True, |
119 | | - "audioformat": "mp3", |
| 117 | + "format": "bestaudio[ext=webm]/bestaudio/best", |
120 | 118 | "outtmpl": os.path.join(music_dir, "%(title)s.%(ext)s"), |
121 | 119 | "restrictfilenames": True, |
122 | 120 | "noplaylist": False, |
| 121 | + "ignoreerrors": True, |
| 122 | + "prefer_ffmpeg": True, |
| 123 | + "quiet": True, |
123 | 124 | } |
124 | 125 |
|
125 | 126 | ffmpeg_options = { |
126 | | - "before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5", |
127 | | - "options": "-vn", |
| 127 | + "before_options": "-nostdin", |
| 128 | + "options": "-vn -filter:a loudnorm", |
128 | 129 | } |
129 | 130 |
|
130 | 131 |
|
@@ -715,15 +716,28 @@ async def after_playback(err, ctx): |
715 | 716 | async def play_song(ctx, info, filename): |
716 | 717 | state = await get_server_state(ctx.guild.id) |
717 | 718 | state["current_song"] = {"title": info["title"], "filename": filename} |
718 | | - ctx.voice_client.play( |
719 | | - discord.FFmpegPCMAudio( |
| 719 | + |
| 720 | + # Check if file exists |
| 721 | + if not os.path.exists(filename): |
| 722 | + await ctx.followup.send(f"Error: Audio file not found: {filename}") |
| 723 | + return |
| 724 | + |
| 725 | + try: |
| 726 | + # Create audio source with error handling |
| 727 | + audio_source = discord.FFmpegPCMAudio( |
720 | 728 | filename, |
721 | 729 | before_options=ffmpeg_options["before_options"], |
722 | 730 | options=ffmpeg_options["options"], |
723 | | - ), |
724 | | - after=lambda e: bot.loop.create_task(after_playback(e, ctx)), |
725 | | - ) |
726 | | - await ctx.followup.send(f'Now playing: {info["title"]}') |
| 731 | + ) |
| 732 | + |
| 733 | + ctx.voice_client.play( |
| 734 | + audio_source, |
| 735 | + after=lambda e: bot.loop.create_task(after_playback(e, ctx)), |
| 736 | + ) |
| 737 | + await ctx.followup.send(f'Now playing: {info["title"]}') |
| 738 | + except Exception as e: |
| 739 | + await ctx.followup.send(f"Error playing audio: {str(e)}") |
| 740 | + print(f"Audio playback error: {e}") |
727 | 741 |
|
728 | 742 |
|
729 | 743 | @bot.slash_command(description="Play a song or playlist from YouTube.") |
@@ -761,11 +775,26 @@ async def play(ctx, *, query): |
761 | 775 | info = ydl.extract_info(url, download=True) |
762 | 776 | if info and "entries" in info: |
763 | 777 | for entry in info["entries"]: |
| 778 | + # Get the actual downloaded filename |
764 | 779 | filename = ydl.prepare_filename(entry) |
765 | | - state["playlist_queue"].append({"info": entry, "filename": filename}) |
| 780 | + actual_file = find_downloaded_file(filename) |
| 781 | + |
| 782 | + if actual_file: |
| 783 | + state["playlist_queue"].append({"info": entry, "filename": actual_file}) |
| 784 | + else: |
| 785 | + print(f"Could not find downloaded file for: {entry.get('title', 'Unknown')}") |
| 786 | + |
766 | 787 | elif info: |
| 788 | + # Get the actual downloaded filename |
767 | 789 | filename = ydl.prepare_filename(info) |
768 | | - state["playlist_queue"].append({"info": info, "filename": filename}) |
| 790 | + actual_file = find_downloaded_file(filename) |
| 791 | + |
| 792 | + if actual_file: |
| 793 | + state["playlist_queue"].append({"info": info, "filename": actual_file}) |
| 794 | + else: |
| 795 | + await ctx.followup.send(f"Downloaded file not found. Check music directory.") |
| 796 | + return |
| 797 | + |
769 | 798 | except Exception as e: |
770 | 799 | await ctx.followup.send(f"Error: {str(e)}") |
771 | 800 | return |
@@ -1063,4 +1092,47 @@ async def whats_new(ctx, from_tool_call=False): |
1063 | 1092 | return error_message |
1064 | 1093 |
|
1065 | 1094 |
|
| 1095 | +def find_downloaded_file(base_filename): |
| 1096 | + """Find the actual downloaded file with various extensions.""" |
| 1097 | + possible_extensions = ['.webm', '.mp3', '.m4a', '.mp4', '.opus'] |
| 1098 | + base_name = os.path.splitext(base_filename)[0] |
| 1099 | + |
| 1100 | + for ext in possible_extensions: |
| 1101 | + full_path = base_name + ext |
| 1102 | + if os.path.exists(full_path): |
| 1103 | + print(f"Found audio file: {full_path}") |
| 1104 | + return full_path |
| 1105 | + |
| 1106 | + # Also check if the original filename exists |
| 1107 | + if os.path.exists(base_filename): |
| 1108 | + print(f"Found audio file: {base_filename}") |
| 1109 | + return base_filename |
| 1110 | + |
| 1111 | + print(f"No audio file found for: {base_filename}") |
| 1112 | + print(f"Checked: {[base_name + ext for ext in possible_extensions]}") |
| 1113 | + return None |
| 1114 | + |
| 1115 | + |
| 1116 | +@bot.slash_command(description="List downloaded music files for debugging.") |
| 1117 | +async def list_music(ctx): |
| 1118 | + """List all files in the music directory for debugging.""" |
| 1119 | + try: |
| 1120 | + if not os.path.exists(music_dir): |
| 1121 | + await ctx.respond("Music directory doesn't exist.") |
| 1122 | + return |
| 1123 | + |
| 1124 | + files = os.listdir(music_dir) |
| 1125 | + if not files: |
| 1126 | + await ctx.respond("No files found in music directory.") |
| 1127 | + return |
| 1128 | + |
| 1129 | + file_list = "\n".join(files[:10]) # Show first 10 files |
| 1130 | + if len(files) > 10: |
| 1131 | + file_list += f"\n... and {len(files) - 10} more files" |
| 1132 | + |
| 1133 | + await ctx.respond(f"**Music files ({len(files)} total):**\n```\n{file_list}\n```") |
| 1134 | + except Exception as e: |
| 1135 | + await ctx.respond(f"Error listing music files: {str(e)}") |
| 1136 | + |
| 1137 | + |
1066 | 1138 | bot.run(TOKEN) |
0 commit comments