Komfortable TTS Ausgabe Funktion

Was macht die Funktion?

[ul]
[li]abspielen von Sprachausgabe auf beliebig vielen Soundkarten[/li][li]umgehen des TTS_Speak Problems unter Windows Vista/2003 oder neuer.[/li][li]nur ein einfacher Befehl tts_play($sk,$ansagetext,$ton,$modus) notwendig[/li][li]Faderfunktion[/li][li]möglichkeit einen Klang/Ton vor der Sprachausgabe abzuspielen[/li][li]mehrere Sprachausgaben hintereinander puffern (entsprechende max. Ausführungszeit des PHP Scripts beachten!)[/li][/ul]

Was muß ich machen?

[ul]
[li]Funktion im Script zur Verfügung stellen (am besten per include)[/li][/ul]
Wenn nicht schon vorhanden (alle 3 Instanzen die gleiche Soundkarte!):

[ul]
[li]eine Mediaplayerinstanz für Musik anlegen[/li][li]eine Mediaplayerinstanz für Sprache/Ton anlegen[/li][li]eine TTS Instanz anlegen[/li][li]Integervariable $id_sk1_counter anlegen (für zweite Soundkarte $id_sk2_counter usw.)[/li][li]Pfadangaben evtl. anpassen bzw. im Media Pfad von IPS einen Unterpfad „wav“ anlegen![/li][/ul]
Pfadangaben sind hier zu finden:
TTS_GenerateFile($id_sk1_tts, $ansagetext, IPS_GetKernelDir().„media/wav/sprache_sk1_“ . $sk1_counter . „.wav“,39);
WAC_AddFile($id_sk1_ton, IPS_GetKernelDir().„media/wav/sprache_sk1_“ . $sk1_counter . „.wav“);

Syntax:

tts_play($sk,$ansagetext,$ton,$modus) Beispiel: tts_play(1,‚Das ist eine Sprachausgabe!‘,‚bell‘,2);

$sk = Integer: Nummer der Soundkarte (1 = erste Soundkarte, 2 = zweite
Soundkarte usw.)
$ansagetext = String: Ansagetext
$ton
= [i]String: abzuspielender Ton aus dem array
$modus = Integer: Modus

Modus /i

[ul]
[li]mit Sprache[/li][li]ohne vorherigen Ton abzuspielen[/li][li]Musik spielt weiter[/li][li]kein Fader der Musik[/li][li]Scriptausführung wird während der Sprachausgabe nicht unterbrochen[/li][/ul]
[i] Modus /i

[ul]
[li]mit Sprache[/li][li]möglichkeit vorherigen Ton abzuspielen[/li][li]Musik macht pause[/li][li]kein Fader der Musik[/li][li]Scriptausführung wird während der Sprachausgabe unterbrochen[/li][/ul]
[i]Modus /i

[ul]
[li]mit Sprache[/li][li]möglichkeit vorherigen Ton abzuspielen[/li][li]Musik spielt weiter (Volumen auf 0)[/li][li]Fader der Musik[/li][li]Scriptausführung wird während der Sprachausgabe unterbrochen[/li][/ul]

Achtung: Die im array enthaltenen wav Dateien sind Beispiele und das array ist nach eigenen Wünschen anzupassen! (Dateien befinden sich im Anhang)

Erläuterung zu den ID´s:
ID der Mediaplayerinstanz für die Musik der Soundkarte 1
$id_sk1_musik
ID des Status der 1. Mediaplayerinstanz für die Musik der Soundkarte 1
$id_sk1_musik_status
ID des Volumens der Mediaplayerinstanz für die Musik der Soundkarte 1
$id_sk1_musik_vol
ID des Status der Mediaplayerinstanz für die Sprache/Ton der Soundkarte 1
$id_sk1_ton_status
ID der Mediaplayerinstanz für Sprache/Ton der Soundkarte 1
$id_sk1_ton
ID der TTS Instanz für Sprachausgabe der Soundkarte 1
$id_sk1_tts
ID des fortlaufenden Counters für die Sprachausgabedatei
$id_sk1_counter

V1.1 (24.12.2011)

  • [li]Funktionsanpassungen[/li][li]Pufferfunktion[/li]

wav.rar (2.76 MB)

function tts_play.ips.rar (1.6 KB)

und die passenden sounds bekommt man hier

[freesound :: view tags](http://www.freesound.org/tagsView.php)

Gruß Michael

Update:
Neu: Fehlerhandling für Datei eingeführt
(Script im ersten Beitrag geändert)

Hmmm, warum holst du dir die Media Player ids nicht über die IPS_GetObjectByName funktion, muesste man zwar eine variable bei der übergabe mehr machen, aber dafür koennte man sich die zusätzlichen case sparen…
Habs allerdings gerade nur mal so überflogen, da ich kein Vista hab und TTS in meinem Weckerscript funktioniert, ist es für mich ehh nicht so relevant, bloss ne idee… Wäre einfacher für die anderen. Ansonsten ne nette sache, wenn man vista hat …

Hallo korny,

ich habe die Funktion bewußt so gewählt, dass jede Soundkarte Ihren eigenen case Bereich erhält. Das hat zum einen den Hintergrund mehrere wav files zu haben, da die wav Datei einige Zeit gesperrt bleibt und andererseits mehrer id´s bekannt sein müssen, je Soundkarte 2 x mp und 1x tts etc.
Die Funktion ist aber bei weitem nicht nur für Leute mit Vista von Interesse, sondern um nicht in jedem Script „endlosen“ Code benutzen zu müssen um z.B. Musik durch einen Slider sanft zu unterbrechen eine Sprache auzugeben und dann die Musik fortzusetzen. Ich habe eine Menge Einsatzgebiete dieser Funktion und wollte den IPS Usern mit Media Interesse ein Arbeitsmittel zur Seite stellen.:wink:

hallo Thomas,
bei dir würde ich mir gerne mal dein Haus anschauen.
Es hört sich so an als hättest Du 50 Zimmer ausgestattet:D

Gruß Uwe

…21:cool:

Bist immer auf ein Bier willkommen.

Hi Ferengi Master,

muss es in deinem Skript nicht 2 mal heissen :

if($merken>0) $warten = $fader/$merken; else $warten = 0;

und nicht:

if($merken>0) $warten = $slider/$merken; else $warten = 0;

und warum:

case $sk1:

wenn du $sk1 vorher fest definierst?

Und weil Du die anderen Variablen auch vorher fest definierst, macht doch die an die Funktion übergebene Var $SK keinen Sinn.

Ist mir nur mal so am WE aufgefallen als ich was mit dem Script machen wollte. Vielleicht peil ich es ja auch einfach nicht aber ich wollte dich nur mal kurz drauf aufmerksam machen.

Gruß
Smudo

Ich kann mich Smudo nur anschließen, mir war das Skript auf den ersten Blick „auch nicht geheuer“ bzw. für mich unverständlich. Erstens, wo definiere ich denn im IPS überhaupt eine Soundkarte mit einer Instanznummer? Ich kann doch nur einen Mediaplayer oder eine TTS Instanz anlegen und weiße ihr eine meiner Soundkarten im System zu. Dann schreibst du, man muss nur die $sk angeben, aber was ist mit all den anderen Instanz-ID’s?

    $id1_musik_status = 12345;
    $id1_ton_status = 10815;
    $id1_musik_vol = 56335;
    $sk1 = 56641;
    $sk1_wav = 51118;
    $tts_sk1 = 24371;

Ich peil das auch irgendwie nicht und wäre über jeden Hinweis glücklich, um das Skript auch einmal bei mir ausprobieren zu können.

Hallo Smudo, Hallo obicom,

das Problem bei der Sache ist, das ich meine Scripte ab und zu im Forum mal neuen Bedingungen anpasse oder Bugs beseitige. Und da passiert es häufiger, dass sich privater Kram mit einschleicht…:o

Ich werde Eure Hinweiße heute abend in der Homezone gleich prüfen und entsprechend antworten.:wink:

muss es in deinem Skript nicht 2 mal heissen…

Ja, da war ein Fehler habe diesen behoben. Danke.

und warum:
case $sk1:
wenn du $sk1 vorher fest definierst?
Und weil Du die anderen Variablen auch vorher fest definierst, macht doch die an die Funktion übergebene Var $SK keinen Sinn.

Das ist richtig so. Mit der Funktion übergibst Du die ID der Mediaplayerinstanz $sk. Sagen wir mal 12345. Der switch Befehl verzweigt dann zu $sk1 (hier auch 12345) oder $sk2 (z.B. 67890) usw. Der Wert muß ja innerhalb der Funktion definiert sein, sonst kann der switch Befehl diesen nicht vergleichen.
Also $sk (12345) == $sk1 (12345).

wo definiere ich denn im IPS überhaupt eine Soundkarte mit einer Instanznummer?

= id der Mediaplayerinstanz für die Musik (war ein wenig umständlich ausgedrückt, habe das geändert)

Ich kann doch nur einen Mediaplayer oder eine TTS Instanz anlegen und weiße ihr eine meiner Soundkarten im System zu. Dann schreibst du, man muss nur die $sk angeben, aber was ist mit all den anderen Instanz-ID’s?
$id1_musik_status = 12345;
$id1_ton_status = 10815;
$id1_musik_vol = 56335;
$sk1 = 56641;
$sk1_wav = 51118;
$tts_sk1 = 24371;

Nein, Du kannst mehreren Mediaplayer/TTS Instanzen die gleiche Soundkarte zuweisen.
Das heißt:

$id1_musik_status = id des Status der 1. Mediaplayerinstanz für Musik Soundkarte 1
$id1_ton_status = id des Status der 2. Mediaplayerinstanz für Sprache/Ton Soundkarte 1
$id1_musik_vol = id des Volumen der 1. Mediaplayerinstanz für Musik Soundkarte 1
$sk1 = id der 1. Mediaplayerinstanz für Musik Soundkarte 1
$sk1_wav = id der 2. Mediaplayerinstanz für Sprache/Ton Soundkarte 1
$tts_sk1 = id der TTS Instanz für Musik Soundkarte 1

Hoffe soweit geholfen zu haben.

Hi, Ferengi Master,

ich hoffe, du hast nichts dageben ,dass ich eine stark vereinfachte Version deines Scriptes hier poste. Ich denke, dafür muss ich nicht noch einen Thread aufmachen mit einem weitern Soundscript. Es hat keine verschiedenen Modi mehr und kann auch nicht die Lautstärke einer anderen Soundkarte herunterfaden. Da ich über IPS keinerlei Musikfunktionen nutze, war das für mich überflüssig. Es kann lediglich einen vordefinierten Klang und/oder eine Ansage abspielen. Das ganze ist auch nicht als Funktion gedacht, sondern als eigenständiges Script zur TTS Ausgabe, welches mit ips_runscriptex und entsprechender Parameter gestartet wird.
Das kann dann als Beispiel in den Scripten so aussehen.

$text= "Solltemperatur im gästezimmer auf 20° geändert";
$ton="gong";
$vol="80";
ips_runscriptex (50039,array("ansagetext" => $text, "ton" => $ton, "vol" => $vol));

oder einfach nur

ips_runscriptex (50039,array("ansagetext" => "lichtautomatik aktiviert));

Hier das Script:

<?
$standardlaustaerke=90; //Lautstaerke, die verwendet wird, wenn keine andere angegeben ist
$mptts_status = 47697;  // ID der Statusanzeige des Mediaplayers für TTS
$mptts = 29669;  // ID des Mediaplayerr für TTS
$tts = 23485; // ID der TTS instanz

$wav = array
	(
	"hinweis"  => IPS_GetKernelDir()."media/hinweis.wav",
	"meldung"  => IPS_GetKernelDir()."media/meldung.wav",
	"abmelden" => IPS_GetKernelDir()."media/abmelden.wav",
	"aus"      => IPS_GetKernelDir()."media/aus.wav",
	"coin"     => IPS_GetKernelDir()."media/coin-fall.wav",
	"thunder"  => IPS_GetKernelDir()."media/thunder.wav",
	"clock"    => IPS_GetKernelDir()."media/clock.wav",
	"shutdown" => IPS_GetKernelDir()."media/shutdown.wav"
	);
$volint = (int)$vol;
WAC_SetVolume (29669 /*[Media Player TTS]*/ , $standardlaustaerke);
if($vol != ""){WAC_SetVolume (29669 /*[Media Player TTS]*/ , $volint);}
if(($ton != "")or($ansagetext !="")){
	WAC_SetRepeat($mptts, false);
	WAC_Stop($mptts);
	WAC_ClearPlaylist($mptts);
	if ($ton != ""){
		WAC_AddFile($mptts,$wav[$ton]);
	}
	if($ansagetext !=""){
		$filename = IPS_GetKernelDir()."media/Sprache1.wav";
		if(is_writable($filename)){
			TTS_GenerateFile($tts, $ansagetext,IPS_GetKernelDir()."media/Sprache1.wav",39);
			IPS_Sleep(50);
			WAC_AddFile($mptts,IPS_GetKernelDir()."media/Sprache1.wav");
		}
		else{
			break;
		}
	}
	IPS_Sleep(50);
	WAC_Play($mptts);
}
?>

Bisher hatte ich die Soundausgabe auch auf mehrere Scripte verteilt, was immer mal wieder das Problem zutage brachte, das die Datei in der die Sprachausgabe gespeicht wird (sprache1.wav) irgendwann nicht mehr freigegeben wurde und darum bei jeder Sprachausgabe der gleiche Text kam.
Das Problem tritt jetzt glaub ich nicht mehr auf, da nur noch dieses eine Script auf die Datei zugreift und da nichts mehr durcheinander laufen kann. Ausserdem kann man so viel einfacher und schneller TTS in die unterschiedlichsten Scripte einbauen.

mfg
Smudo

Hallo smudo,

kein Problem dafür sind die Scripte ja gedacht, sie sollen nicht nur als Endlösung dienen, sondern Anregung für eigene Kreationen sein. Ich habe meine Funktion auch schon weiterentwickelt, weil ich auch ständig das Problem mit dem Zugriff auf die .wav Dateien hatte. Dafür verwende ich jetzt rotierende Dateinamen. Allerdings hat der Mediaplayer meines Erachtens noch zwei nicht so schöne Eigenschaften/Bugs. Einmal hängt sich ab und zu eine Mediaplayerinstanz bei mir auf und gibt kein Ton mehr von sich und desweiteren gibt es Situationen bei denen sich zwei Ausgaben auf einer Instanz verselbständigen und parallel, leicht Zeitversetzt zueinender laufen. Ich finde aber einfach den Fehler nicht. paresy hat da auch schon gesucht. Vieleicht hat da noch jemand eine Idee oder die gleichen Probleme… Aber das wird jetzt zu Off Topic.

Hi Thomas,

versuch doch auch mal das Script nicht als Funktion einzubauen, sondern es mit IPS_RunscripEx und den entsprechenden VARs anzusteuern.
Das hat bei mir auf jeden Fall den durchschlagenden Erfolg gebracht. Keinerlei Probleme mehr mit der Sprachausgabe. Ausserdem vereinfacht es die Einbindung von TTS in die unterschiedlichsten Scripte extrem (1-2 Zeilen).

mfg
Smudo

Kürzer als ein TTS_Play(52345,„Das ist ein Test“,„meldung“,2); gehts ja nun wirklich nicht mehr.:wink:
Und alle meine Funktionen sind mittels include in allen meinen Scripten verfügbar.
Ich denke das Problem ist leider wo anders zu suchen.

Ach so, ich wusste nicht, dass include auch geht. Dann ist es ja das prinzipiell gleiche. Ich dachte du hättest die komplette Funktion in jedem Script drin.

mfg
Smudo

Hallo Thomas,

danke für dein tolles TTS-Script.
Funktioniert super bei uns und mit den Faden bei Musikwiedergabe ist das der Hammer :smiley:

Leider habe ich aber ein kleines Problem.
Ich habe häufig, das TTS Meldungen kurz nacheinander ausgegeben werden. Ist die Wartezeit dazwischen zu kurz, wird die nächste Nachricht verschluckt.

Hast du eine Idee, wie man das unterbinden kann?
Ich hatte mal überlegt die Nachrichten in ein Array zu packen und dann nacheinander abzuarbeiten aber irgenwie fehlt mir hierzu noch die passende Idee, wie man das umsetzen könnte.
Hast du dir dazu auch schon einmal Gedanken gemacht oder hat das Problem schon mal jemand anders gelöst?
Wenn ja wie?

Viele Grüße,
Doc

Hallo Doc,

schön das Dir die Funktion gefällt, das Problem ist bekannt und tritt bei mir ebenfalls sporadisch auf. Leider habe ich zur Zeit so viele Baustellen das ich mich 24h am Tag mit IPS beschäftigen könnte. Da währe die neue WMRS200 Wetterstation die eingebunden werden möchte, die Terminverwaltung die einige Anpassungen für die V2.1 braucht und da sind auch noch einige Ideen die in der Schublade liegen. Aber zurück zum Problem, ich würde das über eine Art Puffer machen. Quasi eine Möglichkeit, wenn noch eine Sprachausgabe oder ein Ton ausgegeben wird merkt dieses die Funktion und speichert die Funktionsparameter im Puffer zwischen und gibt diese dann der Reihe nach aus. Mal sehen wann ich Zeit dafür habe.

Hallo Thomas,

jaja das mit der wenigen Zeit kenne ich.

Wäre schön, wenn du da mal Zeit etwas dafür finden würdest. Du verstehst besser, was dein Script da genau macht.
Ne mal im Ernst, ist wirklich nichts eiliges, ich ärgere mich immer nur wenn ich weiss, das das was kommen müsste, es aber nicht tut.

Wenn ich mal Zeit dafür finde, werde ich aber mit meinen beschränkten PHP Kenntnissen schon mal etwas versuchen.

Grüße,
Doc

Hallo,

habe die Funktion entsprechend angepasst und mit
include „43977.ips.php“;
eingebunden.

Mit dem Befehl:
TTS_Play(21616,„Das ist ein Test“,„Gitarre04“,3);
kommt zwar jetzt die Musik, aber keine Sprachausgabe:confused:.

Die ID der TTS Stimme ist bei $tts_sk1 =xxx eingetragen.

Was könnte denn da nicht passen?

Danke und Gruß, Andreas