Как заставить дискорд бота запустить песню?



@Similization

Использую мак ос на м1, бота делал через библиотеку disnake, встрял с так называемым opus, вроде бы все скачал, но он стабильно выдает мне такую ошибку (это с использованием disnake.opus.load_opus(‘opus’)):

Ignoring exception in slash command 'play_yam':
Traceback (most recent call last):
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/ext/commands/slash_core.py", line 730, in invoke
    await call_param_func(self.callback, inter, self.cog, **kwargs)
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/ext/commands/params.py", line 1022, in call_param_func
    return await maybe_coroutine(safe_call, function, **kwargs)
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/utils.py", line 596, in maybe_coroutine
    return await value
  File "/Users/similization/Programming/python/discord_bot/bot_example.py", line 143, in play_yam_command
    vc = await inter.user.voice.channel.connect()
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/opus.py", line 285, in load_opus
    _lib = libopus_loader(name)
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/opus.py", line 206, in libopus_loader
    lib = ctypes.cdll.LoadLibrary(name)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/ctypes/__init__.py", line 444, in LoadLibrary
    return self._dlltype(name)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/ctypes/__init__.py", line 366, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(opus, 0x0006): tried: 'opus' (no such file), '/usr/local/lib/opus' (no such file), '/usr/lib/opus' (no such file), '/Users/similization/Programming/python/discord_bot/opus' (no such file)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/ext/commands/interaction_bot_base.py", line 1255, in process_application_commands
    await app_command.invoke(interaction)
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/ext/commands/slash_core.py", line 739, in invoke
    raise CommandInvokeError(exc) from exc
disnake.ext.commands.errors.CommandInvokeError: Command raised an exception: OSError: dlopen(opus, 0x0006): tried: 'opus' (no such file), '/usr/local/lib/opus' (no such file), '/usr/lib/opus' (no such file), '/Users/similization/Programming/python/discord_bot/opus' (no such file)

Это другая ошибка, без попытки загрузить opus:

Ignoring exception in slash command 'play_yam':
Traceback (most recent call last):
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/ext/commands/slash_core.py", line 730, in invoke
    await call_param_func(self.callback, inter, self.cog, **kwargs)
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/ext/commands/params.py", line 1022, in call_param_func
    return await maybe_coroutine(safe_call, function, **kwargs)
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/utils.py", line 596, in maybe_coroutine
    return await value
  File "/Users/similization/Programming/python/discord_bot/bot_example.py", line 145, in play_yam_command
    player = vc.play(disnake.FFmpegPCMAudio('music/example.mp3'), after=lambda e: print('done', e))
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/voice_client.py", line 589, in play
    self.encoder = opus.Encoder()
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/opus.py", line 344, in __init__
    _OpusStruct.get_opus_version()
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/opus.py", line 337, in get_opus_version
    raise OpusNotLoaded()
disnake.opus.OpusNotLoaded

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/ext/commands/interaction_bot_base.py", line 1255, in process_application_commands
    await app_command.invoke(interaction)
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/disnake/ext/commands/slash_core.py", line 739, in invoke
    raise CommandInvokeError(exc) from exc
disnake.ext.commands.errors.CommandInvokeError: Command raised an exception: OpusNotLoaded:

Ответы на других форумах пользы не принесли.
Кусок кода с командой для запуска музыки:

import asyncio
import json
import random

import disnake
from disnake.ext import commands

from typing import Literal
import balaboba_integration as bi

intents = disnake.Intents.default()
intents.members = True
intents.message_content = True

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


@bot.slash_command(name="play_yam", description="Search for song in yandex music")
async def play_yam_command(inter, song_name: str):
    if inter.user.voice is None:
        return await inter.response.send_message(f"you should be in a voice channel")
    if inter.user.voice.channel.guild.voice_client is None:
        disnake.opus.load_opus('opus')
        vc = await inter.user.voice.channel.connect()
        await inter.response.send_message(f"bot connected to a voice channel")
        player = vc.play(disnake.FFmpegPCMAudio('music/example.mp3'), after=lambda e: print('done', e))
        player.start()
        while not player.is_done():
            await asyncio.sleep(1)
        # disconnect after the player has finished
        player.stop()
        return await vc.disconnect()
    if inter.user.voice.channel.guild.voice_client.is_connected():
        return await inter.response.send_message(f"bot sits in another voice channel")


@bot.slash_command(name="stop_yam", description="Stop playing music")
async def stop_command(inter):
    if inter.user.voice is None:
        return await inter.response.send_message(f"bot is already left all channels")
    await inter.user.voice.channel.guild.voice_client.disconnect()
    await inter.response.send_message(f"bot disconnected from a voice channel")


@bot.event
async def on_ready():
    print(f"Logged in as {bot.user} (ID: {bot.user.id})\n------")


if __name__ == "__main__":
    with open("configuration.json") as json_data_file:
        data = json.load(json_data_file)
    bot_data = data["bot"]
    bot.run(bot_data["token"])

Пока вместо поиска музыки стоит заглушка.
Еще интереснее, добавил
import libopus
И получил:

Traceback (most recent call last):
  File "/Users/similization/Programming/python/discord_bot/bot_example.py", line 4, in <module>
    import opuslib
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/opuslib/__init__.py", line 19, in <module>
    from .exceptions import OpusError  # NOQA
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/opuslib/exceptions.py", line 10, in <module>
    import opuslib.api.info
  File "/Users/similization/Programming/python/discord_bot/lib/python3.9/site-packages/opuslib/api/__init__.py", line 20, in <module>
    raise Exception(
Exception: Could not find Opus library. Make sure it is installed.

Хотя библиотека установлена (через brew Install opus)
Нашел пару ответов, что он ищет не там эту либу, что в целом не круто, может есть варианты получше, для того, чтобы заставить бота запускать песни?


Решения вопроса 1



@Similization Автор вопроса

Рассказываю, что я сделал, чтобы данный код заработал
1) скачиваем opus на ваш мак:
brew install opus
2) нужно найти, куда скачался данный файл:
brew info opus
у меня это было /opt/homebrew/Cellar/opus
3) находим исполняемый файл:
/opt/homebrew/Cellar/opus/1.3.1/lib
у меня их два libopus.dylib и libopus.0.dylib
4) далее, как вы могли заметить, он ищет libopus по трем путям:

disnake.ext.commands.errors.CommandInvokeError: Command raised an exception: OSError: dlopen(opus, 0x0006): tried: 'opus' (no such file), 
'/usr/local/lib/opus' (no such file), 
'/usr/lib/opus' (no such file), 
'/Users/similization/Programming/python/discord_bot/opus' (no such file)

, я добавил его к себе в папку проекта
5) наконец добавляем куда-нибудь в начало проекта
disnake.opus.load_opus('libopus.dylib')
и бот подключился и запустил музыку


Ответы на вопрос 1



@Vindicar

Ну тебе бот пишет прямым текстом где он ищет библиотеку:

OSError: dlopen(opus, 0x0006): tried: ‘opus’ (no such file), ‘/usr/local/lib/opus‘ (no such file), ‘/usr/lib/opus‘ (no such file), ‘/Users/similization/Programming/python/discord_bot/opus‘ (no such file)

Найди, куда именно установился опус, и создай символическую ссылку на библиотеку по одному из указанных путей. Лучше всего по последнему, я полагаю.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *