Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
cerrar programa con speech_recognition + pygame
#1
hola, aclaro que soy super novato y lo que hice fue adaptar dos scripts , los cuales por separado funcionan bien.

la idea es lograr que el programa haga un random y cambie el color de fondo y el contenido de un texto por comandos de voz. Aclaro que esa parte estaría funcionando.

El problema se surge cuando quiero cerrarlo con esc o quit utilizando pygame.event, aclaro que si empleo el comando de voz el programa se cierra perfectamente.


me gustaría que me den una mano para lograr que el programa se pueda cerrar utilizando esc y/o quit

script cambia color por orden de voz
Código:
import speech_recognition as sr
import pyttsx3
import pywhatkit
from cambia_color import *
import pygame
import random
import time
import sys
from pygame.locals import *
pygame.init()
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
Ncolores = ['marrón', 'verde', 'azul', 'violeta',
            'amarillo', 'rojo', 'naranja', 'rosado']
            # 01234567
colores = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (159, 0, 255),
           (159, 0, 255), (128, 64, 0), (255, 192, 0), (255, 160, 216)]

engine = pyttsx3.init()
voices = engine.getProperty('voices')
engine.setProperty('rate', 145)
#linux
engine.setProperty('voice', 'spanish-latin-am+f2')
# win10
#engine.setProperty('voice', voices[0].id)
def talk(text):
    engine.say(text)
    engine.runAndWait()

def listen():
    listener = sr.Recognizer()
    with sr.Microphone() as source:
        listener.adjust_for_ambient_noise(source, duration=0.5)
        #print("Escuchando...")
        audio = listener.listen(source)
    try:
        #rec = listener.recognize_google(audio, language='es-AR')
        rec = listener.recognize_google(audio, language='es-AR')
        rec = rec.lower()
        return rec
    except sr.UnknownValueError:
        talk("No entendí")
        #pass
    except sr.RequestError as e:
        #talk("No entendí")
        pass
    except:
        talk("No entendí")
        #pass
def cerrar():
    #event = pygame.event.wait()
    '''es = True
    while es:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                es=False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    es=False
    pygame.quit()
    sys.exit()'''

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()
   
   
def cambiaColor_():
   
   
    screen.fill(colores[random.randint(0, 7)])
    fuente = pygame.font.SysFont('arial', 80)
    texto = fuente.render(Ncolores[random.randint(0, 7)], True, (252, 252, 252))
    text_rect = texto.get_rect(center=(width/2, height/2))
    screen.blit(texto, text_rect)
    pygame.draw.circle(screen,  (0, 0, 0), (width/2, height/1.6), 8)
    pygame.display.update()
    '''for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()'''
def run_escuchar():
    cambiaColor_()
    es=True
    while es:
        rec=listen()
        try:
            if "cambiar" in rec:
                cambiaColor_()
            elif "cerrar" in rec:
                es=False
              
        except:
            pass
        cerrar()
if __name__ == "__main__":
    run_escuchar()

script cambia color por tiempo
Código:
import pygame
import random
import time
import sys
from pygame.locals import *



pygame.init()
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
Ncolores = ['marrón', 'verde', 'azul', 'violeta',
            'amarillo', 'rojo', 'naranja', 'rosado']
            # 01234567
colores = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (159, 0, 255),
           (159, 0, 255), (128, 64, 0), (255, 192, 0), (255, 160, 216)]



def cerrar():
    #event = pygame.event.wait()
    es = True
    while es:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                es=False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    es=False
    pygame.quit()
    sys.exit()
def cambiaColor_():
    while True:
   
        screen.fill(colores[random.randint(0, 7)])
        fuente = pygame.font.SysFont('arial', 80)
        texto = fuente.render(Ncolores[random.randint(0, 7)], True, (252, 252, 252))
        text_rect = texto.get_rect(center=(width/2, height/2))
        screen.blit(texto, text_rect)
        pygame.draw.circle(screen,  (0, 0, 0), (width/2, height/1.6), 8)
        pygame.display.update()


        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
                   
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
        time.sleep(2)
                                     
if __name__ == "__main__":
    cambiaColor_()

les agradecería que me puedan ayudar
saludos...
Responder
#2
Hola, bienvenido.

La lógica para cerrar el programa con Esc está bien. Probablemente el problema sea que esta línea

Código:
audio = listener.listen(source)

bloquea la ejecución del código por un tiempo, pues tiene que esperar a que el usuario diga algo por el micrófono. Mientras esa función está corriendo, PyGame no puede detectar el evento de presión de tecla Esc. La solución sería mover toda la lógica del reconocimiento de voz a un hilo secundario, para no bloquear el procesamiento de eventos de PyGame: https://micro.recursospython.com/recurso...hread.html.

Saludos
Responder
#3
(04-08-2022, 01:08 AM)Francisco escribió: Hola, bienvenido.

La lógica para cerrar el programa con Esc está bien. Probablemente el problema sea que esta línea

Código:
audio = listener.listen(source)

bloquea la ejecución del código por un tiempo, pues tiene que esperar a que el usuario diga algo por el micrófono. Mientras esa función está corriendo, PyGame no puede detectar el evento de presión de tecla Esc. La solución sería mover toda la lógica del reconocimiento de voz a un hilo secundario, para no bloquear el procesamiento de eventos de PyGame: https://micro.recursospython.com/recurso...hread.html.

Saludos

gracias por la respuesta, si creo por ahí van los tiros,voy a investigar el tema de los hilos y después comento
saludos...
Responder
#4
hola Francisco
usando threading logré que cierre tamto pygame como la parte de speech_recognition pero hay que ejecutar el comando de voz, por lo menos 1 ves .
he probado varias combinaciones sin poder lograr que cierre luego de iniciar el programa

sobre el tema de aislar dentro de un hilo a:
Código:
audio = listener.listen(source)
probé varias combinaciones pero todas fracasaron

acá dejo el código:
Código:
import speech_recognition as sr
import pyttsx3
import pywhatkit
import pygame
import random
import time
import sys
from pygame.locals import *
import threading
pygame.init()
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
Ncolores = ['marrón', 'verde', 'azul', 'violeta',
            'amarillo', 'rojo', 'naranja', 'rosado']
            # 01234567
colores = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (159, 0, 255),
           (159, 0, 255), (128, 64, 0), (255, 192, 0), (255, 160, 216)]
engine = pyttsx3.init()
voices = engine.getProperty('voices')
engine.setProperty('rate', 145)
#linux
engine.setProperty('voice', 'spanish-latin-am+f2')
# win10
#engine.setProperty('voice', voices[0].id)
def talk(text):
    engine.say(text)
    engine.runAndWait()
def listen():
    listener = sr.Recognizer()
    with sr.Microphone() as source:
        listener.adjust_for_ambient_noise(source, duration=0.5)
        #print("Escuchando...")
        audio = listener.listen(source)
    try:
        rec = listener.recognize_google(audio, language='es-AR')
        rec = rec.lower()
        return rec
    except sr.UnknownValueError:
        talk("No entendí")
        #pass
    except sr.RequestError as e:
        #talk("No entendí")
        pass
    except:
        talk("No entendí")
        #pass
def cambiaColor_():
    #while True:
        screen.fill(colores[random.randint(0, 7)])
        fuente = pygame.font.SysFont('arial', 80)
        texto = fuente.render(Ncolores[random.randint(0, 7)], True, (252, 252, 252))
        text_rect = texto.get_rect(center=(width/2, height/2))
        screen.blit(texto, text_rect)
        pygame.draw.circle(screen,  (0, 0, 0), (width/2, height/1.6), 8)
        pygame.display.update()
        '''for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()'''
t2 = threading.Thread(target=listen)
t2.start()
def cerrar():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                t2.join()
                pygame.quit()
                sys.exit()             
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    t2.join()
                    pygame.quit()
                    sys.exit()               
def run_escuchar():
    cambiaColor_()
    es=True
    while es:
        rec=listen()
        try:
            if "cambiar" in rec:
                cambiaColor_()
            elif "cerrar" in rec:
                es=False
        except:
            pass
if __name__ == "__main__":
    #run_escuchar()
    t1 = threading.Thread(target=cerrar)
    t0 = threading.Thread(target=run_escuchar, daemon=True)
    t1.start()
    t0.start()   
   
¿existirá la posibilidad de que pueda cerrar el programa sin tener que ejecutar antes el comando de voz?
Responder
#5
Hola. No probé el código, pero creo que sería suficiente con lanzar solo un hilo para escuchar el micrófono y que el bucle de PyGame corra normalmente en el hilo principal. Pero ojo con esta línea:

Código:
t2.join()

Acá estás esperando a que termine el hilo del micrófono, por lo cual quedás en la misma situación que antes: si el hilo está bloqueado por la función listener.listen(), el programa no se va a cerrar. Llamar a join() tendría sentido si antes de eso le mandaras una señal al hilo para que se cierre lo más pronto posible. Pero no veo que sea necesario eso, simplemente terminá el programa con sys.exit().

Saludos
Responder
#6
hola , ahora el programa ya cierra desde el inicio sin tener que ejecutar primero la orden de cambiar

ya saque

Código:
t2.join()
pero no pude dejar un solo hilo debido a que, si bien cierra la ventana, seguía activada la función de reconocimiento de voz.
intuyo que sucede porque, si bien pongo la función listen() dentro de un hilo, esta corre multiplicada y al mismo tiempo ya que es llamada por rec=listen() dentro de run_escuchar()  y  cuando cierro, si bien cierra el hilo, queda funcionando el otro listen()

lo otro que noto es que , corriendo el programa, el uso del cpu de la notebock se dispara y creo que eso se debe a, por un lado los 2 listen() que estarían corriendo al mismo tiempo y 2 bucles while (de run_escuchar() y de cerrar())
acá dejo el código con las 'mejoras'
Código:
import speech_recognition as sr
import pyttsx3
import pywhatkit
import pygame
import random
import sys
import threading

pygame.init()
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
Ncolores = ['marrón', 'verde', 'azul', 'violeta',
            'amarillo', 'rojo', 'naranja', 'rosado']
            # 01234567
colores = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (159, 0, 255),
           (159, 0, 255), (128, 64, 0), (255, 192, 0), (255, 160, 216)]
engine = pyttsx3.init()
voices = engine.getProperty('voices')
engine.setProperty('rate', 145)
#linux
engine.setProperty('voice', 'spanish-latin-am+f2')
# win10
#engine.setProperty('voice', voices[0].id)

def talk(text):
    engine.say(text)
    engine.runAndWait()

def listen():
    listener = sr.Recognizer()
    with sr.Microphone() as source:
        listener.adjust_for_ambient_noise(source, duration=0.5)
        #print("Escuchando...")
        audio = listener.listen(source)
    try:
        rec = listener.recognize_google(audio, language='es-AR')
        rec = rec.lower()
        return rec
    except sr.UnknownValueError:
        talk("No entendí")
        #pass
    except sr.RequestError as e:
        #talk("No entendí")
        pass
    except:
        talk("No entendí")
        #pass
t2 = threading.Thread(target=listen, daemon=True)
def cambiaColor_():
    #while True:
        screen.fill(colores[random.randint(0, 7)])
        fuente = pygame.font.SysFont('arial', 80)
        texto = fuente.render(Ncolores[random.randint(0, 7)], True, (252, 252, 252))
        text_rect = texto.get_rect(center=(width/2, height/2))
        screen.blit(texto, text_rect)
        pygame.draw.circle(screen,  (0, 0, 0), (width/2, height/1.6), 8)
        pygame.display.update()
        '''for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()'''


def cerrar():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()       
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()



t2.start()
             
def run_escuchar():
    cambiaColor_()
    es=True
    while es:
        rec=listen()
        #print(rec)
        try:
            if "cambiar" in rec:
                cambiaColor_()
            elif "cerrar" in rec:
                es=False
        except:
            pass
if __name__ == "__main__":
    #run_escuchar()
    t0 = threading.Thread(target=run_escuchar, daemon=True)
    t0.start()
    cerrar()
   

       


   
saludos...
Responder
#7
bueno ,acá dejo el código que ahora cierra al hacer clic en quit o apretar la tecla esc, y en un solo hilo, y con una función para que cuando se nombra el texto se produzca el random y que no sean iguales el nombre del texto y el color del fondo (+o- funciona)

así que estaría dando por solucionado el tema, aunque no he podido evitar que se dispare el uso del cpu.

Código:
import speech_recognition as sr
import pyttsx3
import pywhatkit
import pygame
#from pygame.locals import *
import random
import sys
import threading
n_r=''
con_F=0
con_F_new=1
con_T=2
con_T_new=3
pygame.init()
width, height = 800, 600
screen = pygame.display.set_mode((width, height))

Ncolores = ['marrón', 'verde', 'azul', 'violeta',
            'amarillo', 'rojo', 'naranja', 'rosado']
            # 01234567
colores = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (159, 0, 255),
           (255, 255, 0), (128, 64, 0), (255, 192, 0), (255, 160, 216)]

engine = pyttsx3.init()
voices = engine.getProperty('voices')
engine.setProperty('rate', 145)
#linux
engine.setProperty('voice', 'spanish-latin-am+f2')
# win10
#engine.setProperty('voice', voices[0].id)

def talk(text):
    engine.say(text)
    engine.runAndWait()

def listen():
    listener = sr.Recognizer()
    with sr.Microphone() as source:
        listener.adjust_for_ambient_noise(source, duration=0.5)
        #print("Escuchando...")
        audio = listener.listen(source)
    try:
        rec = listener.recognize_google(audio, language='es-AR')
        rec = rec.lower()
        return rec
    except sr.UnknownValueError:
        talk("No entendí")
        #pass
    except sr.RequestError as e:
        #talk("No entendí")
        pass
    except:
        talk("No entendí")
        #pass
def no_repite():
    global con_F
    global con_F_new
    global con_T
    global con_T_new
    #print(con_F_new, '-',con_T_new)
    while True:
        random.seed(a=None, version=2)
        random_a = random.randint(0,7)
        random_b = random.randint(0,7)
        if Ncolores.index('marrón')==random_a and colores.index((255, 0, 0))!=random_b and n_r!='marrón':
            con_F=random_b
            con_T=random_a
            break
        elif Ncolores.index('verde')==random_a and colores.index((0, 255, 0))!=random_b and n_r!='verde':   
            con_F=random_b
            con_T=random_a
            break
        elif Ncolores.index('azul')==random_a and colores.index((0, 0, 255))!=random_b and n_r!='azul':
            con_F=random_b
            con_T=random_a
            break
        elif Ncolores.index('violeta')==random_a and colores.index((159, 0, 255))!=random_b and n_r!='violeta': 
            con_F=random_b
            con_T=random_a
            break
        elif Ncolores.index('amarillo')==random_a and colores.index((159, 0, 255))!=random_b and n_r!='amarillo':
            con_F=random_b
            con_T=random_a
            break 
        elif Ncolores.index('rojo')==random_a and colores.index((128, 64, 0))!=random_b and n_r!='rojo':     
            con_F=random_b
            con_T=random_a
            break
        elif Ncolores.index('naranja')==random_a and colores.index((255, 192, 0))!=random_b and  n_r!='naranja': 
            con_F=random_b
            con_T=random_a
            break
        elif Ncolores.index('rosado')==random_a and colores.index((255, 160, 216))!=random_b and n_r!='rosado':
            con_F=random_b
            con_T=random_a
            break
        elif con_F_new==con_F or con_T_new==con_T:
            continue
    con_F_new=con_F
    con_T_new=con_T
    return random_a, random_b

def cambiaColor_():
    a, b =no_repite()
    screen.fill(colores[b])
    fuente = pygame.font.SysFont('arial', 80)
    texto = fuente.render(Ncolores[a], True, (252, 252, 252))
    text_rect = texto.get_rect(center=(width/2, height/2))
    screen.blit(texto, text_rect)
    pygame.draw.circle(screen,  (0, 0, 0), (width/2, height/1.6), 8)
    pygame.display.update()
    return a,b

def cerrar():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                #pygame.quit()
                sys.exit()       
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    #pygame.quit()
                    sys.exit()

def run_escuchar():
    a,b = cambiaColor_()
    es=True
    while es:

        try:
            rec=listen()
            print(rec)
            if ('marrón' in rec or 'marron' in rec) and (Ncolores.index('marrón')==a):
                #talk("dijiste " + rec)
                a,b = cambiaColor_()
            elif 'verde' in rec and (Ncolores.index('verde')==a):
                #talk("dijiste " + rec)
                a,b = cambiaColor_()
            elif 'azul' in rec and (Ncolores.index('azul')==a):
                #talk("dijiste " + rec)
                a,b = cambiaColor_()
            elif ('violeta' in rec or 'violetta' in rec) and (Ncolores.index('violeta')==a):
                #talk("dijiste " + rec)
                a,b = cambiaColor_()
            elif 'amarillo' in rec and (Ncolores.index('amarillo')==a):
                #talk("dijiste " + rec)
                a,b = cambiaColor_()
            elif 'rojo' in rec and (Ncolores.index('rojo')==a):
                #talk("dijiste " + rec)
                a,b = cambiaColor_()
            elif 'naranja' in rec and (Ncolores.index('naranja')==a):
                #talk("dijiste " + rec)
                a,b = cambiaColor_()
            elif 'rosado' in rec and (Ncolores.index('rosado')==a):
                #talk("dijiste " + rec)
                a,b = cambiaColor_()

            '''elif "cerrar" in rec or "apagar" in rec:
                es=False'''
               
        except:
            pass
    #pygame.quit()
    #sys.exit()   
     
if __name__ == "__main__":
    #run_escuchar()
    t0 = threading.Thread(target=run_escuchar, daemon=True)
    t0.start()
    cerrar()
DP: disculpen por subir el tema
Responder
#8
¡Excelente! Gracias por compartir la solución. Smile
Responder


Salto de foro:


Usuarios navegando en este tema: 1 invitado(s)