NÃO reinvente a roda! Conversão de Texto em Fala na Azure

Nos artigos anteriores, falamos da categoria Visão. Agora vamos explorar os Serviços Cognitivos da Azure de Fala, começando com como converter texto em fala!

Como funciona a Conversão de Texto em Fala na Azure

Há diversas aplicações possíveis para a conversão de Texto em Fala, como acessibilidade, interação com usuário, assistentes de voz, dentre outras.

Assim como todos os Serviços Cognitivos da Azure, o Serviço de Conversão de Texto em Fala 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.

Com a Conversão de Texto em Fala na Azure, você pode escolher “entre mais de 100 vozes em mais de 40 idiomas”.

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, criaremos agora uma Solution Folder com nome de Speech, que é o nome da categoria que estamos explorando agora.

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

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

\"Estrutura-do-projeto-conversao-texto-em-fala\"
Estrutura do Projeto

2. Configure a Azure

Crie uma conta gratuita no Azure e, logo após, crie um recurso para conversão de texto em fala e obtenha a chave e o endpoint do recurso, como na imagem a seguir.

Campos de chave e endpoint do recurso

3. Conecte a Conversão de Texto em Fala ao seu projeto

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

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

dotnet add .TextToSpeech package Microsoft.CognitiveServices.Speech --version 1.12.0

Não esqueça, também, de conectar o projeto TextToSpeech 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 TextToSpeech. Assim o projeto AzureCognitiveServices conseguirá acessar o projeto TextToSpeech consumir o que precisar.

Adicionando o projeto TextToSpeech ao projeto AzureCognitiveServices

4. Implemente a Conversão de Texto em Fala na classe TranscricaoDeTexto.cs

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

using Microsoft.CognitiveServices.Speech;
using System;
using System.Threading.Tasks;

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

namespace TextToSpeech
{
    public class TranscricaoDeTexto
    {
        private const string _chave = \"<sua chave>\";
        private const string _endpoint = \"<seu endpoint>\";

        private readonly SpeechConfig _configuracaoDaTranscricao;

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

O objeto do tipo SpeechConfig é, justamente, o objeto  que utilizaremos para chamar os métodos que o Serviço Cognitivo de Conversão de Texto em Fala nos disponibiliza.

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

public TranscricaoDeTexto() =>
    _configuracaoDaTranscricao = SpeechConfig.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<string> Falar(string textoParaFalar, Narrador narrador)
{
    _configuracaoDaTranscricao.SpeechSynthesisVoiceName = narrador.Codigo;

    using var sintetizador = new SpeechSynthesizer(_configuracaoDaTranscricao);
    using var resultado = await sintetizador.SpeakTextAsync(textoParaFalar);
    if (resultado.Reason == ResultReason.SynthesizingAudioCompleted)
    {
        return $\"O texto \"{textoParaFalar}\" será falado na saída de som padrão por {narrador.Nome} ({narrador.Pais})\";
    }
    else if (resultado.Reason == ResultReason.Canceled)
    {
        var cancelamento = SpeechSynthesisCancellationDetails.FromResult(resultado);

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

    return string.Empty;
}
}
}

Essa classe contém apenas um método, que chamamos de Falar(). Tal método é responsável por pegar o texto que queremos que o Serviço Cognitivo fale e qual a voz que escolhemos.

Dentro dela, o método que efetivamente executa o áudio pela saída de som é o sintetizador.SpeakTextAsync. Após ele, apenas verificamos se a execução foi concluída com sucesso, ou não, e retornamos uma mensagem de acordo com a situação.

A classe inteira pode ser visualizada no github.

5. Crie a classe Narrador.cs ainda no projeto TextToSpeech

Ainda no projeto chamado de TextToSpeech cria uma nova classe e dê o nome de Narrador.cs. Essa classe será responsável por guardar informações sobre o narrador escolhido, bem como listar todos os narradores 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 TextToSpeech
{
    public class Narrador
    {
        private Narrador(string nome, string codigo, string pais)
        {
            Nome = nome;
            Codigo = codigo;
            Pais = pais;
        }

        public string Nome { get; private set; }

        public string Codigo { get; private set; }

        public string Pais { 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 narrador.

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<Narrador> NarradoresDisponiveis() =>
    new List<Narrador>(20)
    {
        new Narrador(\"Heloísa\", \"pt-BR-HeloisaRUS\", \"Brasil\"),
        new Narrador(\"Daniel\", \"pt-BR-Daniel-Apollo\", \"Brasil\"),
        new Narrador(\"Zira\", \"en-US-ZiraRUS\", \"EUA\"),
        new Narrador(\"Aria\", \"en-US-AriaRUS\", \"EUA\"),
        new Narrador(\"Benjamin\", \"en-US-BenjaminRUS\", \"EUA\"),
        new Narrador(\"Laura\", \"es-ES-Laura-Apollo\", \"Espanha\"),
        new Narrador(\"Helena\", \"es-ES-HelenaRUS\", \"Espanha\"),
        new Narrador(\"Heidi\", \"fi-FI-HeidiRUS\", \"Finlândia\"),
        new Narrador(\"Julie\", \"fr-FR-Julie-Apollo\", \"França\"),
        new Narrador(\"Hortense\", \"fr-FR-HortenseRUS\", \"França\"),
        new Narrador(\"Paul\", \"fr-FR-Paul-Apollo\", \"França\"),
        new Narrador(\"Cosimo\", \"IT-IT-Cosimo-Apollo\", \"Itália\"),
        new Narrador(\"Lucia\", \"IT-IT-LuciaRUS\", \"Itália\"),
        new Narrador(\"Ayumi\", \"ja-JP-Ayumi-Apollo\", \"Japão\"),
        new Narrador(\"Ichiro\", \"ja-JP-Ichiro-Apollo\", \"Japão\"),
        new Narrador(\"Hanna\", \"nl-NL-HannaRUS\", \"Holanda\"),
        new Narrador(\"Irina\", \"ru-RU-Irina-Apollo\", \"Rússia\"),
        new Narrador(\"Pavel\", \"ru-RU-Pavel-Apollo\", \"Rússia\"),
        new Narrador(\"Huihui\", \"zh-CN-HuihuiRUS\", \"China\"),
        new Narrador(\"Kangkang\", \"zh-CN-Kangkang-Apollo\", \"China\")
    };
}
}

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

Note que todos os narradores, códigos e países 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 narradores disponíveis. Mas, você pode ver todos clicando nesse link. Fique a vontade para adicionar, ou remover, narradores.

A classe inteira pode ser visualizada no github.

6. Crie o arquivo TextToSpeech.cshtml no projeto AzureCognitiveServices

Dentro do projeto AzureCognitiveServices crie uma nova pasta dentro da pasta Pages e a chame de Speech. Nesta pasta criada agora, adicione uma Razor Page e a chame de TextToSpeech.cshtml.

Nela, criaremos o formulário responsável por capturar o texto que desejamos ser convertido em fala, bem como a informação do narrador que fará isso.

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.RazorPages;
using System.Collections.Generic;
using System.Linq;
using TextToSpeech;

Adicione agora as variáveis que utilizaremos na classe.

namespace AzureCognitiveServices
{
    public class TextToSpeechModel : PageModel
    {
        public string Mensagem { get; private set; } = string.Empty;

        public readonly IEnumerable<Narrador> Narradores;

Temos apenas duas variáveis. A primeira, string Mensagem, é responsável por armazenar a mensagem de sucesso, ou erro, da conversão de texto em fala e, por padrão, começa como uma string vazia (string.Empty).

Já a outra é uma lista que conterá todos os narradores disponíveis, a chamamos de IEnumerable<Narrador> Narradores

Crie o método construtor.

public TextToSpeechModel() =>
    Narradores = Narrador.NarradoresDisponiveis();

O método construtor apenas alimenta a lista de Narradores 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()
{
    var textoParaFalar = Request.Form[\"textoParaFalar\"];
    var narrador = Narradores.FirstOrDefault(n => Request.Form[\"Narrador\"].Equals(n.Codigo));
    Mensagem = new TranscricaoDeTexto().Falar(textoParaFalar, narrador).Result;
}
}
}

O método post dessa classe é bem curto, ele começa capturando o texto que queremos converter em fala, depois verifica qual o narrador foi escolhido e, por fim, chama o método da classe que criamos no passo 4. Implemente a Conversão de Texto em Fala na classe TranscricaoDeTexto.cs e armazena o texto resultante na variável Mensagem

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.TextToSpeechModel
@{
    ViewData[\"Title\"] = \"Texto para Fala\";

    var corDoAlert = Model.Mensagem.ToLower().StartsWith(\"erro\")
        ? \"danger\"
        : \"success\";
}

<h1>Texto para Fala</h1>

No início do código HTML verificamos se a variável Mensagem, 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=\"textoParaFalar\">Texto para fala:</label>
                <textarea name=\"textoParaFalar\" id=\"textoParaFalar\" rows=\"4\" required></textarea>
            </div>
        </div>

        <div>
            <div>
                <label for=\"narrador\">Narrador:</label>
                <select name=\"narrador\" id=\"narrador\" required>
                    @foreach (var narrador in Model.Narradores)
                    {
                        <option value=\"@narrador.Codigo\">@narrador.Nome (@narrador.Pais)</option>
                    }
                </select>
            </div>
        </div>
    </div>

    <br />
    <br />

    <div>
        <button type=\"submit\">Falar</button>
    </div>
</form>

@if (!string.IsNullOrWhiteSpace(Model.Mensagem))
{
    <div role=\"alert\">
        @Model.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 os campos de Texto e Narrador, necessários para a Conversão de Texto em Fala na Azure, sendo que ambos os campos são obrigatórios.

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

E, no final do formulário, há o botão para concluir a operação.

Ao final, caso a variável Mensagem possua alguma informação, uma alerta é exibido 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 de Conversão de Texto em 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 artigo sobre Serviços Cognitivos da Azure Face criamos um menu para todos os Serviços Cognitivos da categoria Visão, então, agora criaremos, logo abaixo dele, um menu para todos os Serviços Cognitivos da categoria Fala.

<li>
    <a href=\"#\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">
        Speech
    </a>
    <div aria-labelledby=\"navbarDropdownMenuLink\">
        <a asp-page=\"/Speech/TextToSpeech\">Texto para Fala</a>
    </div>
</li>

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 Texto para Fala

O arquivo inteiro pode ser visualizada no github.

Conclusão

Mudamos de categoria dentre os Serviços Cognitivos da Azure e, com isso, vemos que não é apenas tratamento de imagens os benefícios de se utilizar os Serviços.

Eles são ambos, fáceis de implementar, e altamente testados.

Com o Serviço de Conversão de Texto em Fala na Azure conseguimos, de forma rápida, uma aplicação que faz a conversão de qualquer texto colocado em diversos idiomas, com uma voz natural, com entonação e mais humana, o que pode ser ótimo em diversos cenários.

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

\"Estrutura-atual-do-projeto-conversao-texto-em-fala\"
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