Прослушивание голосового канала discord.py
В общем такая ситуация, я хочу чтобы бот заходил в голосовой канал (если там кто-то есть), и прослушивал разговор, записывая его в файл для дальнейшей манипуляции с ним. С заходом в голосовой канал всё понятно, но вот как слушать звук? Порылся немного в документации и нашёл voice_client.source
, но этот код безуспешно выводит None:
audio_data = ctx.voice_client.source
while True:
print(audio_data)
Как я понял, надо создать отдельный аудио поток opus, но как это сделать я хз вообще. Кто может помочь разобраться?
Ответы (1 шт):
Вы можете использовать библиотеку PyCord
.
pip install py-cord
Там у класса VoiceClient
есть метод start_recording
, позволяющий записывать звук пользователей в канале.
В свое время, я даже столкнулся с проблемой записи нескольких пользователей, которая была связана с некоторыми особенностями в реализации получения звуковых пакетов от пользователей. После того, как я сообщил о проблеме, реализацию немного поменяли и прямо в репозиторий библиотеки добавили пример, как пользоваться этим методом и получать звуковой файл записи.
Есть пример audio_recording.py
— для записи одного пользователя
Есть таже пример для записи нескольких пользователей: audio_recording_merged.py
Код второго:
import io
import pydub # pip install pydub==0.25.1
import discord
from discord.sinks import MP3Sink
bot = discord.Bot()
@bot.event
async def on_ready():
print(f"Logged in as {bot.user}")
async def finished_callback(sink: MP3Sink, channel: discord.TextChannel):
mention_strs = []
audio_segs: list[pydub.AudioSegment] = []
files: list[discord.File] = []
longest = pydub.AudioSegment.empty()
for user_id, audio in sink.audio_data.items():
mention_strs.append(f"<@{user_id}>")
seg = pydub.AudioSegment.from_file(audio.file, format="mp3")
# Determine the longest audio segment
if len(seg) > len(longest):
audio_segs.append(longest)
longest = seg
else:
audio_segs.append(seg)
audio.file.seek(0)
files.append(discord.File(audio.file, filename=f"{user_id}.mp3"))
for seg in audio_segs:
longest = longest.overlay(seg)
with io.BytesIO() as f:
longest.export(f, format="mp3")
await channel.send(
f"Finished! Recorded audio for {', '.join(mention_strs)}.",
files=files + [discord.File(f, filename="recording.mp3")],
)
@bot.command()
async def join(ctx: discord.ApplicationContext):
"""Join the voice channel!"""
voice = ctx.author.voice
if not voice:
return await ctx.respond("You're not in a vc right now")
await voice.channel.connect()
await ctx.respond("Joined!")
@bot.command()
async def start(ctx: discord.ApplicationContext):
"""Record the voice channel!"""
voice = ctx.author.voice
if not voice:
return await ctx.respond("You're not in a vc right now")
vc: discord.VoiceClient = ctx.voice_client
if not vc:
return await ctx.respond(
"I'm not in a vc right now. Use `/join` to make me join!"
)
vc.start_recording(
MP3Sink(),
finished_callback,
ctx.channel,
sync_start=True, # WARNING: This feature is very unstable and may break at any time.
)
await ctx.respond("The recording has started!")
@bot.command()
async def stop(ctx: discord.ApplicationContext):
"""Stop the recording"""
vc: discord.VoiceClient = ctx.voice_client
if not vc:
return await ctx.respond("There's no recording going on right now")
vc.stop_recording()
await ctx.respond("The recording has stopped!")
@bot.command()
async def leave(ctx: discord.ApplicationContext):
"""Leave the voice channel!"""
vc: discord.VoiceClient = ctx.voice_client
if not vc:
return await ctx.respond("I'm not in a vc right now")
await vc.disconnect()
await ctx.respond("Left!")
bot.run("TOKEN")
Поизучайте как он работает, почитайте документацию к методу start_recording
и, думаю, сможете на основе этого примера сделать какую-то свою реализацию.