Почему система очереди wavlink не работает правильно при воспроизведении нескольких песен с использованием библиотеки waPython

Программы на Python
Ответить
Anonymous
 Почему система очереди wavlink не работает правильно при воспроизведении нескольких песен с использованием библиотеки wa

Сообщение Anonymous »

Привет, ребята, я здесь новичок, я пытался создать бот discord.py с музыкальным процессором, который использует сервер nodelink и wavelink. я сам сделал версию кода и почти работал, а потом попросил ИИ переписать ее, вся моя проблема в очереди. на самом деле он никогда не воспроизводит вторую песню в очереди...

Код: Выделить всё

@commands.Cog.listener()
async def on_wavelink_track_end(self, payload: wavelink.TrackEndEventPayload):
"""Called when a track finishes playing."""
if not payload.player or not payload.player.guild:
return

guild = payload.player.guild
logging.info(f"on_wavelink_track_end fired - Guild: {guild.id}, Reason: {payload.reason}")

# CRITICAL: Ignore 'REPLACED' to prevent skipping the song that just started
if payload.reason == "REPLACED":
logging.info(f"Ignoring REPLACED event for guild {guild.id}")
return

logging.info(f"Track ended in guild {guild.id}. Reason: {payload.reason}. Triggering play_next...")

# Trigger the next song
await asyncio.sleep(0.5) # Small delay to allow state to settle
await self.play_next(guild, force=True)

@commands.Cog.listener()
async def on_wavelink_track_stuck(self, payload: wavelink.TrackStuckEventPayload):
"""Called when a track gets stuck."""
if not payload.player or not payload.player.guild:
return
logging.warning(f"Track Stuck in guild {payload.player.guild.id}: {payload.threshold}ms")
await asyncio.sleep(0.5)
self.bot.loop.create_task(self.play_next(payload.player.guild, force=True))

async def play_next(self, guild: discord.Guild, force: bool = False, user_skipped: bool = False, recursion: int = 0):
if recursion > 3:
logging.error(f"play_next recursion limit reached for guild {guild.id}")
return

queue = self.get_queue(guild.id)

if queue.disconnect_task:
queue.disconnect_task.cancel()
queue.disconnect_task = None

vc: wavelink.Player = guild.voice_client
if not vc:
logging.warning(f"No voice client for guild {guild.id}")
return

# Safety check: if already playing, don't interfere (prevents double-play from skip + track_end)
# BUT if force=True (from TrackEnd or Skip), we MUST proceed even if it thinks it's playing
if vc.playing and not force and not user_skipped:
logging.info(f"play_next called but already playing for guild {guild.id}, skipping")
return

# CRITICAL FIX: Check if queue has songs BEFORE calling next()
# This ensures manually queued songs always play first
has_queued_songs = len(queue.queue) > 0
track = queue.next(skipped=user_skipped)

logging.info(f"play_next - Guild {guild.id}: track={track.title if track else 'None'}, had_queued={has_queued_songs}, queue_now={len(queue.queue)}, loop_mode={queue.loop_mode}")

# 1. HANDLE EMPTY QUEUE / RADIO / 24-7
# Only generate new tracks if we didn't have any queued songs
if not track and not has_queued_songs:
logging.info(f"No track in queue for guild {guild.id}.  Checking radio/247/autoplay modes...")
# 24/7 Mode Logic
if queue.is_24_7_mode:
non_bot_members = [m for m in vc.channel.members if not m.bot]
if not non_bot_members:
if not queue.is_idle:
queue.is_idle = True
await self._clear_vc_status(vc)
# If skipping in 24/7 mode and no members, we should stop playing
if user_skipped and vc.playing:
await vc.stop()
return # Stay connected but idle

if queue.is_idle: queue.is_idle = False

# Fetch random track
random_track_info = await self._get_random_track_general()
if random_track_info:
artist, title = random_track_info
logging.info(f"24/7: Found track {title} by {artist}")
w_track = await self.search_wavelink(f"{artist} - {title}")
if w_track:
track = self._create_track(w_track, self.bot.user, vc.channel.id)
track.provider = "24/7 Radio"
queue.current = track
logging.info(f"24/7: Created track {track.title}")
else:
logging.warning(f"24/7: Failed to search for {artist} - {title}")
else:
logging.warning("24/7: Failed to get random track info")

# Radio Mode Logic
# Radio Mode Logic (with Retry)
elif queue.radio_mode:
logging.info(f"Radio mode active for guild {guild.id}")

# Try up to 3 times to get a valid track
for attempt in range(3):
if queue.radio_artist:
random_track_info = await self._get_random_track_from_artist(queue.radio_artist)
else:
random_track_info = await self._get_random_track_general()

if random_track_info:
artist, title = random_track_info
logging.info(f"Radio: Found track {title} by {artist} (Attempt {attempt+1})")
w_track = await self.search_wavelink(f"{artist} - {title}")

if w_track:
track = self._create_track(w_track, self.bot.user, vc.channel.id)
track.provider = f"Radio ({queue.radio_artist if queue.radio_artist else 'General'})"
queue.current = track
logging.info(f"Radio: Created track {track.title}")
break # Success! Exit the retry loop
else:
logging.warning(f"Radio: Failed to search Wavelink for {artist} - {title}")
else:
logging.warning("Radio: Failed to get track info from LastFM")

# Small delay before retry
await asyncio.sleep(0.5)

# Autoplay Logic
# Autoplay Logic
# Use history[-1] because queue.current is cleared by queue.next()
last_track = queue.history[-1] if queue.history else None
if not track and queue.autoplay and last_track:
artist, title = self._parse_track_info(last_track)
similar = await self._get_similar_track(artist, title)
if similar:
s_artist, s_title = similar
w_track = await self.search_wavelink(f"{s_artist} - {s_title}")
if w_track:
track = self._create_track(w_track, self.bot.user, last_track.channel_id)
track.provider = "Autoplay"
queue.current = track

# 2.  FINAL CHECK & PLAY
if not track:
if user_skipped and vc.playing:
await vc.stop()

if not queue.is_24_7_mode:
await self._clear_vc_status(vc)
if not queue.disconnect_task:
queue.disconnect_task = self.bot.loop.create_task(self._scheduled_disconnect(guild))
else:
# In 24/7 mode, if we failed to get a track, retry shortly
await asyncio.sleep(5)
await self.play_next(guild, force=True, recursion=recursion+1)
return

self.cancel_scrobble_task(guild.id)
track.start_time = time.time()

# Check if original_track is valid
if not track.original_track:
logging.error(f"Track {track.title} has no original_track object! Skipping...")
await self.play_next(guild, force=True, recursion=recursion+1)
return

# Add to history
queue.history.append(track)

# Update VC Status (Background Task)
artist, title = self._parse_track_info(track)
status_text = f"🎵 {title} - {artist}"
self.bot.loop.create_task(self._update_vc_status(vc, status_text[:128]))

try:
# Play with Wavelink
logging.info(f"Attempting to play track: {track.title} in guild {guild.id}")
if vc.paused:
await vc.pause(False)

await asyncio.sleep(1)

await vc.play(track.original_track)

# Set volume if saved
if guild.id in self.volumes:
await vc.set_volume(int(self.volumes[guild.id] * 100))

# Scrobble
await self.update_lastfm_for_channel(vc.channel, track)
self.scrobble_tasks[guild.id] = self.bot.loop.create_task(
self.wait_and_scrobble(guild.id, vc.channel, track)
)

# Generate and send NOW PLAYING CARD
channel = self.bot.get_channel(track.channel_id)
if channel:
try:
card = await self._generate_now_playing_card(track, track.requester)
view = MusicControls(self.bot, guild.id)

if card:
# Send beautiful card
file = discord.File(card, filename="nowplaying.png")
await channel.send(file=file, view=view)
else:
# Fallback to embed if card generation fails
embed = discord.Embed(
title="🎵 Now Playing",
description=f"**[{track.title}]({track.url})**",
color=discord.Color.purple()
)
embed.add_field(name="Requested by", value=track.requester.mention)
embed.add_field(name="Source", value=f"**{track.provider}**", inline=True)
duration_str = time.strftime('%M:%S', time.gmtime(track.duration))
embed.add_field(name="Duration", value=f"`{duration_str}`", inline=True)
if track.thumbnail:
embed.set_thumbnail(url=track.thumbnail)
await channel.send(embed=embed, view=view)
except Exception as e:
print(f"Failed to send now playing message: {e}")
pass

except Exception as e:
print(f"Play Error: {e}")
logging.error(f"Play Error in guild {guild.id}: {e}")
await asyncio.sleep(1)
await self.play_next(guild, force=True, recursion=recursion+1)

@commands.Cog.listener()
async def on_wavelink_track_start(self, payload: wavelink.TrackStartEventPayload):
"""Called when a track starts playing - for debugging."""
if not payload.player or not payload.player.guild:
return
logging.info(f"Track STARTED in guild {payload.player.guild.id}: {payload.track.title}")
Я попробовал множество исправлений и в конце концов применил ИИ, но, к сожалению, даже это не помогло.

Подробнее здесь: https://stackoverflow.com/questions/798 ... liple-song
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»