diff --git a/CHANGELOG.md b/CHANGELOG.md index 0df83c03a2..4906fd851e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ These changes are available on the `master` branch, but have not yet been releas `tags`. ([#2520](https://github.com/Pycord-Development/pycord/pull/2520)) - Added `Member.guild_banner` and `Member.display_banner` properties. ([#2556](https://github.com/Pycord-Development/pycord/pull/2556)) +- Added `elapsed` method to `VoiceClient`. + ([#2587](https://github.com/Pycord-Development/pycord/pull/2587/)) - Added optional `filter` parameter to `utils.basic_autocomplete()`. ([#2590](https://github.com/Pycord-Development/pycord/pull/2590)) diff --git a/discord/player.py b/discord/player.py index 508bf906ae..9868aabe70 100644 --- a/discord/player.py +++ b/discord/player.py @@ -724,6 +724,7 @@ def __init__(self, source: AudioSource, client: VoiceClient, *, after=None): self._current_error: Exception | None = None self._connected: threading.Event = client._connected self._lock: threading.Lock = threading.Lock() + self._played_frames_offset: int = 0 if after is not None and not callable(after): raise TypeError('Expected a callable for the "after" parameter.') @@ -751,10 +752,12 @@ def _do_run(self) -> None: # wait until we are connected self._connected.wait() # reset our internal data + self._played_frames_offset += self.loops self.loops = 0 self._start = time.perf_counter() self.loops += 1 + # Send the data read from the start of the function if it is not None if first_data is not None: data = first_data @@ -809,6 +812,7 @@ def pause(self, *, update_speaking: bool = True) -> None: self._speak(False) def resume(self, *, update_speaking: bool = True) -> None: + self._played_frames_offset += self.loops self.loops = 0 self._start = time.perf_counter() self._resumed.set() @@ -834,3 +838,7 @@ def _speak(self, speaking: bool) -> None: ) except Exception as e: _log.info("Speaking call in player failed: %s", e) + + def played_frames(self) -> int: + """Gets the number of 20ms frames played since the start of the audio file.""" + return self._played_frames_offset + self.loops diff --git a/discord/voice_client.py b/discord/voice_client.py index b9d4766883..4ba571c9a7 100644 --- a/discord/voice_client.py +++ b/discord/voice_client.py @@ -40,6 +40,7 @@ from __future__ import annotations import asyncio +import datetime import logging import select import socket @@ -988,3 +989,9 @@ def send_audio_packet(self, data: bytes, *, encode: bool = True) -> None: ) self.checked_add("timestamp", opus.Encoder.SAMPLES_PER_FRAME, 4294967295) + + def elapsed(self) -> datetime.timedelta: + """Returns the elapsed time of the playing audio.""" + if self._player: + return datetime.timedelta(milliseconds=self._player.played_frames() * 20) + return datetime.timedelta()