Lenovo 360
Lenovo 360

Reputation: 647

How to pause, resume and stop pyttsx3 from speaking?

Is there any way to pause , resume and stop pyttsx3 from speaking?

I've tried many ways but I couldn't find a solution.

Here's the code:

from tkinter import *
import pyttsx3
import threading

root = Tk()

def read():
    engine.say(text.get(1.0 , END))
    engine.runAndWait()

def stop():
    # Code to stop pyttsx3 from speaking
    pass

def pause():
    # Code to pause pyttsx3
    pass

def unpause():
    # Code to unpause pyttsx3
    pass

engine = pyttsx3.init()

text = Text(width = 65 , height = 20 , font = "consolas 14")
text.pack()

text.insert(END , "This is a text widget\n"*10)

read_button = Button(root , text = "Read aloud" , command = lambda: threading.Thread(target=read, daemon=True).start())
read_button.pack(pady = 20)

pause_button = Button(root , text = "Pause" , command = lambda: threading.Thread(target=pause , daemon = True).start())
pause_button.pack()

unpause_button = Button(root , text = "Unpause" , command = unpause)
unpause_button.pack(pady = 20)

stop_button = Button(root , text = "Stop" , command = threading.Thread(target=stop, daemon = True).start())
stop_button.pack()

mainloop()

What I want is to pause, resume, and stop pyttsx3 whenever I want by clicking the buttons.

Is there any way to achieve this in tkinter?

It would be great if anyone could help me out.

Upvotes: 0

Views: 3787

Answers (2)

user18083011
user18083011

Reputation: 41

using pygame and pyttsx3 without tkinter

from pygame import mixer
import pyttsx3
engine = pyttsx3.init()
  
say = 'getting details of current voice'
voices = engine.getProperty('voices')      
# engine.setProperty('volume',1.0)    
engine.setProperty('voice', voices[1].id)  
engine.setProperty('rate', 200)     # setting up new voice rate
outfile = "temp.wav"
engine.save_to_file(say, outfile)
engine.runAndWait()
  
mixer.init()
mixer.music.load("temp.wav")
mixer.music.play()


def stop():
    mixer.music.stop()

def pause():
    mixer.music.pause()

def unpause():
    mixer.music.unpause()

 
while True:
      
    print("Press 'p' to pause, 'r' to resume")
    print("Press 'e' to exit the program")
    query = input("  ")
      
    if query == 'p':
        pause() 
    elif query == 'r':
        unpause() 
  
    elif query == 'e':
        mixer.music.stop()
        break


Upvotes: 0

acw1668
acw1668

Reputation: 46761

There is no pause and resume function provided by pyttsx3, but you can simulate these feature by splitting the sentence into words, and then speak word by word. In between words, you can check whether pause, unpause or stop button is clicked and do corresponding action:

from tkinter import *
import pyttsx3
import threading

root = Tk()

class Speaking(threading.Thread):
    def __init__(self, sentence, **kw):
        super().__init__(**kw)
        self.words = sentence.split()
        self.paused = False

    def run(self):
        self.running = True
        while self.words and self.running:
            if not self.paused:
                word = self.words.pop(0)
                print(word)
                engine.say(word)
                engine.runAndWait()
        print("finished")
        self.running = False

    def stop(self):
        self.running = False

    def pause(self):
        self.paused = True

    def resume(self):
        self.paused = False

speak = None

def read():
    global speak
    if speak is None or not speak.running:
        speak = Speaking(text.get(1.0, END), daemon=True)
        speak.start()

def stop():
    global speak
    if speak:
        speak.stop()
        speak = None

def pause():
    if speak:
        speak.pause()

def unpause():
    if speak:
        speak.resume()

engine = pyttsx3.init()

text = Text(width=65, height=20, font="consolas 14")
text.pack()

text.insert(END, "This is a text widget\n"*10)

read_button = Button(root, text="Read aloud", command=read)
read_button.pack(pady=20)

pause_button = Button(root, text="Pause", command=pause)
pause_button.pack()

unpause_button = Button(root, text="Unpause", command=unpause)
unpause_button.pack(pady=20)

stop_button = Button(root, text="Stop", command=stop)
stop_button.pack()

mainloop()

Update: Using pygame as the player:

from tkinter import *
import pyttsx3
import pygame

pygame.mixer.init()
engine = pyttsx3.init()

root = Tk()

def read():
    outfile = "temp.wav"
    engine.save_to_file(text.get('1.0', END), outfile)
    engine.runAndWait()
    pygame.mixer.music.load(outfile)
    pygame.mixer.music.play()

def stop():
    pygame.mixer.music.stop()

def pause():
    pygame.mixer.music.pause()

def unpause():
    pygame.mixer.music.unpause()


text = Text(width=65, height=20, font="consolas 14")
text.pack()

text.insert(END, "This is a text widget\n"*10)

read_button = Button(root, text="Read aloud", command=read)
read_button.pack(pady=20)

pause_button = Button(root, text="Pause", command=pause)
pause_button.pack()

unpause_button = Button(root, text="Unpause", command=unpause)
unpause_button.pack(pady=20)

stop_button = Button(root, text="Stop", command=stop)
stop_button.pack()

mainloop()

Upvotes: 1

Related Questions