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.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
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.
Answered By – MCW