Como Transmitir Áudio em Tempo Real com Bot do Discord Usando Pycord Sinks
🔍 WiseChecker

Como Transmitir Áudio em Tempo Real com Bot do Discord Usando Pycord Sinks

Bots do Discord podem fazer mais do que enviar mensagens de texto e reproduzir arquivos de áudio. Você pode criar um bot que escuta um canal de voz e processa áudio em tempo real. Isso é útil para reconhecimento de fala, transcrição de áudio, análise musical ou moderação de voz ao vivo. Pycord é um wrapper moderno da API do Discord para Python que inclui um recurso chamado sinks. Sinks permitem que seu bot receba e manipule dados de áudio conforme eles chegam dos canais de voz. Este artigo explica como configurar o Pycord, criar um cliente de voz e usar sinks para transmitir áudio em tempo real de canais de voz do Discord.

Principais Conclusões: Pycord Sinks para Transmissão de Áudio em Tempo Real

  • Classes de sink do Pycord: Classes integradas como PCMAudio e FFmpegPCMAudio permitem que seu bot receba e processe áudio sem salvar arquivos no disco.
  • Método voice_client.listen(): Inicia a escuta de um canal de voz e envia dados de áudio PCM brutos para uma função de callback que você define.
  • Parâmetro after em create_ffmpeg_player: Aciona uma função após a reprodução de áudio terminar, útil para encadear ações de escuta e reprodução.

ADVERTISEMENT

O Que São Pycord Sinks e Por Que Você Precisa Deles

Pycord é um fork mantido do discord.py que suporta a API de voz do Discord. Um sink é um mecanismo que captura dados de áudio de um canal de voz e os entrega ao seu código em pedaços. Sem sinks, seu bot só pode reproduzir áudio ou enviar arquivos de áudio. Com sinks, seu bot pode processar áudio ao vivo para conversão de fala em texto, detecção de som ou comandos personalizados acionados por voz.

O conceito central é simples. Quando seu bot entra em um canal de voz, ele cria um objeto VoiceClient. Chamar voice_client.listen() inicia um sink que recebe dados de áudio de cada usuário falando no canal. Os dados chegam como quadros PCM brutos. Você escreve uma função de callback que recebe cada quadro. Dentro dessa função, você pode analisar o áudio, salvá-lo ou encaminhá-lo para outro serviço.

Pycord fornece dois tipos principais de sink. A classe PCMAudio funciona para dados PCM brutos sem transcodificação. A classe FFmpegPCMAudio usa FFmpeg para converter formatos de áudio dinamicamente. Para transmissão em tempo real, PCMAudio é a melhor escolha porque evita a sobrecarga de codificação e decodificação. Você precisa ter o FFmpeg instalado no servidor ou na máquina local se planeja usar FFmpegPCMAudio.

Pré-requisitos para Transmitir Áudio em Tempo Real

Antes de escrever qualquer código, verifique se estes itens estão em ordem:

  • Python 3.8 ou superior instalado no sistema.
  • Biblioteca Pycord instalada via pip: pip install py-cord[voice]. O extra [voice] instala as dependências de áudio necessárias, como pynacl e audioop.
  • FFmpeg instalado e adicionado ao PATH do sistema. Baixe de ffmpeg.org e coloque o executável em uma pasta que esteja na variável de ambiente PATH.
  • Um token de bot do Discord. Crie um bot no Portal do Desenvolvedor do Discord, ative as intenções Server Members Intent e Message Content Intent, e convide o bot para um servidor com as permissões connect e speak.
  • Um canal de texto onde o bot possa enviar mensagens ou um canal de voz dedicado para testes.

Passos para Criar um Bot que Transmite Áudio em Tempo Real

Os passos a seguir criam um bot simples que entra em um canal de voz, escuta todo o áudio e imprime o tamanho dos dados de áudio no console. Você pode substituir o callback pela sua própria lógica de processamento.

  1. Crie o script do bot
    Abra um novo arquivo Python chamado voice_sink_bot.py. Importe os módulos necessários: discord, asyncio e discord.ext.commands. Defina uma instância do bot com a classe commands.Bot e defina o prefixo de comando como !.
  2. Defina a classe de callback do sink
    Crie uma classe que herda de discord.Sink. Sobrescreva o método __init__ para inicializar um buffer. Sobrescreva o método write. O método write recebe dois argumentos: data (um objeto bytes de áudio PCM) e user (um objeto discord.User ou discord.Member). Dentro de write, processe os dados de áudio. Neste exemplo, imprima o comprimento dos dados e o nome do usuário.
  3. Crie o comando join
    Adicione um comando chamado join que recebe um parâmetro ctx. Verifique se o autor está em um canal de voz. Se não estiver, envie uma mensagem de erro. Use await ctx.author.voice.channel.connect() para fazer o bot entrar no canal. Armazene o voice_client para uso posterior.
  4. Crie o comando listen
    Adicione um comando chamado listen. Dentro do comando, obtenha o voice_client de ctx.voice_client. Se o bot não estiver conectado, envie uma mensagem pedindo para o usuário executar !join primeiro. Instancie sua classe de sink personalizada. Chame voice_client.listen(sink_instance) para iniciar a escuta. Envie uma mensagem de confirmação.
  5. Crie o comando stop
    Adicione um comando chamado stop. Chame voice_client.stop_listening() para parar o sink. Envie uma mensagem informando que a escuta foi interrompida.
  6. Execute o bot
    No final do script, adicione bot.run('SEU_TOKEN_DO_BOT'). Substitua SEU_TOKEN_DO_BOT pelo token real do seu bot. Execute o script com python voice_sink_bot.py.

Exemplo de Código Completo

Aqui está o script completo funcional para um bot que transmite áudio em tempo real e imprime os tamanhos dos dados:

import discord
from discord.ext import commands
import asyncio

class AudioSink(discord.Sink):
    def __init__(self):
        super().__init__()
        self.buffer = b''

    def write(self, data, user):
        self.buffer += data
        print(f"Recebidos {len(data)} bytes de {user}")

bot = commands.Bot(command_prefix='!')

@bot.command()
async def join(ctx):
    if ctx.author.voice:
        channel = ctx.author.voice.channel
        await channel.connect()
        await ctx.send(f"Entrou em {channel.name}")
    else:
        await ctx.send("Você não está em um canal de voz")

@bot.command()
async def listen(ctx):
    voice = ctx.voice_client
    if not voice:
        await ctx.send("O bot não está em um canal de voz. Use !join primeiro")
        return
    sink = AudioSink()
    voice.listen(sink)
    await ctx.send("Escutando áudio...")

@bot.command()
async def stop(ctx):
    voice = ctx.voice_client
    if voice and voice.is_listening():
        voice.stop_listening()
        await ctx.send("Escuta interrompida")
    else:
        await ctx.send("O bot não está escutando no momento")

bot.run('SEU_TOKEN_DO_BOT')

ADVERTISEMENT

Erros Comuns e Limitações ao Usar Pycord Sinks

O Bot Não Responde a Comandos de Voz

Se o bot entrar no canal mas não receber áudio, verifique se você ativou a Server Members Intent no Portal do Desenvolvedor do Discord. Sem essa intenção, o bot não consegue ver quem está falando. Verifique também se o bot tem a permissão speak no canal de voz. Sem ela, o bot não pode receber áudio.

Dados de Áudio Chegam em Pequenos Pedaços

Pycord envia dados de áudio em quadros de 20 milissegundos. Isso é normal para transmissão em tempo real. Se você precisar de buffers maiores para processamento, acumule os dados no método write do seu sink até ter amostras suficientes. Use um temporizador ou um contador de quadros para liberar o buffer periodicamente.

O Bot Trava Quando Vários Usuários Falam Simultaneamente

O método write é chamado separadamente para cada usuário. Sua classe sink recebe áudio de todos os falantes. Se sua lógica de processamento for lenta, use asyncio.create_task dentro de write para delegar o trabalho a uma corrotina separada. Isso evita bloquear o fluxo de áudio.

Erro FFmpeg Não Encontrado

Se você usar FFmpegPCMAudio e receber um FileNotFoundError, o FFmpeg não está instalado ou não está no PATH. Baixe a versão correta para seu sistema operacional de ffmpeg.org, extraia o executável e adicione a pasta à variável de ambiente PATH do sistema. Reinicie o terminal ou IDE após fazer a alteração.

O Bot Desconecta Após Reproduzir Áudio

O cliente de voz do Pycord desconecta automaticamente se nenhum áudio for reproduzido ou escutado por um período. Para manter o bot conectado, inicie o sink imediatamente após entrar ou use voice_client.play(discord.PCMAudio(silent_pcm_data)) para reproduzir uma faixa silenciosa. A faixa silenciosa mantém a conexão ativa sem produzir ruído audível.

Tipos de Pycord Sink: PCMAudio vs FFmpegPCMAudio

Item PCMAudio FFmpegPCMAudio
Formato de entrada Áudio PCM bruto (não comprimido) Qualquer formato suportado pelo FFmpeg (MP3, AAC, OGG, etc.)
Sobrecarga de transcodificação Nenhuma Uso adicional de CPU para decodificação
Requisito de instalação Nenhum além do Pycord FFmpeg deve estar instalado e no PATH
Adequação para transmissão em tempo real Melhor para processamento de baixa latência Adequado quando você precisa receber áudio em um codec diferente
Caso de uso Detecção de atividade de voz, reconhecimento de fala, análise personalizada Gravação de áudio em arquivos, reprodução de música, conversão de formato

Agora você tem um bot funcional que transmite áudio em tempo real de um canal de voz do Discord usando Pycord sinks. O próximo passo é substituir a instrução print no método write do sink pela lógica real de processamento de áudio. Por exemplo, você pode alimentar os dados PCM para uma biblioteca de reconhecimento de fala como speech_recognition ou uma biblioteca de análise de som como pydub. Lembre-se de manipular os dados de áudio em pedaços para manter o bot responsivo. Para uso avançado, explore a documentação da classe discord.Sink do Pycord para aprender sobre parâmetros personalizados de sink e o callback after para encadear ações de escuta e reprodução.

ADVERTISEMENT