Fala do Android
Este artigo aborda os conceitos básicos do uso do namespace Android.Speech muito poderoso. Desde a sua criação, o Android tem sido capaz de reconhecer a fala e produzi-la como texto. É um processo relativamente simples. Para texto para fala, no entanto, o processo é mais envolvido, pois não só o mecanismo de fala deve ser levado em conta, mas também os idiomas disponíveis e instalados a partir do sistema Text To Speech (TTS).
Visão geral da fala
Ter um sistema que "entenda" a fala humana e enuncia o que está sendo digitado – Speech to Text e Text to Speech – é uma área cada vez maior dentro do desenvolvimento móvel à medida que a demanda por comunicação natural com nossos dispositivos aumenta. Há muitos casos em que ter um recurso que converte texto em fala, ou vice-versa, é uma ferramenta muito útil para incorporar em seu aplicativo Android.
Por exemplo, com a repressão ao uso do celular durante a condução, os usuários querem uma maneira mãos-livres de operar seus dispositivos. A infinidade de diferentes fatores de forma do Android — como o Android Wear — e a inclusão cada vez maior daqueles capazes de usar dispositivos Android (como tablets e blocos de notas), criaram um foco maior em ótimos aplicativos TTS.
O Google fornece ao desenvolvedor um rico conjunto de APIs no namespace Android.Speech para cobrir a maioria das instâncias de tornar um dispositivo "consciente de fala" (como software projetado para cegos). O namespace inclui a facilidade de permitir que o texto seja traduzido em fala através Android.Speech.Tts
do , controle sobre o mecanismo usado para executar a tradução, bem como um número de RecognizerIntent
s que permitem que a fala seja convertida em texto.
Embora as facilidades existam para que a fala seja compreendida, há limitações com base no hardware usado. É improvável que o dispositivo interprete com sucesso tudo o que lhe é falado em todos os idiomas disponíveis.
Requisitos
Não há requisitos especiais para este guia, além de seu dispositivo ter um microfone e alto-falante.
O núcleo de um dispositivo Android interpretando a fala é o uso de um Intent
com um OnActivityResult
correspondente .
É importante, porém, reconhecer que o discurso não é compreendido – mas interpretado em texto. A diferença é importante.
A diferença entre compreender e interpretar
Uma definição simples de compreensão é que você é capaz de determinar pelo tom e contexto o real significado do que está sendo dito. Interpretar significa apenas pegar as palavras e produzi-las de outra forma.
Considere o seguinte exemplo simples que é usado em conversas diárias:
Olá, tudo bem?
Sem flexão (ênfase colocada em palavras específicas ou partes de palavras), é uma pergunta simples. No entanto, se um ritmo lento for aplicado à linha, a pessoa que está ouvindo detectará que o asker não está muito feliz e talvez precise se animar ou que o asker não está bem. Se a ênfase é colocada em "são", a pessoa que pergunta geralmente está mais interessada na resposta.
Sem um processamento de áudio bastante poderoso para fazer uso da inflexão e um grau de inteligência artificial (IA) para entender o contexto, o software não consegue nem começar a entender o que foi dito — o melhor que um simples telefone pode fazer é converter a fala em texto.
Configurando
Antes de usar o sistema de fala, é sempre aconselhável verificar se o dispositivo tem um microfone. De pouco adiantaria tentar executar seu aplicativo em um bloco de notas do Kindle ou do Google sem um microfone instalado.
O exemplo de código abaixo demonstra como consultar se um microfone está disponível e, se não, para criar um alerta. Se nenhum microfone estiver disponível neste momento, você encerrará a atividade ou desabilitará a capacidade de gravar a fala.
string rec = Android.Content.PM.PackageManager.FeatureMicrophone;
if (rec != "android.hardware.microphone")
{
var alert = new AlertDialog.Builder(recButton.Context);
alert.SetTitle("You don't seem to have a microphone to record with");
alert.SetPositiveButton("OK", (sender, e) =>
{
return;
});
alert.Show();
}
Criando a intenção
A intenção para o sistema de fala usa um tipo particular de intenção chamado RecognizerIntent
. Essa intenção controla um grande número de parâmetros, incluindo quanto tempo esperar com silêncio até que a gravação seja considerada encerrada, quaisquer idiomas adicionais para reconhecer e produzir, e qualquer texto para incluir no Intent
diálogo modal do como meio de instrução. Neste trecho, VOICE
é um readonly int
usado para reconhecimento em OnActivityResult
.
var voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
voiceIntent.PutExtra(RecognizerIntent.ExtraPrompt, Application.Context.GetString(Resource.String.messageSpeakNow));
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 15000);
voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults, 1);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.Default);
StartActivityForResult(voiceIntent, VOICE);
Conversão do discurso
O texto interpretado a partir da fala será entregue dentro do , que é retornado quando a atividade foi concluída e é acessado Intent
via GetStringArrayListExtra(RecognizerIntent.ExtraResults)
. Isso retornará um IList<string>
, do qual o índice pode ser usado e exibido, dependendo do número de idiomas solicitados na intenção do chamador (e especificados no RecognizerIntent.ExtraMaxResults
). Como em qualquer lista, porém, vale a pena verificar se há dados a serem exibidos.
Ao ouvir o valor de retorno de um StartActivityForResult
, o OnActivityResult
método deve ser fornecido.
No exemplo abaixo, textBox
é um TextBox
usado para emitir o que foi ditado. Ele também pode ser usado para passar o texto para alguma forma de intérprete e, a partir daí, o aplicativo pode comparar o texto e a ramificação com outra parte do aplicativo.
protected override void OnActivityResult(int requestCode, Result resultVal, Intent data)
{
if (requestCode == VOICE)
{
if (resultVal == Result.Ok)
{
var matches = data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
if (matches.Count != 0)
{
string textInput = textBox.Text + matches[0];
textBox.Text = textInput;
switch (matches[0].Substring(0, 5).ToLower())
{
case "north":
MovePlayer(0);
break;
case "south":
MovePlayer(1);
break;
}
}
else
{
textBox.Text = "No speech was recognised";
}
}
base.OnActivityResult(requestCode, resultVal, data);
}
}
Conversão de Texto em Fala
Texto para fala não é exatamente o inverso de fala para texto e depende de dois componentes principais; um mecanismo de conversão de texto em fala sendo instalado no dispositivo e um idioma sendo instalado.
Em grande parte, os dispositivos Android vêm com o serviço padrão do Google TTS instalado e pelo menos um idioma. Isso é estabelecido quando o dispositivo é configurado pela primeira vez e será baseado em onde o dispositivo está no momento (por exemplo, um telefone configurado na Alemanha instalará o idioma alemão, enquanto um na América terá inglês americano).
Etapa 1 - Instanciando o TextToSpeech
TextToSpeech
pode levar até 3 parâmetros, os dois primeiros são necessários com o terceiro sendo opcional (AppContext
, IOnInitListener
, engine
). O ouvinte é usado para vincular ao serviço e testar se há falha com o mecanismo sendo qualquer número de mecanismos de texto para fala disponíveis no Android. No mínimo, o dispositivo terá o próprio motor do Google.
Passo 2 - Encontrar os idiomas disponíveis
A Java.Util.Locale
classe contém um método útil chamado GetAvailableLocales()
. Essa lista de idiomas suportados pelo mecanismo de fala pode então ser testada em relação aos idiomas instalados.
É uma questão trivial gerar a lista de línguas "compreendidas". Sempre haverá um idioma padrão (o idioma que o usuário definiu quando configurou seu dispositivo pela primeira vez), portanto, neste exemplo, o List<string>
tem "Padrão" como o primeiro parâmetro, o restante da lista será preenchido dependendo do resultado do textToSpeech.IsLanguageAvailable(locale)
.
var langAvailable = new List<string>{ "Default" };
var localesAvailable = Java.Util.Locale.GetAvailableLocales().ToList();
foreach (var locale in localesAvailable)
{
var res = textToSpeech.IsLanguageAvailable(locale);
switch (res)
{
case LanguageAvailableResult.Available:
langAvailable.Add(locale.DisplayLanguage);
break;
case LanguageAvailableResult.CountryAvailable:
langAvailable.Add(locale.DisplayLanguage);
break;
case LanguageAvailableResult.CountryVarAvailable:
langAvailable.Add(locale.DisplayLanguage);
break;
}
}
langAvailable = langAvailable.OrderBy(t => t).Distinct().ToList();
Esse código chama TextToSpeech.IsLanguageAvailable para testar se o pacote de idioma de uma determinada localidade já está presente no dispositivo.
Esse método retorna um LanguageAvailableResult, que indica se o idioma da localidade passada está disponível. Se LanguageAvailableResult
indicar que o idioma é NotSupported
, então não há nenhum pacote de voz disponível (mesmo para download) para esse idioma. Se LanguageAvailableResult
estiver definido como MissingData
, é possível baixar um novo pacote de idiomas, conforme explicado abaixo na Etapa 4.
Passo 3 - Definindo a velocidade e o pitch
O Android permite que o usuário altere o som da fala alterando o SpeechRate
e Pitch
(a taxa de velocidade e o tom da fala). Isso vai de 0 a 1, com a fala "normal" sendo 1 para ambos.
Etapa 4 - Testando e carregando novos idiomas
O download de um novo idioma é realizado usando um Intent
arquivo . O resultado dessa intenção faz com que o método OnActivityResult seja invocado. Ao contrário do exemplo de fala para texto (que usou o RecognizerIntent como um PutExtra
parâmetro para o Intent
), o teste e o carregamento Intent
s são Action
baseados em:
TextToSpeech.Engine.ActionCheckTtsData – Inicia uma atividade do mecanismo de plataforma
TextToSpeech
para verificar a instalação adequada e a disponibilidade de recursos de idioma no dispositivo.TextToSpeech.Engine.ActionInstallTtsData – Inicia uma atividade que solicita que o usuário baixe os idiomas necessários.
O exemplo de código a seguir ilustra como usar essas ações para testar recursos de idioma e baixar um novo idioma:
var checkTTSIntent = new Intent();
checkTTSIntent.SetAction(TextToSpeech.Engine.ActionCheckTtsData);
StartActivityForResult(checkTTSIntent, NeedLang);
//
protected override void OnActivityResult(int req, Result res, Intent data)
{
if (req == NeedLang)
{
var installTTS = new Intent();
installTTS.SetAction(TextToSpeech.Engine.ActionInstallTtsData);
StartActivity(installTTS);
}
}
TextToSpeech.Engine.ActionCheckTtsData
testes de disponibilidade de recursos linguísticos. OnActivityResult
é invocado quando este teste é concluído. Se os recursos de idioma precisarem ser baixados, OnActivityResult
disparará a TextToSpeech.Engine.ActionInstallTtsData
ação para iniciar uma atividade que permita ao usuário baixar os idiomas necessários. Observe que essa OnActivityResult
implementação não verifica o Result
código porque, neste exemplo simplificado, já foi determinada que o pacote de idioma precisa ser baixado.
A TextToSpeech.Engine.ActionInstallTtsData
ação faz com que a atividade de dados de voz do Google TTS seja apresentada ao usuário para escolher os idiomas a serem baixados:
Como exemplo, o usuário pode escolher francês e clicar no ícone de download para baixar dados de voz em francês:
A instalação desses dados acontece automaticamente após a conclusão do download.
Passo 5 - O IOnInitListener
Para que uma atividade possa converter o texto em fala, o método OnInit
de interface precisa ser implementado (este é o segundo parâmetro especificado para a instanciação da TextToSpeech
classe). Isso inicializa o ouvinte e testa o resultado.
O ouvinte deve testar para ambos OperationResult.Success
e OperationResult.Failure
no mínimo.
O exemplo a seguir mostra exatamente isso:
void TextToSpeech.IOnInitListener.OnInit(OperationResult status)
{
// if we get an error, default to the default language
if (status == OperationResult.Error)
textToSpeech.SetLanguage(Java.Util.Locale.Default);
// if the listener is ok, set the lang
if (status == OperationResult.Success)
textToSpeech.SetLanguage(lang);
}
Resumo
Neste guia, analisamos os conceitos básicos de conversão de texto em fala e fala em texto e possíveis métodos de como incluí-los em seus próprios aplicativos. Embora eles não abranjam todos os casos específicos, agora você deve ter uma compreensão básica de como a fala é interpretada, como instalar novos idiomas e como aumentar a inclusão de seus aplicativos.