Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VoiceClient.play() plays too fast in the first 5-10 seconds when streaming from youtube url #9120

Open
3 tasks done
Gabeperson opened this issue Dec 7, 2022 · 3 comments
Open
3 tasks done
Labels
needs info This issue needs more information to be actionable.

Comments

@Gabeperson
Copy link

Gabeperson commented Dec 7, 2022

Summary

If you stream any audio from a youtube url (not sure if the same applies for non-youtube urls), the first 5-10 seconds of audio are sped up by a significant amount. This does not happen when downloading the video and playing it locally using youtube-dl. I have also tried extracting the video url using PyTube to see if youtube-dl was the problem, but the problem still persists with it as well. Also, this does not happen all the time. Sometimes, the audio will play normally. Sometimes it will play quickly. I have replicated this with basic_voice.py.

Reproduction Steps

  1. Copy the code from examples/basic_voice.py into python file.
  2. Put discord token in.
  3. Start the bot.
  4. Join a voice channel.
  5. Type !yt (link)
  6. Listen.

Minimal Reproducible Code

No response

Expected Results

Audio starts playing at the same speed throughout the entire clip.

Actual Results

Audio starts playing quickly then slows down to the usual pace after around 5-10 seconds of audio.

Intents

message_content

System Information

  • Python v3.11.0-final
  • discord.py v2.1.0-final
  • aiohttp v3.8.3
  • system info: Windows 10 10.0.19044

Checklist

  • I have searched the open issues for duplicates.
  • I have shown the entire traceback, if possible.
  • I have removed my token from display, if visible.

Additional Context

A question pertaining to the same (or a similar) bug was posted to StackOverflow around 1 year ago: https://stackoverflow.com/questions/70545716/discord-py-ffmpeg-song-plays-too-quickly-at-the-beginning
The only "workaround" that is possible is to asyncio.sleep(), as the comment in the post suggests. However, this does not guarantee that this will happen. It merely decreases the chances.
Due to the randomness and how asyncio.sleep() seems to somehow slightly alleviate this, I'm thinking it's some sort of network problem, but I could be wrong.

@Gabeperson Gabeperson added the unconfirmed bug A bug report that needs triaging label Dec 7, 2022
@TimG233
Copy link

TimG233 commented Dec 20, 2022

I got the same issue with the bot sometimes. I used extract_info rather than download for youtube_dl. I haven't found a solution yet. But seems like the situation is worse when testing locally than running the bot on a server (digital ocean). And the StackOverflow question is definitely not helping. (since asyncio.sleep(...) is not a proper way to solve this, and I mean like how long I should even sleep is something unknown and unsure)

@Rapptz Rapptz added needs info This issue needs more information to be actionable. and removed unconfirmed bug A bug report that needs triaging labels Dec 20, 2022
@blastbeng
Copy link

blastbeng commented Mar 16, 2023

+1 same problem here

I have a client server configuration.
The bot is the client, and I have apis server side that do the processing work.

The Bot calls the API /youtube/get/myvideoid, then the server starts downloading audio and send it back to the client using Flask send_file. So all i receive from the Bot is a pretranscoded mp3 audio.

This is the code:

@client.tree.command()
@app_commands.rename(url='url')
@app_commands.describe(url="Youtube link (Must match https://www.youtube.com/watch?v=1abcd2efghi)")
async def youtube(interaction: discord.Interaction, url: str):
    """Play a youtube link"""
    try:
        if interaction.user.voice and interaction.user.voice.channel:
            voice_client = get_voice_client_by_guildid(client.voice_clients, interaction.guild.id)
            await connect_bot_by_voice_client(voice_client, interaction.user.voice.channel)
            
            if not hasattr(voice_client, 'play'):
                await interaction.response.send_message(utils.translate(get_current_guild_id(interaction.guild.id),"Retry in a moment, I'm initializing the voice connection..."), ephemeral = True)
            elif not voice_client.is_playing():

                if "watch?v=" in url:
                    currentguildid = get_current_guild_id(interaction.guild.id)
                    message = utils.translate(get_current_guild_id(interaction.guild.id),"I'm playing audio from") +' ' + url
                    voice_client.play(discord.FFmpegPCMAudio(os.environ.get("API_URL")+os.environ.get("API_PATH_MUSIC")+"youtube/get/"+(url.split("watch?v=",1)[1])+"/"+urllib.parse.quote(currentguildid)), after=lambda e: logging.info(message))
                    await interaction.response.send_message(message, ephemeral = True)
                else:
                    await interaction.response.send_message(utils.translate(get_current_guild_id(interaction.guild.id),"Retry in a moment or use /stop command"), ephemeral = True)
            else:
                await interaction.response.send_message(utils.translate(get_current_guild_id(interaction.guild.id),"URL must match something like https://www.youtube.com/watch?v=1abcd2efghi"), ephemeral = True)

            
        else:
            await interaction.response.send_message(utils.translate(get_current_guild_id(interaction.guild.id),"You must be connected to a voice channel to use this command"), ephemeral = True)
    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        logging.error("%s %s %s", exc_type, fname, exc_tb.tb_lineno, exc_info=1)
        await interaction.response.send_message(utils.translate(get_current_guild_id(interaction.guild.id),"Error")+"!", ephemeral = True)

As you can see the important line is this one:
voice_client.play(discord.FFmpegPCMAudio(os.environ.get("API_URL")+os.environ.get("API_PATH_MUSIC")+"youtube/get/"+(url.split("watch?v=",1)[1])+"/"+urllib.parse.quote(currentguildid)), after=lambda e: logging.info(message))

I directly play the generated audio calling my APIS, the resulting URL is something like:
http://127.0.0.1/music/youtube/get/671b12ye6712/91236381278812821

Any thoughts?

@hc20k
Copy link

hc20k commented May 22, 2023

Has anyone found a reliable solution to this issue? I'm also having the same problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs info This issue needs more information to be actionable.
Projects
None yet
Development

No branches or pull requests

5 participants