willwade / tts-wrapper

TTS-Wrapper makes it easier to use text-to-speech APIs by providing a unified and easy-to-use interface.
MIT License
9 stars 2 forks source link

pause, resume function not working #27

Open Chafid opened 2 weeks ago

Chafid commented 2 weeks ago

Prerequisites

For more information, see the contributing guide.

Description

When we use these functions: tts.pause_audio() tts.resume_audio() audio playback does not pause and resume during playback, but instead the functions were executed after playback is finished

Steps to Reproduce

Run: tts.speak_streamed("test pause resume") tts.pause_audio() input("Press enter to resume") tts.resume_audio()

Expected behavior: [What you expected to happen] audio is played until finished then paused

Actual behavior: [What actually happened]

willwade commented 2 weeks ago

Again. Test test test this logic.


import threading
import time
import sounddevice as sd
import numpy as np

class AbstractTTS(ABC):
    def __init__(self):
        super().__init__()
        self.playing = threading.Event()      # Controls playback state
        self.paused = threading.Event()       # Controls pause state
        self.paused.clear()                   # Not paused by default
        self.playing.clear()                  # Not playing by default
        self.stream = None
        self.audio_data = None
        self.position = 0

    def speak_streamed(self, text: str) -> None:
        """Starts streaming audio playback."""
        self.audio_data = self.synth_to_bytes(text)  # Assume PCM bytes
        self.playing.set()  # Start playback
        self.position = 0  # Reset playback position

        # Start the playback thread
        playback_thread = threading.Thread(target=self._play_audio)
        playback_thread.start()

    def _play_audio(self):
        """Plays audio and checks for pause/resume state."""
        with sd.OutputStream(samplerate=22050, channels=1, dtype="int16") as stream:
            while self.position < len(self.audio_data):
                # Check if the playback should be paused
                self.paused.wait()  # Blocks here if paused

                # Get the next chunk of audio
                chunk_size = 1024
                chunk = self.audio_data[self.position:self.position + chunk_size]
                self.position += chunk_size

                # Convert to numpy array and play
                if chunk:
                    stream.write(np.frombuffer(chunk, dtype=np.int16))

                time.sleep(0.01)  # Adjust for smoother playback control

            self.playing.clear()  # Playback finished

    def pause_audio(self):
        """Pauses audio playback by clearing the paused event."""
        self.paused.clear()
        print("Audio paused")

    def resume_audio(self):
        """Resumes audio playback by setting the paused event."""
        self.paused.set()
        print("Audio resumed")
willwade commented 2 days ago

No. My comment here I think is whack. @Chafid this is taking more than 5 minutes.. its yours!