You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nextcord Discord机器人MusicCog无法播放Spotify音乐求助

问题描述

我正在为Discord服务器开发机器人,使用Spotipy库添加音乐功能。机器人能正常加入语音频道,但调用!play ...命令时,只会显示“Now playing: ...”提示,没有任何声音输出。

已确认的信息:

  • 机器人拥有包括Administrator在内的所有权限
  • Spotify开发者密钥正确(已打码)
  • 对第三方库使用经验不足,不确定是否是代码问题

附上代码:

main.py

import nextcord, os, config
from nextcord.ext import commands

intents = nextcord.Intents.all()
intents.members = True

bot = commands.Bot(command_prefix="!", intents=intents)

@bot.event
async def on_ready():
    
    print("_______________________________________________________________")
    print(f"\nSuccessfully logged in as {bot.user.name} ({bot.user.id})\n")
    print("_______________________________________________________________")
    

# LOAD COGS
for filename in os.listdir('./cogs'):
    if filename.endswith('.py'):
        bot.load_extension(f"cogs.{filename[:-3]}")
    

bot.run(config.TOKEN)

music.py(Cog)

import nextcord
from nextcord.ext import commands
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials

class Music(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.voice = None
        self.sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials(client_id='//////', client_secret='/////'))

    @commands.command()
    async def join(self, ctx):
        if ctx.author.voice:
            self.voice = await ctx.author.voice.channel.connect()
            await ctx.send(f"Joined {ctx.author.voice.channel.name} voice channel.")
        else:
            await ctx.send("You need to be in a voice channel to use this command.")

    @commands.command()
    async def leave(self, ctx):
        if self.voice:
            await self.voice.disconnect()
            self.voice = None
            await ctx.send("Left the voice channel.")
        else:
            await ctx.send("I'm not connected to a voice channel.")

    @commands.command()
    async def play(self, ctx, *, query: str):
        if not self.voice or not self.voice.is_connected():
            await ctx.send("I'm not connected to a voice channel. Use `!join` first.")
            return

        try:
            # Search for the track on Spotify
            track_info = self.sp.search(q=query, type='track', limit=1)
            
            # Check if any tracks were found
            if not track_info or not track_info['tracks']['items']:
                await ctx.send("Couldn't find any matching tracks.")
                return

            # Get the first track found
            track = track_info['tracks']['items'][0]
            track_url = track['external_urls']['spotify']

            # Load and play the track
            source = await nextcord.FFmpegOpusAudio.from_probe(track_url)
            self.voice.play(source)

            # Send a message indicating the track is playing
            await ctx.send(f"Now playing: {track['name']} by {', '.join(artist['name'] for artist in track['artists'])}")
        except Exception as e:
            # Handle any errors that occur during track playback
            await ctx.send(f"An error occurred while playing the track: {e}")

    @commands.command()
    async def skip(self, ctx):
        if ctx.voice_client:
            ctx.voice_client.stop()
            await ctx.send("Skipped the current song.")

    @commands.command()
    async def stop(self, ctx):
        if ctx.voice_client:
            await ctx.voice_client.disconnect()
            self.voice = None
            await ctx.send("Stopped and disconnected from the voice channel.")

def setup(bot):
    bot.add_cog(Music(bot))
    print("MusicCog was loaded")

尝试过AI工具但没找到有效方案,求修复方法。

解决方案

问题核心在于你直接使用了Spotify的网页URL(track['external_urls']['spotify'])作为FFmpeg的输入源,而这个URL是网页链接,不是可直接解码的音频流,FFmpeg无法从中提取音频,所以没有声音输出。

Spotify的官方API不会提供完整的音频流(出于版权限制),你有两种可行的解决思路:


思路1:使用Spotify的预览音频

Spotify API会返回每个曲目30秒的预览音频URL,虽然时长有限,但可以快速验证播放功能:

修改play命令中获取音频源的部分:

# 替换原有的track_url和source部分
track = track_info['tracks']['items'][0]
preview_url = track.get('preview_url')

if not preview_url:
    await ctx.send("This track doesn't have a preview available.")
    return

# 加载预览音频
source = await nextcord.FFmpegOpusAudio.from_probe(preview_url)
self.voice.play(source)

思路2:使用第三方工具获取完整音频流(推荐)

如果需要播放完整曲目,需要借助yt-dlp这样的工具,通过曲目名称在YouTube上搜索对应的音频并获取流链接,再传给FFmpeg。

步骤如下:

  1. 安装依赖:
pip install yt-dlp
  1. 修改music.py的play命令:
# 导入yt-dlp
import yt_dlp

# 在Music类的__init__中添加yt-dlp配置
def __init__(self, bot):
    self.bot = bot
    self.voice = None
    self.sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials(client_id='//////', client_secret='/////'))
    self.ydl_opts = {
        'format': 'bestaudio/best',
        'quiet': True,
        'no_warnings': True,
        'default_search': 'ytsearch',
    }

# 修改play命令
@commands.command()
async def play(self, ctx, *, query: str):
    if not self.voice or not self.voice.is_connected():
        await ctx.send("I'm not connected to a voice channel. Use `!join` first.")
        return

    try:
        # 先通过Spotify获取准确的曲目名称和艺术家
        track_info = self.sp.search(q=query, type='track', limit=1)
        if not track_info or not track_info['tracks']['items']:
            await ctx.send("Couldn't find any matching tracks on Spotify.")
            return

        track = track_info['tracks']['items'][0]
        full_query = f"{track['name']} {', '.join(artist['name'] for artist in track['artists'])}"

        # 使用yt-dlp获取音频流
        with yt_dlp.YoutubeDL(self.ydl_opts) as ydl:
            info = ydl.extract_info(full_query, download=False)
            audio_url = info['entries'][0]['url']

        # 加载音频流
        source = await nextcord.FFmpegOpusAudio.from_probe(audio_url)
        self.voice.play(source)

        await ctx.send(f"Now playing: {track['name']} by {', '.join(artist['name'] for artist in track['artists'])}")
    except Exception as e:
        await ctx.send(f"An error occurred while playing the track: {str(e)}")

注意:这种方式依赖YouTube的内容,确保遵守相关版权规定。


此外,还需要确保你的服务器上已经安装了FFmpeg,Nextcord的音频功能依赖它。如果没有安装:

  • Windows:从FFmpeg官网下载并添加到系统PATH
  • Linux:用包管理器安装(如apt install ffmpeg)
  • macOS:用Homebrew安装(brew install ffmpeg)

内容的提问来源于stack exchange,提问作者fmDXP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:57:04