PBToolboxAI v3 ← Site

speechout — n_pbt_speechout #

← Komponentenreferenz · Inhalt des Handbuchs

Vorlesen: Die Anwendung liest einen Text Satz für Satz und sagt Ihnen, wo sie steht. Kein Drittanbieterdienst, kein API-Schlüssel — die Sprachsynthese ist die des Arbeitsplatzes.

▶ Live ansehen — Demoanwendung, Kachel Speech out: die Vorschau, der zugehörige Code und diese Seite nebeneinander.


Kurzüberblick #

Nichtvisuelles Objektn_pbt_speechout
WofürEinen Text hörbar machen: Barrierefreiheit, belegte Hände, eine Meldung, die niemand ansieht
PrinzipSie übergeben den Text; die Komponente zerlegt ihn in Sätze und sagt Ihnen, welchen sie liest
AbhängigkeitDie Sprachsynthese des Arbeitsplatzes — kein Drittanbieterdienst, kein API-Schlüssel

Schnellstart #

// once, when the window opens
inv_voice.of_open()

// then, wherever you need it
inv_voice.is_lang = inv_voice.LANG_FR_FR
inv_voice.of_speak("Bonjour. Votre commande est expediee.")

Nichtvisuell: die Verdrahtung der Ereignisse #

Eine Stimme hat nichts zu zeigen. Die Komponente zeichnet daher nichts: keine Abspielleiste, für die Platz zu finden wäre, kein Raum, der dem weggenommen wird, dem sie dient.

Und Sie müssen dafür nichts verdrahten: Ein nichtvisuelles Objekt hat kein Fenster, also keine Glocke, aber die Komponente holt ihre Ereignisse selbst auf der PowerBuilder-Schleife, solange die Stimme offen ist, und löst sie am Objekt aus. Sie schreiben nur die ue_*-Handler (kein Empfänger, kein Timer).

// Just speak -- the ue_* events arrive on their own :
inv_voice.of_speak("Good morning. Your order has shipped.")
// the ue_sentence / ue_word / ue_stopped events arrive on their own

Dem Vorlesen in IHREM Text folgen #

ue_sentence trägt den Index und den Text des gerade gelesenen Satzes. Daher stammt die Hervorhebung — in Ihrem mle_, Ihrer datawindow oder Ihrem statictext: Sie wissen, wo Ihr Text steht, wir nie.

Auch der Rückweg existiert: of_speak_from() setzt bei einem bestimmten Satz an, was man auf den Klick auf einen Absatz legt. Die Nummern stammen aus ue_sentence und bezeichnen daher stets das tatsächlich Gelesene.

Die Zerlegung ist die der Komponente, nicht Ihre: of_sentence_count() liefert ihre eigene Zählung. Zählen Sie nicht selbst nach, beides würde auseinanderlaufen.


Was der Arbeitsplatz wirklich sprechen kann #

of_languages() liefert die Sprachen, die dieser Arbeitsplatz tatsächlich aussprechen kann, ohne Dubletten. Das ist die Frage eines Benutzers: nicht „welche Stimmen gibt es“, sondern „ist meine Sprache dabei“.

of_voices() geht eine Stufe tiefer und benennt die Stimmen selbst. Beide Listen stammen von der Maschine, nicht von uns: kodieren Sie nie einen Namen fest.

Die Spracherkennung hat kein Gegenstück, und das ist kein Versehen: Die Erkennung führt keine Liste der von ihr akzeptierten Sprachen.

Ganz ohne eigene Komponente liefert gnv_utils.of_speech_languages(as_tags[]) dieselbe Liste — die DLL befragt eine verborgene Stimme und verwirft sie wieder: das fragt ein Dialog, bevor die Stimme existiert, welche Sprache anbieten, in welcher lesen. Der Aufruf ist synchron und kann beim ersten Mal bis zu zwei Sekunden dauern: die Stimmenliste kommt spät, und der Aufruf wartet darauf. Und gnv_utils.of_speech_voices(as_names[], as_langs[]) liefert die Stimmen selbst mit ihrer Sprache, um „Hortense“ oder „Julie“ statt einer Marke anzubieten; gnv_utils.of_locale_name(as_tag) gibt einer Sprachmarke ihren lesbaren Namen — „Französisch (Frankreich)“ für fr-FR.

string ls_tags[]

if inv_voice.of_languages(ls_tags) > 0 then inv_voice.is_lang = ls_tags[1]

Eigenschaften #

EigenschaftTypStandardRolle
is_langstringen-USVorgelesene Sprache in BCP-47 (LANG_*-Konstanten). Entscheidet, welche Stimme gewählt wird — solange is_voice leer ist, denn ein Stimmname legt seine eigene Sprache fest. Ohne Stimme für diese Sprache liest der Rechner mit der vorhandenen, und ue_voice_fallback nennt beide
is_textstring""Der zu lesende Text. Die Komponente zerlegt ihn in Sätze; drei Tags sagen, WIE ein Stück gelesen wird: [pause=500], [spell]…[/spell], [say-as=digits]…[/say-as] (siehe unten)
is_voicestring""Stimmname aus of_voices(). Leer = die erste, die is_lang spricht
ii_rateinteger100Tempo in PROZENT des normalen Tempos (10 bis 400). Mitten im Lesen geändert, gilt es ab dem nächsten Satz
ii_pitchinteger100Tonhöhe der Stimme in PROZENT der normalen Höhe (0 bis 200)
ii_volumeinteger100Lautstärke in Prozent (0 stumm bis 100), die Skala des Videoplayers
il_timeout_mslong300000Längste Dauer einer SYNCHRONEN Wiedergabe: fünf Minuten. Danach gibt of_speak_sync -4 zurück und die Wiedergabe wird abgebrochen (is_last_error sagt warum)
is_last_errorstring""Warum das letzte of_speak_sync -4 lieferte: Stimme nicht erzeugt, Engine-Fehler, Zeitüberschreitung

Methoden #

MethodeRolle
of_open ( )Erzeugt die Stimme. Optional — of_speak tut es — aber beim Öffnen des Fensters aufgerufen, fällt der Aufwand einmal an, fern des ersten Satzes. Liefert eine positive Zahl, sobald die Stimme existiert, 0 oder weniger, wenn sie nicht erzeugt werden konnte
of_is_open ( )Wahr, sobald die Stimme existiert
of_speak ( string as_text )Setzt den Text und liest ihn ab dem ersten Satz. Ohne Argument wird is_text erneut gelesen. Liefert 0 nach dem Senden, -1, wenn die Stimme nicht erzeugt werden konnte
of_speak_from ( long al_index )Setzt das Lesen bei einem bestimmten Satz fort. Liefert 0 nach dem Senden, -1, wenn die Stimme nicht erzeugt werden konnte
of_pause ( )Hält das Lesen an der aktuellen Stelle an. Liefert 0 nach dem Senden, -1, wenn die Stimme nicht erzeugt werden konnte
of_resume ( )Setzt dort fort, wo of_pause aufgehört hat. Liefert 0 nach dem Senden, -1, wenn die Stimme nicht erzeugt werden konnte
of_stop ( )Beendet das Lesen; of_speak beginnt wieder beim ersten Satz
of_is_speaking ( )Wahr, solange ein Satz gelesen wird — ein pausiertes Lesen zählt noch. Bei der Komponente erfragt, nie eine veraltete Kopie
of_sentence_count ( )Liefert, wie viele Sätze die Komponente aus dem Text gemacht hat
of_count ( ) → integerWie viele Sätze die Komponente aus dem Text gemacht hat — dieselbe Zahl, die of_sentence_count liefert. Die Bibliothek stellt diese Frage überall unter einem Namen
of_voices ( ref string as_names[] )Füllt das Array mit den auf diesem Arbeitsplatz installierten Stimmen und liefert deren Anzahl
of_languages ( ref string as_tags[] )Füllt das Array mit den Sprachen, die dieser Arbeitsplatz aussprechen kann, ohne Dubletten, und liefert deren Anzahl
of_voice_used ( )Die Stimme, die die Komponente dem Motor tatsächlich übergibt — nicht immer die von is_lang verlangte: Ein Arbeitsplatz trägt die Stimmen, die jemand installiert hat, und keine anderen. Leer = die Komponente gibt keine vor, und der Motor nimmt seine eigene, die der Systemsprache. Diese zu benennen wäre geraten. ue_error sagt dasselbe beim Lesen; dies liest es vorher
of_speak_sync ( { string as_text } )Liest und WARTET auf das Ende: die nächste Zeile läuft nach dem letzten Satz, das Fenster zeichnet weiter. Gibt 0 zurück am Ende, -4 bei Fehler oder Zeitüberschreitung (is_last_error)
of_enqueue ( string as_text )Stellt einen Text in die WARTESCHLANGE: sofort gelesen, wenn die Stimme frei ist, sonst nach dem laufenden Lesen, ohne es je zu unterbrechen. Gibt 0 zurück, -1 wenn die Stimme nicht erzeugt werden konnte
of_clear_queue ( )Vergisst die wartenden Texte, ohne den gelesenen zu unterbrechen. Gibt 0 zurück, -1 wenn die Stimme nicht erzeugt werden konnte
of_queue_count ( )Gibt die Zahl der noch wartenden Texte zurück (der gelesene zählt nicht)
of_add_replacement ( string as_from, string as_to )Eine Ausspracheregel: jedes GANZE Wort as_from wird als as_to gelesen (PB → PowerBuilder). Vor den Tags angewandt, vom Objekt behalten. Gibt 0 zurück, -5 wenn as_from leer ist
of_clear_replacements ( )Leert das Wörterbuch. Gibt 0 zurück
of_replacement_count ( )Gibt die Zahl der Regeln im Wörterbuch zurück
of_pick_voice ( string as_lang, string as_gender )Wählt eine INSTALLIERTE Stimme für eine Sprache und, falls vorhanden, ein Geschlecht (GENDER_FEMALE, GENDER_MALE, GENDER_ANY): genaue Sprache, dann ihre Familie. Setzt sie in is_voice und gibt sie zurück; leer, wenn keine Stimme diese Sprache spricht
of_duration ( )Gibt die GESCHÄTZTE Dauer des Vorlesens in Millisekunden zurück (Wörter pro Minute beim gewünschten Tempo, Pausen inklusive): für einen Fortschrittsbalken, nicht für eine Stoppuhr. Das Tempo LERNT die Stimme: jeder zu Ende gelesene Satz misst das echte, je Stimme auf diesem Rechner gemerkt
of_position ( )Gibt die geschätzte Position des Vorlesens in Millisekunden zurück, verfeinert durch die von der Engine gemeldeten Wörter; 0 wenn nichts gelesen wird
of_progress ( )Gibt den geschätzten Fortschritt zurück, 0 bis 100
of_spoken_text ( )Die Sätze, WIE die Stimme sie erhält, einer pro Zeile (Wörterbuch angewandt, Tags aufgelöst): der Text, der anzuzeigen ist, um Wort für Wort zu folgen
of_process_events ( )Leert die anstehenden Ereignisse und löst sie auf diesem Objekt aus. Der interne Pump der Komponente ruft sie für Sie auf, solange die Stimme offen ist — Sie rufen sie nie auf
of_close ( )Gibt die Stimme frei und stoppt zuvor, was sie gerade sagte. Der Destruktor ruft es auf
of_reset ( )Setzt alle Eigenschaften auf ihren Ausgangswert zurück

Ereignisse #

EreignisAusgelöst wenn
ue_started (string as_lang)Das Lesen beginnt; as_lang erinnert an die Sprache
ue_stopped ( )Der letzte Satz ist fertig, oder of_stop wurde aufgerufen
ue_paused ( )Das Lesen ist angehalten
ue_resumed ( )Das Lesen läuft weiter
ue_sentence (long al_index, string as_text)Für jeden Satz, mit Rang und Text: so folgt man dem Lesen anderswo im Fenster
ue_error (string as_message)Der Arbeitsplatz hat keine Engine oder keine Stimme, oder die Stimme versagt. Eine bloß FEHLENDE Stimme ist kein Fehler: das ist ue_voice_fallback
ue_voices_ready (long al_count)Die Engine hat ihre Stimmenliste gefüllt — sie kommt spät; of_voices, of_languages, of_voice_used und of_pick_voice warten von selbst darauf (höchstens 2,5 s), dieses Event sagt nur, WANN sie kam; al_count nennt, wie viele der Arbeitsplatz hat
ue_word (long al_index, long al_start, long al_length)Das gerade gesprochene WORT im Satz al_index: Mid(satz, al_start, al_length). Wenn die Engine Wörter meldet (die meisten Windows-Stimmen)
ue_queue_done ( )Der letzte Text der Warteschlange (of_enqueue) ist gelesen
ue_voice_fallback (string as_wanted, string as_used)Die gewünschte Stimme oder Sprache ist nicht auf diesem Arbeitsplatz; as_used nennt die, die stattdessen liest. Eine Information, kein Fehler: das Vorlesen geht weiter

Aussprache: Pausen, Buchstabieren, Wörterbuch #

WebView2 hat kein SSML. Der Text trägt daher drei eigene Tags, die vor der Satztrennung aufgelöst werden, und ein Wörterbuch ganzer Wörter, das davor angewandt wird. Ein unbekanntes Tag wird gelesen, wie es dasteht.

TagWirkung
[pause=500]Eine Stille von 500 ms (höchstens 10 s). Die Pause beendet den laufenden Satz
[spell]ABC12[/spell]Jedes Zeichen einzeln gesprochen: „A, B, C, 1, 2“
[say-as=digits]4152[/say-as]Die Ziffern einzeln, nicht „viertausendeinhundertzweiundfünfzig“
[say-as=characters]…[/say-as]Wie [spell]
// The dictionary : whole words, in the order added, case-sensitive
inv_voice.of_add_replacement("PB", "PowerBuilder")
inv_voice.of_add_replacement("Mme", "Madame")
inv_voice.of_add_replacement("4152", "[say-as=digits]4152[/say-as]")   // a rule may add a tag

inv_voice.of_speak("Mme Durand, PB order 4152 [pause=600] code [spell]PBT[/spell].")

Warteschlange, synchrones Vorlesen, Fortschritt #


Beispiele #

Eine Benachrichtigung vorlesen #

inv_voice.of_speak("Order 4152 has been shipped. It arrives on Thursday.")

Den aktuellen Satz hervorheben #

// in ue_sentence, on the nonvisual object
st_read.text = as_text

// and a click on a paragraph resumes from it
inv_voice.of_speak_from(2)

Stimme und Tempo wählen #

string ls_voices[]

if inv_voice.of_voices(ls_voices) > 0 then inv_voice.is_voice = ls_voices[1]
inv_voice.ii_rate = 75
inv_voice.of_speak()

Ansagen ohne Unterbrechen: die Warteschlange #

// Each event of the application is queued : all of them are heard, in order
inv_voice.of_enqueue("Order 4152 has been shipped.")
inv_voice.of_enqueue("Order 4153 is ready.")
// ue_queue_done fires after the last one

Das aktuelle Wort hervorheben #

// in ue_sentence : keep the sentence
is_sentence = as_text

// in ue_word : the word is Mid(is_sentence, al_start, al_length)
st_read.text = Left(is_sentence, al_start - 1) + "[" + Mid(is_sentence, al_start, al_length) + "]" + Mid(is_sentence, al_start + al_length)

Eine Stimme nach Sprache und Geschlecht, dann Vorlesen bis zum Ende #

inv_voice.of_pick_voice(n_pbt_speechout.LANG_FR_FR, n_pbt_speechout.GENDER_FEMALE)
if inv_voice.of_speak_sync("Please confirm the order.") = 0 then
	li_answer = MessageBox("Order", "Confirm ?", Question!, YesNo!)
end if

Bewährte Praxis #


← Komponentenreferenz · Inhalt des Handbuchs