Seite 1 von 1

Konsole unterdrücken

Verfasst: Mittwoch 1. September 2010, 22:18
von raorao
Hoi mitenand!

Bin kurz vor der Fertigstellung einer Lernsoftware und wollte nun noch eine Sprachausgabe der Abfragen einbauen. Über die üblichen Microsoft Stimmen führt dies wie gewünscht zum Erfolg, allerdings sind diese recht unverständlich, deshalb habe ich mir eSpeak installiert, funktioniert deutlich verständlicher. Beim Versuch, eine Ausgabe via

Code: Alles auswählen

os.system("C:\\Programme\\eSpeak\\command_line\\espeak 'hello'")
zu erreichen, entsteht aber die Unschönheit, dass für kurze Zeit (nämlich während der gesamten Sprechzeit) ein schwarzes Konsolenfenster im Vordergrund sichtbar wird. Gibt es eine Möglichkeit, dieses zu unterdrücken oder aber einen ganz anderen Ansatz eSpeak zum sprechen zu zwingen?

Herzlichen Dank für eure Mithilfe!
raorao

Re: Konsole unterdrücken

Verfasst: Mittwoch 1. September 2010, 23:27
von Hyperion
Vergiss, dass es os.system() gibt und nutze das subprocess-Modul. Beispiele gibt es in der Doku (gaaanz unten) und auch zu Hauf hier im Forum ;-)

Vermutlich liegt das Konsolenfenster an diesem "espeak"-Tool. Ich denke nicht, dass man das unterdrücken kann.

Re: Konsole unterdrücken

Verfasst: Mittwoch 1. September 2010, 23:33
von fhoech
Das Konsolenfenster sollte sich mit dem startupinfo-Schlüsselwortargument unterdrücken lassen.

Code: Alles auswählen

import subprocess

startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE

subprocess.call(["C:\\Programme\\eSpeak\\command_line\\espeak", "hello"], startupinfo=startupinfo)

Re: Konsole unterdrücken

Verfasst: Donnerstag 2. September 2010, 00:43
von raorao
Suuuuuuper, herzlichen Dank! Funktioniert super, habe folgendes Modul geschrieben, welches bei Ausführung als __main__ die bessere der beiden installierten Varianten ausgibt. Der Pfad in der Klasse TTS_eSpeak muss natürlich je nach Speicherort und Betriebssystem angepasst werden.

Code: Alles auswählen

import sys, subprocess
sys.path.append(r"C:\Python26\Lib\site-packages\win32\lib")
sys.path.append(r"C:\Python26\Lib\site-packages\win32")
import win32com.client

class TTS_Sapi(object):
    def __init__(self, text):
        self.text = text
        self.sprechen()
        
    def sprechen(self):
        speaker = win32com.client.Dispatch("SAPI.SpVoice")
        speaker.Speak(self.text)

class TTS_eSpeak(object):
    def __init__(self, text):
        self.text = text
        self.sprechen()

    def sprechen(self):
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
        startupinfo.wShowWindow = subprocess.SW_HIDE
        subprocess.call(["C:\\Programme\\eSpeak\\command_line\\espeak",\
                         "%s" % self.text], startupinfo=startupinfo)

if __name__ == "__main__":
    try:
        TTS_eSpeak("Speaking espeak")
    except:
        TTS_Sapi("Speaking Microsoft")

Re: Konsole unterdrücken

Verfasst: Donnerstag 2. September 2010, 08:38
von BlackJack
@raorao: Das ist aber heftiger Missbrauch von Klassen. Das wären doch einfach nur zwei einfache Funktionen, warum machst Du das so unnötig kompliziert!?

Re: Konsole unterdrücken

Verfasst: Donnerstag 2. September 2010, 09:16
von raorao
Na weil da jemand wohl deutlich zu wenig Ahnung von objektorientierter Programmierung hat... :?
Habs nun daher nochmals überarbeitet, danke:

Code: Alles auswählen

import sys, subprocess
sys.path.append(r"C:\Python26\Lib\site-packages\win32\lib")
sys.path.append(r"C:\Python26\Lib\site-packages\win32")
import win32com.client

def sapi(text):
    speaker = win32com.client.Dispatch("SAPI.SpVoice")
    speaker.Speak(text)

def espeak(text):
    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    startupinfo.wShowWindow = subprocess.SW_HIDE
    subprocess.call(["C:\\Programme\\eSpeak\\command_line\\espeak",\
                     "%s" % text], startupinfo=startupinfo)

if __name__ == "__main__":
    try:
        espeak("Speaking espeak")
    except:
        sapi("Speaking Microsoft")

Re: Konsole unterdrücken

Verfasst: Donnerstag 2. September 2010, 09:56
von cofi
Das blanke `except` solltest du mir der tatsaechlichen Exception erweitern, bei der du `sapi` noch nutzen kannst. Momentan wird das auch ausgefuehrt, wenn jemand `Ctrl-C` waehrend `espeak` drueckt oder wenn waehrend dessen bspw ein `MemoryError` passiert. Schlechte Idee.

Re: Konsole unterdrücken

Verfasst: Donnerstag 2. September 2010, 15:33
von micnic
Statt den Pfad zum Programm hart reinzuschreiben, könnte man auch versuchen, ihn aus der Registry auszulesen:

Code: Alles auswählen

import _winreg
...
root = _winreg.HKEY_LOCAL_MACHINE
hKey = _winreg.OpenKey (root, 'SOFTWARE\Microsoft\Speech\Voices\Tokens\eSpeak', 0, _winreg.KEY_READ)
program_path, _ = _winreg.QueryValueEx (hKey, 'Path')
Grüße,
micnic

Re: Konsole unterdrücken

Verfasst: Donnerstag 2. September 2010, 17:20
von Hyperion
fhoech hat geschrieben:Das Konsolenfenster sollte sich mit dem startupinfo-Schlüsselwortargument unterdrücken lassen.
Cool - war mir noch nicht bekannt. Wieder was gelernt :-)

Re: Konsole unterdrücken

Verfasst: Freitag 3. September 2010, 23:16
von raorao
@micnic: Sehr interessante Lösung, funktioniert natürlich hervorragend. Soweit ich der Doku entnehmen konnte, funktioniert _winreg jedoch nur für Windows. Gibts dassselbe vielleicht sogar noch Plattformunabhängig?

@cofi: Danke, hab ich vergessen mittlerweile aber brav durch if os.path.isfile(pfad):... else: ersetzt, so gehts gleich ganz ohne try and error bzw. try and except...

Re: Konsole unterdrücken

Verfasst: Samstag 4. September 2010, 07:19
von BlackJack
@raorao: Ausnahmebehandlung wird einem Test in Python aber oft vorgezogen. Also Ausnahmen "brav" durch Tests ersetzen ist vielleicht gar nicht so brav. :-)

Re: Konsole unterdrücken

Verfasst: Samstag 4. September 2010, 17:29
von Leonidas
raorao hat geschrieben:@micnic: Sehr interessante Lösung, funktioniert natürlich hervorragend. Soweit ich der Doku entnehmen konnte, funktioniert _winreg jedoch nur für Windows. Gibts dassselbe vielleicht sogar noch Plattformunabhängig?
Ähm, die anderen Platformen haben keine solche Registry, also nein, da es sowas eigentlich nur auf Windows gibt. Das was am nächsten da rankommt ist gconf unter GNOME, aber dort stehen keine Pfade zu Binaries drin, weil Binaries sinnigerweise direkt im $PATH auffindbar sind. Somit reicht es auf Unices einfach den Namen des Programms zu kennen um es aufzurufen.

Re: Konsole unterdrücken

Verfasst: Samstag 4. September 2010, 17:33
von DasIch
raorao hat geschrieben:@cofi: Danke, hab ich vergessen mittlerweile aber brav durch if os.path.isfile(pfad):... else: ersetzt, so gehts gleich ganz ohne try and error bzw. try and except...
Nein so geht es nicht ohne try und except. Nach dem os.path.isfile aufruf und bevor du die Datei aufrufst kann sie immer noch verschwinden oder du bekommst einfach keinen Zugriff darauf.