Search code examples
audiopython-3.6pyaudiodiscord.py

Discord.py Play Voice From PyAudio


I'm trying to play live-audio from my microphone into my Discord bot, but I can't convert the stream from PyAudio into an acceptable format Discord can play. I have tried:

async def play_audio_in_voice():
    input_stream = p.open(format = FORMAT,
                channels = CHANNELS,
                rate = RATE,
                input = True,
                frames_per_buffer = CHUNK)
    while True:
        await voice_commands.play_voice(input_stream)

async def play_voice(self, input_stream):
        guild = #got guild here
        if guild.voice_client:
            data = input_stream.read(CHUNK, exception_on_overflow = False)
            voice_client = guild.voice_client
            voice_client.send_audio_packet(data)

and,

async def play_voice(self, input_stream):
        guild = #got guild here
        if guild.voice_client:
            data = input_stream.read(CHUNK, exception_on_overflow = False)
            stream = await discord.FFmpegPCMAudio(data)
            voice_client = guild.voice_client
            voice_client.send_audio_packet(data)

In the first code, I'm getting:

File "D:\Program Files\lib\site-packages\discord\voice_client.py", line 454, in send_audio_packet
    encoded_data = self.encoder.encode(data, self.encoder.SAMPLES_PER_FRAME)
AttributeError: 'NoneType' object has no attribute 'encode'

I am aware that I'm getting guild every time I call the function here, I'll fix that now :)


Solution

  • discord.FFmpegPCMAudio automatically does Opus encoding to your sound data. But send_audio_packet does not know if you are passing encoded or non-encoded data.

    Just add encode argument when calling send_audio_packet method:

    async def play_voice(self, input_stream):
        ...
        voice_client.send_audio_packet(data, encode=input_stream.is_opus())