Потоковая передача аудиоконтента с YouTube на Discord

Я разрабатываю бота Discord, используя discord.py, и в рамках этого бота мне поручено создавать музыкальный функционал. Я действительно это сделал, и бот будет воспроизводить песни с помощью модуля pytube. Для этого он загружает лучший источник звука, преобразует его в .wav (чтобы Discord мог его понять), затем открывает этот файл и воспроизводит его через голосовой клиент, чтобы его могли услышать все участники голосового вызова. Проблема в том, что он работает очень медленно из-за необходимости загрузки полного аудио перед началом воспроизведения. Это код в его нынешнем виде:

    # Plays a Youtube object in the voice call.
    async def play_youtube_object(self, yt:YouTube, interaction:discord.Interaction, voice_client):
        try:
            # Extract audio stream with highest audio bitrate
            audio_stream = yt.streams.filter(file_extension = "webm").order_by('abr').desc().first()
            audio_filename = os.path.abspath(rf"./data/music cache/{yt.author}{hex(random.randint(1,999999))[2:]}")
            audio_stream.download(filename=audio_filename+".webm")

            # Convert from .webm to .wav
            audio_f = moviepy.AudioFileClip(audio_filename+".webm")
            audio_f.write_audiofile(audio_filename+".wav", fps=48000) # Discord requires 48kHz, 44.1kHz causes it to speed up by 8.125%.
            remove_file(audio_filename + ".webm") # Remove the .webm since we're now done with it

            # Open the downloaded audio file in binary mode and create a PCMAudio object which can be interpreted by discord
            f = open(audio_filename+".wav", "rb")
            source = PCMAudio(f)

            # Play the audio
            voice_client.play(source)

            # Wait until the song is finished before ending the function
            while voice_client.is_playing() or voice_client.is_paused():
                await asyncio.sleep(1)
            f.close()
        except ...

Мое потенциальное решение этой проблемы (если это возможно) — транслировать аудио прямо с YouTube, конвертировать его в источник PCMAudio и передавать в Discord Live. Проблема в том, что я понятия не имею, с чего начать реализацию этого. Является ли это возможным? Если да, то где мне следует начать исследования для этого? Есть ли модуль, который может помочь?

По сути, цель состоит в том, чтобы получить близкую к мгновенной обратную связь: объект pytubeYouTube анализируется в подпрограмме play_youtube_object, и звук начинает воспроизводиться для пользователя в Discord сразу после этого (или, по крайней мере, не с задержкой до 20 секунд, как сейчас). .

Любая помощь или подсказки приветствуются, заранее спасибо! :D

Я не знаю, поддерживает ли pytube потоковую передачу, но у вас yt-dlp есть возможность перенаправления в другую программу, а ffmpeg (который также используется в moviepy) должна быть возможность читать из другой программы, а также перенаправляться в другую программу - используя pipe- в bash в Linux он может выглядеть похоже на yt-dlp -o - ... | ffmpeg .... | vlc -, но subprocess в python также может его перенаправить, но, возможно, над этим придется поработать.

furas 01.06.2024 02:27

В Python также есть модуль ffmpeg-python, который может быть полезен.

furas 01.06.2024 02:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
109
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решено! Благодаря некоторой помощи, указывающей мне в правильном направлении из комментариев. Использование yt-dlp и использование ffmpeg по конвейеру сработало блестяще и устранило эту неприятную задержку (теперь примерно 3 секунды, что совсем неплохо).

Это рабочий код, в котором на данный момент немного беспорядок, но я решил закончить этот пост, прежде чем продолжить работу над ним:

    async def play_youtube_url(self, url, interaction:discord.Interaction, voice_client):
        ydl_opts = {
            'format': 'bestaudio/best',
            'quiet': True,
            'noplaylist': True
        }

        try:
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                info_dict = ydl.extract_info(url, download=False)
                audio_url = info_dict['url']

            ffmpeg_options = {
                'options': '-vn'
            }

            source = FFmpegPCMAudio(audio_url, **ffmpeg_options)
            voice_client.play(source)

            while voice_client.is_playing() or voice_client.is_paused():
                await asyncio.sleep(1)
        except Exception as e:
            await interaction.followup.send(f"An error occured: {e}")

Благодаря yt-dlp программа сможет обрабатывать гораздо больше аудиоисточников, но не тех, которые имеют защиту DRM (например, Spotify), поэтому мне, возможно, придется посмотреть, смогу ли я найти способ обойти это, или, если кто-нибудь что-нибудь знает, пожалуйста, прокомментируйте: ).

Другие вопросы по теме