PBToolboxAI v3 ← Site

speechout — n_pbt_speechout #

← Referência dos componentes · Índice do guia

Leitura em voz alta: a aplicação lê um texto frase a frase e diz-lhe onde vai. Sem serviço de terceiros, sem chave de API — a síntese é a do posto de trabalho.

▶ Ver ao vivo — Aplicação de demonstração, mosaico Speech out: a pré-visualização, o código que a produz e esta página, lado a lado.


Em resumo #

Objeto não visualn_pbt_speechout
Serve paraFazer ouvir um texto: acessibilidade, mãos ocupadas, um aviso que ninguém olha
PrincípioDá o texto; o componente corta-o em frases e diz-lhe qual está a ler
DependênciaA síntese de voz do posto — sem serviço de terceiros, sem chave de API

Início rápido #

// 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.")

Não visual: a ligação dos eventos #

Uma voz não tem nada para mostrar. O componente não desenha portanto nada: nenhuma barra de leitura para arranjar espaço, nenhum lugar tirado àquilo que serve.

E para isso não tem de ligar nada: um objeto não visual não tem janela, logo não há campainha, mas o componente recolhe os seus eventos no ciclo do PowerBuilder enquanto a voz está aberta e dispara-os no objeto. Só escreve os tratadores ue_* (sem recetor, sem temporizador).

// 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

Seguir a leitura no SEU texto #

ue_sentence transporta o índice e o texto da frase que está a ser lida. É daí que vem o realce — no seu mle_, na sua datawindow ou no seu statictext: você sabe onde está o seu texto, nós nunca.

O caminho inverso também existe: of_speak_from() retoma numa frase precisa, o que se liga ao clique num parágrafo. Os números vêm de ue_sentence, logo apontam sempre para o que foi realmente lido.

O corte é o do componente, não o seu: of_sentence_count() devolve a contagem dele. Não volte a contar do seu lado, as duas divergiriam.


O que o posto sabe realmente dizer #

of_languages() devolve os idiomas que este posto sabe efetivamente pronunciar, sem duplicados. É a pergunta que um utilizador faz: não «que vozes existem», mas «o meu idioma está lá».

of_voices() desce um degrau e nomeia as próprias vozes. Ambas as listas vêm da máquina, não de nós: nunca escreva um nome fixo no código.

O reconhecimento de voz não tem equivalente, e não é um esquecimento: o reconhecimento não traz qualquer lista dos idiomas que aceita.

Sem qualquer componente da sua parte, gnv_utils.of_speech_languages(as_tags[]) dá a mesma lista — a DLL consulta uma voz oculta e depois descarta-a: é o que uma janela pergunta antes de a voz existir, que idioma propor, em qual ler. A chamada é síncrona e pode demorar até dois segundos da primeira vez: a lista de vozes chega tarde, e a chamada espera por ela. E gnv_utils.of_speech_voices(as_names[], as_langs[]) dá as vozes em si com o seu idioma, para propor «Hortense» ou «Julie» em vez de uma etiqueta; gnv_utils.of_locale_name(as_tag) dá a uma etiqueta o seu nome legível — «francês (França)» para fr-FR.

string ls_tags[]

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

Propriedades #

PropriedadeTipoPredefiniçãoFunção
is_langstringen-USIdioma lido, em BCP-47 (constantes LANG_*). Decide que voz é escolhida — enquanto is_voice estiver vazia, pois um nome de voz fixa a sua própria língua. Sem voz para essa língua o posto lê com a que tem, e ue_voice_fallback nomeia as duas
is_textstring""O texto a ler. O componente corta-o em frases; três etiquetas dizem COMO ler um pedaço: [pause=500], [spell]…[/spell], [say-as=digits]…[/say-as] (ver abaixo)
is_voicestring""Nome da voz, tirado de of_voices(). Vazio = a primeira que fala is_lang
ii_rateinteger100Velocidade, em POR CENTO da normal (10 a 400). Alterada durante a leitura, aplica-se à frase seguinte
ii_pitchinteger100Altura da voz, em POR CENTO da altura normal (0 a 200)
ii_volumeinteger100Volume em percentagem (0 mudo a 100), a escala do leitor de vídeo
il_timeout_mslong300000Duração máxima de uma leitura SÍNCRONA: cinco minutos. Depois, of_speak_sync devolve -4 e a leitura é cortada (is_last_error diz porquê)
is_last_errorstring""Porque o último of_speak_sync devolveu -4: voz não criada, falha do motor, tempo esgotado

Métodos #

MétodoFunção
of_open ( )Cria a voz. Facultativo — of_speak fá-lo — mas chamá-lo ao abrir a janela paga o custo uma vez, longe da primeira frase. Devolve um número positivo quando a voz existe, 0 ou menos se não pôde ser criada
of_is_open ( )Verdadeiro assim que a voz existe
of_speak ( string as_text )Define o texto e lê-o, desde a primeira frase. Sem argumento, relê is_text. Devolve 0 uma vez enviado, -1 se a voz não pôde ser criada
of_speak_from ( long al_index )Retoma a leitura numa frase precisa. Devolve 0 uma vez enviado, -1 se a voz não pôde ser criada
of_pause ( )Suspende a leitura onde está. Devolve 0 uma vez enviado, -1 se a voz não pôde ser criada
of_resume ( )Retoma onde of_pause parou. Devolve 0 uma vez enviado, -1 se a voz não pôde ser criada
of_stop ( )Para a leitura; of_speak recomeça pela primeira frase
of_is_speaking ( )Verdadeiro enquanto uma frase é lida — uma leitura em pausa ainda conta. Perguntado ao componente, nunca uma cópia desatualizada
of_sentence_count ( )Devolve quantas frases o componente fez do texto
of_count ( ) → integerQuantas frases o componente fez do texto — o mesmo número que of_sentence_count devolve. A biblioteca faz esta pergunta sob um único nome em todo o lado
of_voices ( ref string as_names[] )Preenche o vetor com as vozes instaladas neste posto e devolve quantas são
of_languages ( ref string as_tags[] )Preenche o vetor com os idiomas que este posto sabe pronunciar, sem duplicados, e devolve quantos são
of_voice_used ( )A voz que o componente entregará realmente ao motor — nem sempre a que is_lang pede: um posto carrega as vozes que alguém lá instalou e nenhuma outra. Vazio = o componente não impõe nenhuma, e o motor toma a sua, a da língua do sistema. Nomeá-la seria adivinhar. ue_error diz o mesmo ao ler; isto lê-se antes
of_speak_sync ( { string as_text } )Lê e ESPERA o fim: a linha seguinte corre após a última frase, a janela continua a pintar-se. Devolve 0 no fim, -4 em caso de falha ou tempo esgotado (is_last_error)
of_enqueue ( string as_text )Põe um texto em FILA: lido de imediato se a voz está livre, após a leitura em curso caso contrário, sem nunca a cortar. Devolve 0, -1 se a voz não pôde ser criada
of_clear_queue ( )Esquece os textos em espera, sem cortar o que se lê. Devolve 0, -1 se a voz não pôde ser criada
of_queue_count ( )Devolve o número de textos ainda em espera (o que se lê não conta)
of_add_replacement ( string as_from, string as_to )Uma regra de pronúncia: cada palavra INTEIRA as_from é lida as_to (PB → PowerBuilder). Aplicada antes das etiquetas, guardada pelo objeto. Devolve 0, -5 se as_from estiver vazio
of_clear_replacements ( )Esvazia o dicionário. Devolve 0
of_replacement_count ( )Devolve o número de regras do dicionário
of_pick_voice ( string as_lang, string as_gender )Escolhe uma voz INSTALADA para um idioma e, se existir, um género (GENDER_FEMALE, GENDER_MALE, GENDER_ANY): idioma exato, depois a sua família. Põe-na em is_voice e devolve-a; vazio se nenhuma voz fala esse idioma
of_duration ( )Devolve a duração ESTIMADA da leitura, em milissegundos (palavras por minuto ao ritmo pedido, pausas incluídas): para uma barra de progresso, não para um cronómetro. O ritmo APRENDE a voz: cada frase lida até ao fim mede o real, guardado por voz neste posto
of_position ( )Devolve a posição estimada da leitura, em milissegundos, afinada pelas palavras que o motor reporta; 0 quando nada se lê
of_progress ( )Devolve o progresso estimado, de 0 a 100
of_spoken_text ( )As frases TAL COMO a voz as recebe, uma por linha (dicionário aplicado, etiquetas resolvidas): o texto a mostrar para seguir palavra a palavra
of_process_events ( )Esvazia os eventos pendentes e levanta-os neste objeto. O pump interno do componente chama-o por si enquanto a voz está aberta — nunca o chama
of_close ( )Liberta a voz, parando antes o que estivesse a dizer. O destrutor chama-o
of_reset ( )Repõe todas as propriedades no valor inicial

Eventos #

EventoDisparado quando
ue_started (string as_lang)A leitura começa; as_lang recorda em que idioma
ue_stopped ( )A última frase terminou, ou of_stop foi chamado
ue_paused ( )A leitura está suspensa
ue_resumed ( )A leitura recomeça
ue_sentence (long al_index, string as_text)Para cada frase, com o seu lugar e o seu texto: é assim que se segue a leitura noutro ponto da janela
ue_error (string as_message)O posto não tem motor nem voz alguma, ou a voz falha. Uma voz simplesmente AUSENTE não é um erro: é ue_voice_fallback
ue_voices_ready (long al_count)O motor preencheu a sua lista de vozes — chega tarde; of_voices, of_languages, of_voice_used e of_pick_voice esperam por ela sozinhos (2,5 s no máximo), este evento só diz QUANDO chegou; al_count diz quantas o posto tem
ue_word (long al_index, long al_start, long al_length)A PALAVRA em curso na frase al_index: Mid(frase, al_start, al_length). Quando o motor reporta as palavras (a maioria das vozes Windows)
ue_queue_done ( )O último texto da fila (of_enqueue) está lido
ue_voice_fallback (string as_wanted, string as_used)A voz ou o idioma pedido não está neste posto; as_used nomeia a que lê em seu lugar. Uma informação, não um erro: a leitura continua

Pronúncia: pausas, soletração, dicionário #

O WebView2 não tem SSML. O texto traz por isso três etiquetas próprias, resolvidas antes do corte em frases, e um dicionário de palavras inteiras aplicado antes delas. Uma etiqueta desconhecida é lida tal como está.

EtiquetaEfeito
[pause=500]Um silêncio de 500 ms (10 s no máximo). A pausa termina a frase em curso
[spell]ABC12[/spell]Cada carácter dito um a um: «A, B, C, 1, 2»
[say-as=digits]4152[/say-as]Os dígitos um a um, não «quatro mil cento e cinquenta e dois»
[say-as=characters]…[/say-as]Como [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].")

Fila, leitura síncrona, progresso #


Exemplos #

Ler uma notificação #

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

Realçar a frase em curso #

// 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)

Escolher a voz e a velocidade #

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()

Anunciar sem cortar: a fila #

// 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

Realçar a palavra em curso #

// 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)

Uma voz por idioma e género, depois ler esperando o fim #

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

Boas práticas #


← Referência dos componentes · Índice do guia