kilkuwu
kilkuwu

Reputation: 47

Is there a thing in discord.py similar to streamTime in discord.js?

I'm using the package youtube_dl for the play music command. After a while, now I've been working on the rewind & forward commands, I have implemented a basic seek command using ffmpeg options, so the only thing left is just to find the position of the track being played by the bot, so that I can seek (position +- ) to go to that position of the track. The only thing I've figured out is to count the progression of the track like this.

async def count_progress(self):
    try:
        if not self.on_count:
            self.on_count = True
            while self.is_playing:
            await asyncio.sleep(0.99)  
            self.queue._queue[0].progress += 1
            self.on_count = False
    except (AttributeError, IndexError):
        self.on_count = False

I found that discord.js has something called streamTime, is there anything similar in discord.py? if not is there any better way than just counting the progress?

Update: I have forgotten about this post I made but ever since I have found a really nice solution to this problem.

What I did was making a custom class to count the bytes read by the player. (Thanks to this issue I made)

class CalculableAudio(discord.PCMVolumeTransformer):
    def __init__(self, original, start, volume: float):
        self.played = start
        super().__init__(original, volume=volume)

    def read(self) -> bytes:
        self.played += 20 # reading 20 frames at a time (1 sec = 1000 frames)
        return super().read()

Then whenever I want to find the seconds played I just need to do this:

seconds_played = ctx.voice_client.source.played//1000

Upvotes: 2

Views: 351

Answers (2)

MCW
MCW

Reputation: 56

I found this piece of code in player.py ( one of the modules of discord.py ) which is responsible for playing audio:

       while not self._end.is_set():
            # are we paused?
            if not self._resumed.is_set():
                # wait until we aren't
                self._resumed.wait()
                continue

            # are we disconnected from voice?
            if not self._connected.is_set():
                # wait until we are connected
                self._connected.wait()
                # reset our internal data
                self.loops = 0
                self._start = time.perf_counter()

            self.loops += 1
            data = self.source.read()

            if not data:
                self.stop()
                break

            play_audio(data, encode=not self.source.is_opus())
            next_time = self._start + self.DELAY * self.loops
            delay = max(0, self.DELAY + (next_time - time.perf_counter()))
            time.sleep(delay)

Therefore If you do :

loop_count = ctx.voice_client._player.loops

This gives the loop count which the playing thread has gone through, which can be useful for representing the time position of the audio.

time_position_in_second = loop_count // 50

I would also recommend doing a floor division of 50 to convert it into seconds, since the loop runs every 20 ms which is 50 times in a second.

Upvotes: 1

Zero
Zero

Reputation: 2286

A few things right here at your disposal!

TL;DR - No, such a thing never existed in discord.py and never will.


  • In discord.js v12 there used to be a StreamDispatcher which had a StreamDispatcher.streamTime property which was further removed in v13 (discord.js) and is being re-added as per this commit on the official Discord.js repository.
  • Talking about your primary issue, Discord.py has been discontinued and will not be receiving any updates from the developer from now on, and previously it did not have any such method to access the stream time of the client's stream ( voice / video - not applicable to bot users) anyway. You may refer the documentation's VoiceClient section and review for yourself that no such attribute / method existed at any point.

Although Python itself is at your service! you may declare a variable of the time it starts playing and subtract it from the time right now!

# when command is first used save it to a database or as a variable simply :P starttime = datetime.datetime.utcnow()
@client.command()
async def playtime(ctx):
    time = datetime.datetime.utcnow() - starttime
    time = str(uptime).split(".")[0]
    embed = discord.Embed(title="Total playtime", description=f"**time** = " + ''  + time +'')
    await ctx.send(embed=embed)

Upvotes: 3

Related Questions