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

Heroku-22栈下Discord.py音乐机器人无法播放音乐的解决办法

解决Heroku-22栈上Discord音乐机器人播放异常问题

Heroku-22基于Ubuntu 22.04,和Heroku-20的Ubuntu 20.04相比,预装软件版本、依赖环境存在差异,导致原代码中的youtube-dl和FFmpeg配置无法适配新环境。以下是针对性修复方案:

核心问题分析

  • youtube-dl停止维护:原代码使用的youtube-dl已停止更新,无法兼容新的流媒体协议,在Heroku-22环境下无法正确拉取音频流。
  • FFmpeg参数不足:Heroku-22的FFmpeg版本更高,默认配置无法处理流媒体的重连需求,导致播放中断或无法启动。

修复步骤

1. 替换依赖库:用yt-dlp替代youtube-dl

yt-dlp是youtube-dl的活跃分支,兼容新平台和协议,可完全替代原库功能:

  • 修改requirements.txt,将youtube-dl替换为yt-dlp
  • 代码中同步替换导入和初始化逻辑

2. 调整FFmpeg配置

添加流媒体重连参数,确保在Heroku网络环境下稳定拉取音频流。

3. 确认Heroku环境的FFmpeg支持

Heroku-22默认预装FFmpeg,若缺失可在Heroku控制台的应用设置中添加buildpack:https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git

修改后的完整代码

import yt_dlp
import discord
from discord import app_commands, Interaction
import asyncio
import os

class MyClient(discord.Client):
    async def on_ready(self):
        await self.wait_until_ready()
        await tree.sync()
        print(f"login at {self.user}")
        
intents = discord.Intents.all()
client = MyClient(intents=intents)
tree = app_commands.CommandTree(client)

yt_dlp.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
    'format': 'bestaudio/best',
    'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
    'restrictfilenames': True,
    'noplaylist': True,
    'nocheckcertificate': True,
    'ignoreerrors': False,
    'logtostderr': False,
    'quiet': True,
    'no_warnings': True,
    'default_search': 'auto',
    'source_address': '0.0.0.0',  # 绑定IPv4避免IPv6问题
}

# 新增FFmpeg重连参数,适配Heroku-22环境
ffmpeg_options = {
    'options': '-vn -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
}

ytdl = yt_dlp.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
    def __init__(self, source, *, data, volume=0.5):
        super().__init__(source, volume)

        self.data = data
        self.title = data.get('title')
        self.url = data.get('url')

    @classmethod
    async def from_url(cls, url, *, loop=None, stream=True):
        loop = loop or asyncio.get_event_loop()
        data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
        if 'entries' in data:
            # 取播放列表第一个条目
            data = data['entries'][0]
        filename = data['url'] if stream else ytdl.prepare_filename(data)
        return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)

queue = {}
@tree.command(name="play", description="play music")
async def playmusic(interaction: Interaction, url_title: str, playfirst: bool=False):
    await interaction.response.send_message("I'm looking for music!!")
    guild = str(interaction.guild.id)
    try:
        queue[guild]
    except KeyError:
        queue[guild] = []
    if interaction.user.voice is None:
        await interaction.edit_original_response(content="you must join any voice channel")
    else:
        voice_client: discord.VoiceClient = discord.utils.get(client.voice_clients, guild=interaction.guild)
        if voice_client is None:
            await interaction.user.voice.channel.connect()
            voice_client: discord.VoiceClient = discord.utils.get(client.voice_clients, guild=interaction.guild)
        player = await YTDLSource.from_url(url_title, loop=None)
        if playfirst and len(queue[guild]) > 1:
            queue[guild].insert(1, player)
        else:
            queue[guild].append(player)
        if not voice_client.is_playing():
            voice_client.play(player, after=None)
            await interaction.edit_original_response(content=f"{player.title} playing!!")
        else:
            await interaction.edit_original_response(content=f"{player.title} enqueued!")
        await asyncio.sleep(7)
        await interaction.delete_original_response()

# 从环境变量获取token,避免硬编码
client.run(os.getenv('DISCORD_TOKEN'))

额外配置说明

  • requirements.txt示例:
discord.py>=2.3.0
yt-dlp>=2023.10.13
  • Heroku环境变量:将Discord机器人token添加到Heroku应用的环境变量中,键为DISCORD_TOKEN,替代代码中的硬编码token。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:12:30