NÃO reinvente a roda! Como Traduzir Fala na Azure

Finalizamos a categoria de Fala dos Serviços Cognitivos da Azure, desta vez com foco em como traduzir fala na Azure!

Como funciona a Tradução de Fala na Azure

Internacionalização de produtos pode ser um ponto competitivo extremamente interessante, porém trabalhoso. Alinhando isso com a interação por fala, o quão complicado poderia ser?

Bom, usando os Serviços Cognitivos, a complicação é praticamente zero. O Serviço para Tradução de Fala na Azure, também conta com as mesmas características de facilidade de implementação e uso, bem como deixa de lado a necessidade de conhecer toda a dificuldade por trás da inteligência artificial.

Vamos demonstrar como implementar essa funcionalidade ao longo do artigo.

Todo o código está disponível no github.

Então, vamos a mão na massa!

1. Tenha seu projeto

Criamos um projeto do tipo ASP.NET Core Web Application, com o template Web Application para ter o projeto criado voltado para o Razor Pages. Demos a ele o nome de AzureCognitiveServices. Confira no primeiro passo do primeiro artigo técnico da série e crie o seu projeto também.

Com o projeto criado e atualizado, procure a Solution Folder com nome de Speech, que é o nome da categoria que continuamos explorando e finalizamos neste artigo.

Dentro dessa Solution Folder, crie um novo Projeto do tipo Class Library (.NET Core) e o nomeie como SpeechTranslation.

Até esse ponto, a estrutura do projeto deve ser a seguinte:

\"estrutura-projeto-traduzir-fala\"
Estrutura do Projeto

2. Configure a Azure

Crie uma conta gratuita no Azure e, logo após, crie um recurso para converter fala em texto, ou utilize o criado no primeiro, ou segundo artigo da categoria de Fala (acesse a busca de recursos aqui) e obtenha a chave e o endpoint do recurso, como na imagem a seguir.

Campos de chave e endpoint do recurso

3. Conecte a Tradução de Fala ao seu projeto

Voltando ao projeto no Visual Studio, vamos renomear o arquivo Class1.cs para algo mais palatável. Renomeio para TraducaoDeFala.cs.

Abra o Package Manager Console e execute o seguinte comando para adicionar as bibliotecas do Serviço Cognitivo para Converter Fala em Texto ao projeto que chamamos de SpeechTranslation.

dotnet add .SpeechTranslation package Microsoft.CognitiveServices.Speech --version 1.12.1

Não esqueça, também, de conectar o projeto SpeechTranslation ao projeto AzureCognitiveServices clicando com o botão direito em cima do projeto AzureCognitiveServices e indo a opção Add > Reference…, depois adicionando o projeto SpeechTranslation. Assim o projeto AzureCognitiveServices conseguirá acessar o projeto SpeechTranslation e consumir o que precisar.

\"adicionado-projeto-traduzir-fala-na-azure\"
Adicionando o projeto SpeechTranslation ao projeto AzureCognitiveServices

4. Implemente a Tradução de Fala na classe TraducaoDeFala.cs

Comece colocando todos os Usings necessários para o funcionamento correto da classe:

using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Translation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

Depois adicione as variáveis de instância que utilizaremos ao longo da classe:

namespace SpeechTranslation
{
    public class TraducaoDeFala
    {
        private const string _chave = \"<sua chave>\";
        private const string _endpoint = \"<seu endpoint>\";
        private readonly SpeechTranslationConfig _configuracaoDaTraducao;

Lembre de substituir \"<sua chave>\" e \"<seu endpoint>\" pelos valores obtidos no passo 2. Configure a Azure.

O objeto do tipo SpeechTranslationConfig é, justamente, o objeto  que utilizaremos para chamar os métodos que o Serviço Cognitivo para Traduzir Fala na Azure nos disponibiliza.

Crie um método construtor para que, sempre que essa classe for instanciada, a variável _configuracaoDaTraducao seja instanciada também.

public TraducaoDeFala() =>
    _configuracaoDaTraducao = SpeechTranslationConfig.FromEndpoint(new Uri(_endpoint), _chave);

Adicione os códigos abaixo e não esqueça de fechar todas as chaves da classe:

public async Task<IList<string>> Ouvir(Idioma traduzirDe, IEnumerable<Idioma> traduzirPara)
{
    _configuracaoDaTraducao.SpeechRecognitionLanguage = traduzirDe.Codigo;

    foreach (var idioma in traduzirPara)
        _configuracaoDaTraducao.AddTargetLanguage(idioma.Codigo);

    using var reconhecer = new TranslationRecognizer(_configuracaoDaTraducao);
    var resultado = await reconhecer.RecognizeOnceAsync();

    if (resultado.Reason == ResultReason.TranslatedSpeech)
    {
        var traducoes = new List<string>(resultado.Translations.Count + 1)
            { $\"Traduzindo de \"{traduzirDe.Nome}\"\" };

        traducoes.AddRange(
            resultado
            .Translations
            .Select(r => $\"Traduzido para \"{NomearIdioma(r.Key)}\": \"{r.Value}\"\"));

        return traducoes;
    }

    var semTraducao = new List<string> { $\"Não foi possível traduzir de \"{traduzirDe.Nome}\".\" };

    if (resultado.Reason == ResultReason.Canceled)
    {
        var cancelamento = CancellationDetails.FromResult(resultado);

        if (cancelamento.Reason == CancellationReason.Error)
            semTraducao.Add($\" Erro: \"{cancelamento.ErrorDetails}\".\");
    }

    return semTraducao;
}

private static string NomearIdioma(string codigo) =>
    Idioma.IdiomasDisponiveis()
        .Any(i => i.Codigo.ToLower().Contains(codigo.ToLower()))
            ? Idioma.IdiomasDisponiveis()
                .First(i => i.Codigo.ToLower().Contains(codigo.ToLower())).Nome
            : codigo;
}
}

Essa classe contém dois métodos, o primeiro, que chamamos de Ouvir(), é responsável por entender o áudio, a partir da entrada de áudio padrão, que queremos que o Serviço Cognitivo traduza e nos devolva um texto para cada idioma alvo de tradução escolhida.

Dentro dele, o método que efetivamente captura o áudio pela entrada de som padrão é o reconhecer.RecognizeOnceAsync. Após ele, apenas verificamos se a execução foi concluída com sucesso, ou não, e retornamos uma lista com as traduções ou com os erros ocorridos.

O segundo, NomearIdioma(), recebe o código do idioma traduzido, devolvido pelo Serviço, e retorna, se possível, o nome do idioma.

A classe inteira pode ser visualizada no github.

5. Crie a classe Idioma.cs ainda no projeto SpeechTranslation.

Ainda no projeto chamado de SpeechTranslation crie uma nova classe e dê o nome de Idioma.cs. Essa classe será responsável por guardar informações sobre o idioma escolhido para traduzir, bem como listar todos os idiomas que temos disponíveis.

Comece colocando o Using necessário para o funcionamento correto da classe:

using System.Collections.Generic;

Depois adicione o método construtor da classe e as propriedades do mesmo.

namespace SpeechTranslation
{
    public class Idioma
    {
        private Idioma(string nome, string codigo)
        {
            Nome = nome;
            Codigo = codigo;
        }

        public string Nome { get; private set; }

        public string Codigo { get; private set; }

Note que o método construtor da classe é privado, o que indica que ninguém, fora ela mesma, consegue criar instâncias.

Além disso, todas as propriedades possuem sua propriedade set também privada.

Nessa classe temos as informações necessárias para definir qualquer idioma.

Agora, por fim, coloque o restante do código e não esqueça de fechar as chaves ao final da classe.

public static IEnumerable<Idioma> IdiomasDisponiveis() =>
    new List<Idioma>(10)
    {
        new Idioma(\"Português (Brasil)\", \"pt-BR\"),
        new Idioma(\"Inglês (EUA)\", \"en-US\"),
        new Idioma(\"Espanhol\", \"es-ES\"),
        new Idioma(\"Finlandês\", \"fi-FI\"),
        new Idioma(\"Francês\", \"fr-FR\"),
        new Idioma(\"Italiano\", \"IT-IT\"),
        new Idioma(\"Japonês\", \"ja-JP\"),
        new Idioma(\"Holandês\", \"nl-NL\"),
        new Idioma(\"Russo\", \"ru-RU\"),
        new Idioma(\"Chinês\", \"zh-CN\"),
    };
}
}

Esse método, por estar dentro da mesma classe, consegue criar instâncias da mesma. Por isso retorna uma lista contendo diversos idiomas.

Note que todos os idiomas, e seus códigos, estão fixos no código, o que chamamos de hard coded, pois o kit de desenvolvimento para este Serviço Cognitivo ainda não conta com uma forma de listar os idiomas disponíveis. Mas, você pode ver todos acessando aqui. Fique a vontade para adicionar, ou remover, idiomas.

A classe inteira pode ser visualizada no github.

6. Crie o arquivo SpeechTranslation.cshtml no projeto AzureCognitiveServices

Dentro do projeto AzureCognitiveServices utilize a pasta Speech, dentro da pasta Pages. Nesta pasta adicione uma Razor Page e a chame de SpeechTranslation.cshtml.

Nela, criaremos o formulário responsável por iniciar a captura de áudio, bem como o idioma da fala que será traduzido e os idiomas para o qual a frase será traduzida.

Vamos, primeiro, editar o código do servidor. Para isso, clique com o botão direito no arquivo aberto e vá em Go to PageModel ou aperte o F7.

Esse arquivo é responsável pelo código C# desta página. Comece colocando os usings.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using SpeechTranslation;
using System.Collections.Generic;
using System.Linq;

Adicione agora as variáveis que utilizaremos na classe.

namespace AzureCognitiveServices
{
    public class SpeechTranslationModel : PageModel
    {
        public ICollection<string> Mensagens { get; private set; } = new List<string>(0);
        public readonly IEnumerable<Idioma> Idiomas;
        [BindProperty]
        public IList<string> TraduzirPara { get; set; }

Temos apenas três variáveis. A primeira, ICollection<string> Mensagens, é responsável por armazenar as mensagens com as traduções, ou erros, da tradução de fala e, por padrão, começa como uma List vazia.

Já a outra é uma lista que conterá todos os idiomas disponíveis, a chamamos de IEnumerable <Idiomas>.

Por fim, temos a variável IList<string> TraduzirPara marcada com [BindProperty], que é responsável por capturar os idiomas que serão alvos da tradução.

Crie o método construtor.

public SpeechTranslationModel() =>
    Idiomas = Idioma.IdiomasDisponiveis();

O método construtor apenas alimenta a lista de Idiomas que criamos para ser exibida no HTML.

Por último, crie o método post para capturar os envios do formulário HTML e não esqueça de fechar as chaves da classe.

public void OnPost()
{
    if (!TraduzirPara.Any())
    {
        Mensagens.Add(\"Não foi possível traduzir. Você precisa selecionar pelo menos 1 idioma alvo.\");
        return;
    }
    var traduzirDe = Idiomas.FirstOrDefault(n => Request.Form[\"traduzirDe\"].Equals(n.Codigo));
    var traduzirPara = Idiomas.Where(i => TraduzirPara.Any(alvo => alvo.Equals(i.Codigo)));
    Mensagens = new TraducaoDeFala().Ouvir(traduzirDe, traduzirPara).Result;
}
}
}

O método post dessa classe é bem curto, ele começa verificando se pelo menos 1 idioma foi selecionado como alvo da tradução, após isso, verifica qual o idioma foi escolhido para se falar, quais os idiomas que serão alvos da tradução e, por fim, chama o método da classe que criamos no passo 4. Implemente a Tradução de Fala na classe TraducaoDeFala.cs e armazena os textos resultantes na variável Mensagens.

Isso encerra o código da parte do servidor. Vamos voltar a parte do HTML.

A classe HTML terá o código inicial. O altere para isso:

@page
@model AzureCognitiveServices.SpeechTranslationModel
@{
    ViewData[\"Title\"] = \"Tradução de Fala\";
    var corDoAlert = Model.Mensagens.Any(m => m.ToLower().StartsWith(\"não\"))
        ? \"danger\"
        : \"success\";
}
<h1>Tradução de Fala</h1>

No início do código HTML verificamos se a variável Mensagens, do servidor, possui alguma informação e qual é ela. Então modificamos a cor do alerta de acordo com isso.

Coloque o seguinte código HTML no restante do arquivo:

<form method=\"post\">
    <div>
        <div>
            <div>
                <label for=\"traduzirDe\">Traduzir de:</label>
                <select name=\"traduzirDe\" id=\"traduzirDe\" required>
                    @foreach (var idioma in Model.Idiomas)
                    {
                        <option value=\"@idioma.Codigo\">@idioma.Nome</option>
                    }
                </select>
            </div>
        </div>
        <div>
            <fieldset>
                <legend>Selecione os idiomas alvos para tradução:</legend>
                <div>
                    @foreach (var idioma in Model.Idiomas)
                    {
                        <div>
                            <input type=\"checkbox\" id=\"@idioma.Codigo\" name=\"traduzirPara\" value=\"@idioma.Codigo\">
                            <label for=\"@idioma.Codigo\">@idioma.Nome</label>
                        </div>
                    }
                </div>
            </fieldset>
        </div>
    </div>
    <br />
    <br />
    <div>
        <button type=\"submit\">Ouvir</button>
    </div>
</form>
@foreach (var mensagem in Model.Mensagens)
{
    <div role=\"alert\">
        @mensagem
        <button type=\"button\" data-dismiss=\"alert\" aria-label=\"Close\">
            <span aria-hidden=\"true\">&times;</span>
        </button>
    </div>
}

Este código tem apenas o HTML que gerará um formulário contendo o campo para escolha do idioma, obrigatória para Traduzir Fala, um espaço exibindo todos os idiomas alvos para escolha e um botão para iniciar o processo de captura de áudio pela entrada padrão e tradução.

Cada opção dos campos de idioma é um elemento da lista de Idiomas do servidor, que estamos percorrendo com um foreach.

Ao final, caso a variável Mensagens possua alguma informação, uma alerta é exibido para cada um dos elementos e sua cor depende do conteúdo da mensagem.

Os arquivos inteiros podem ser visualizados no github, tanto o arquivo de HTML, quando a classe do servidor.

7. Adicione ao menu a página para Traduzir Fala criada.

Agora que tudo está criado, chegamos ao momento de adicionar ao menu a página criada. Para isso, vá na pasta Shared e abra o arquivo _Layout.cshtml. Esse arquivo tem todo o layout que é compartilhado por todas as páginas, o que se repete em todas, como menu e footer, por exemplo.

No primeiro artigo da categoria de Fala criamos um menu para todos os serviços cognitivos de Fala, então, apenas complemente esse menu com mais uma opção.

Logo abaixo da opção de Fala em Texto, adicione o seguinte código:

<a asp-page=\"/Speech/SpeechTranslation\">Tradução de Fala</a>

Isso fará com que o menu tenha mais uma opção, similar a imagem a seguir.

\"\"
Exemplo do menu com a opção de ir à página Tradução de Fala

O arquivo inteiro pode ser visualizado no github.

Conclusão

Com o Serviço para Traduzir Fala na Azure conseguimos, de forma rápida, uma aplicação que consegue interagir com o usuário em diversos idiomas, facilitando a internacionalização do produto, o que pode ajudar em diversos cenários.

Com isso, a estrutura atual do seu projeto deve estar se parecendo assim:

Estrutura atual do projeto

Todo o projeto está disponível no github com uma licença que possibilita colaboração. Sinta-se a vontade.

Siga-nos em nossas redes sociais!

Posts recentes

Ultimas do blog