Pycord-Development / pycord

Pycord is a modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python
https://docs.pycord.dev
MIT License
2.75k stars 462 forks source link

"The AudioData is already finished writing." #1578

Closed MahmoudAdelbghany closed 2 years ago

MahmoudAdelbghany commented 2 years ago

Summary

voice recieveng only work once then i get the exception "The AudioData is already finished writing."

Reproduction Steps

I used the voice recording example in the examples folder it works for the first time when i try to stop the second record it raise an exception "The AudioData is already finished writing." i believe it's because the attribute finished of the sink is set to true on first time and doesn't become false again when i manually set it to false in the stop function it works fine but there is wierd siund in the first record second

Minimal Reproducible Code

from enum import Enum
import discord

intents = discord.Intents().all()
intents.members = True

token = 'token'
bot = discord.Bot(debug_guilds=["servers"], prefix = '', intents=intents)
connections = {}

class Sinks(Enum):
    mp3 = discord.sinks.MP3Sink()
    wav = discord.sinks.WaveSink()
    pcm = discord.sinks.PCMSink()
    ogg = discord.sinks.OGGSink()
    mka = discord.sinks.MKASink()
    mkv = discord.sinks.MKVSink()
    mp4 = discord.sinks.MP4Sink()
    m4a = discord.sinks.M4ASink()

async def finished_callback(sink, channel: discord.TextChannel, *args):
    recorded_users = [f"<@{user_id}>" for user_id, audio in sink.audio_data.items()]
    await sink.vc.disconnect()
    files = [
        discord.File(audio.file, f"{user_id}.{sink.encoding}")
        for user_id, audio in sink.audio_data.items()
    ]
    await channel.send(
        f"Finished! Recorded audio for {', '.join(recorded_users)}.", files=files
    )

@bot.command()
async def start(ctx: discord.ApplicationContext):
    """
    Record your voice!
    """
    voice = ctx.author.voice
    sinky = Sinks.mp3

    if not voice:
        return await ctx.respond("You're not in a vc right now")

    vc = await voice.channel.connect()
    connections.update({ctx.guild.id: vc})

    vc.start_recording(
        sinky.value,
        finished_callback,
        ctx.channel,
    )

    await ctx.respond("The recording has started!")

@bot.command()
async def stop(ctx: discord.ApplicationContext):
    """Stop recording."""
    if ctx.guild.id in connections:
        vc = connections[ctx.guild.id]
        vc.stop_recording()
        del connections[ctx.guild.id]
        await ctx.delete()
    else:
        await ctx.respond("Not recording in this guild.")

bot.run(token)

Expected Results

i expected the example to work just fine

Actual Results

i get the exception "The AudioData is already finished writing." after the first time.

Intents

intents = discord.Intents().all()

System Information

Checklist

Additional Context

No response

Lulalaby commented 2 years ago

Status Update please @Pycord-Development/maintainers

plun1331 commented 2 years ago

You're reusing the same sink objects, you should use a new sink each time instead