Skip to content
This repository has been archived by the owner on Mar 13, 2023. It is now read-only.

Commit

Permalink
feat: Allow audio pre-buffering (#570)
Browse files Browse the repository at this point in the history
* feat: Allow for audio pre-buffering

* feat: Allow setting buffer duration through pre-buffer
  • Loading branch information
LordOfPolls authored Jul 31, 2022
1 parent 547c4f6 commit 2a0f5ce
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
28 changes: 25 additions & 3 deletions naff/api/voice/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def audio_complete(self) -> bool:
return False
return True

def _create_process(self) -> None:
def _create_process(self, *, block: bool = True) -> None:
before = (
self.ffmpeg_before_args if isinstance(self.ffmpeg_before_args, list) else self.ffmpeg_before_args.split()
)
Expand Down Expand Up @@ -162,8 +162,9 @@ def _create_process(self) -> None:
)
self.read_ahead_task.start()

# block until some data is in the buffer
self.buffer.initialised.wait()
if block:
# block until some data is in the buffer
self.buffer.initialised.wait()

def _read_ahead(self) -> None:
while self.process:
Expand All @@ -181,6 +182,24 @@ def _read_ahead(self) -> None:
self.buffer.initialised.set()
time.sleep(0.1)

def pre_buffer(self, duration: None | float = None) -> None:
"""
Start pre-buffering the audio.
Args:
duration: The duration of audio to pre-buffer.
"""
if duration:
self.buffer_seconds = duration

if self.process and self.process.poll() is None:
raise RuntimeError("Cannot pre-buffer an already running process")
# sanity value enforcement to prevent audio weirdness
self.buffer = AudioBuffer()
self.buffer.initialised.clear()

self._create_process(block=False)

def read(self, frame_size: int) -> bytes:
"""
Reads frame_size bytes of audio from the buffer.
Expand All @@ -190,6 +209,9 @@ def read(self, frame_size: int) -> bytes:
"""
if not self.process:
self._create_process()
if not self.buffer.initialised.is_set():
# we cannot start playing until the buffer is initialised
self.buffer.initialised.wait()

data = self.buffer.read(frame_size)

Expand Down
5 changes: 1 addition & 4 deletions naff/api/voice/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ def play(self) -> None:
"""Start playing."""
self._stop_event.clear()
self._resume.set()
try:
self.start()
finally:
self.current_audio.cleanup()
self.start()

def run(self) -> None:
"""The main player loop to send audio to the voice websocket."""
Expand Down

0 comments on commit 2a0f5ce

Please sign in to comment.