Partilhar via


Express.js aplicativo converte texto em fala com o Azure AI Speech

Neste tutorial, adicione o Azure AI Speech a um aplicativo Express.js existente para adicionar conversão de texto em fala usando o serviço Azure AI Speech. A conversão de texto em fala permite que você forneça áudio sem o custo de gerar manualmente o áudio.

Este tutorial mostra 3 maneiras diferentes de converter texto em fala do Azure AI Speech:

  • O JavaScript do cliente obtém áudio diretamente
  • O JavaScript do servidor obtém áudio do arquivo (*.MP3)
  • O JavaScript do servidor obtém áudio de arrayBuffer na memória

Arquitetura da aplicação

O tutorial usa um aplicativo de Express.js mínimo e adiciona funcionalidade usando uma combinação de:

  • nova rota para a API do servidor fornecer conversão de texto para fala, retornando um fluxo MP3
  • nova rota para um formulário HTML para permitir que você insira suas informações
  • novo formulário HTML, com JavaScript, fornece uma chamada do lado do cliente para o serviço de fala

Esta aplicação fornece três chamadas diferentes para converter fala em texto:

  • A primeira chamada do servidor cria um arquivo no servidor e o retorna ao cliente. Normalmente, você usaria isso para texto mais longo ou texto que você sabe que deve ser servido mais de uma vez.
  • A segunda chamada do servidor é para texto de curto prazo e é mantida na memória antes de retornar ao cliente.
  • A chamada de cliente demonstra uma chamada direta para o serviço de fala usando o SDK. Você pode optar por fazer essa chamada se tiver um aplicativo somente cliente sem um servidor.

Pré-requisitos

  • Node.js LTS - instalado na sua máquina local.

  • Visual Studio Code - instalado em sua máquina local.

  • A extensão do Serviço de Aplicativo do Azure para VS Code (instalada de dentro do VS Code).

  • Git - usado para enviar por push para o GitHub - que ativa a ação do GitHub.

  • Usar o Azure Cloud Shell usando o bash

    Lançamento incorporado

  • Se preferir, instale o CLI do Azure para executar comandos de referência de CLI.

    • Se estiver a utilizar uma instalação local, inicie sessão com o CLI do Azure ao utilizar o comando az login. Para concluir o processo de autenticação, siga os passos apresentados no seu terminal. Consulte Entrar com a CLI do Azure para obter mais opções de entrada.
    • Quando lhe for pedido, instale as extensões do CLI do Azure durante a primeira utilização. Para obter mais informações sobre as extensões, veja Utilizar extensões com o CLI do Azure.
    • Execute o comando az version para localizar a versão e as bibliotecas dependentes instaladas. Para atualizar para a versão mais recente, execute o comando az upgrade.

Download de exemplo Express.js repositório

  1. Usando o git, clone o repositório de amostra Express.js para o computador local.

    git clone https://github.com/Azure-Samples/js-e2e-express-server
    
  2. Mude para o novo diretório para o exemplo.

    cd js-e2e-express-server
    
  3. Abra o projeto no Visual Studio Code.

    code .
    
  4. Abra um novo terminal no Visual Studio Code e instale as dependências do projeto.

    npm install
    

Instalar o SDK de Fala do Azure AI para JavaScript

No terminal do Visual Studio Code, instale o SDK de Fala do Azure AI.

npm install microsoft-cognitiveservices-speech-sdk

Criar um módulo de Fala para o aplicativo Express.js

  1. Para integrar o SDK de fala no aplicativo Express.js, crie um arquivo na src pasta chamada azure-cognitiveservices-speech.js.

  2. Adicione o código a seguir para puxar dependências e criar uma função para converter texto em fala.

    // azure-cognitiveservices-speech.js
    
    const sdk = require('microsoft-cognitiveservices-speech-sdk');
    const { Buffer } = require('buffer');
    const { PassThrough } = require('stream');
    const fs = require('fs');
    
    /**
     * Node.js server code to convert text to speech
     * @returns stream
     * @param {*} key your resource key
     * @param {*} region your resource region
     * @param {*} text text to convert to audio/speech
     * @param {*} filename optional - best for long text - temp file for converted speech/audio
     */
    const textToSpeech = async (key, region, text, filename)=> {
        
        // convert callback function to promise
        return new Promise((resolve, reject) => {
            
            const speechConfig = sdk.SpeechConfig.fromSubscription(key, region);
            speechConfig.speechSynthesisOutputFormat = 5; // mp3
            
            let audioConfig = null;
            
            if (filename) {
                audioConfig = sdk.AudioConfig.fromAudioFileOutput(filename);
            }
            
            const synthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig);
    
            synthesizer.speakTextAsync(
                text,
                result => {
                    
                    const { audioData } = result;
    
                    synthesizer.close();
                    
                    if (filename) {
                        
                        // return stream from file
                        const audioFile = fs.createReadStream(filename);
                        resolve(audioFile);
                        
                    } else {
                        
                        // return stream from memory
                        const bufferStream = new PassThrough();
                        bufferStream.end(Buffer.from(audioData));
                        resolve(bufferStream);
                    }
                },
                error => {
                    synthesizer.close();
                    reject(error);
                }); 
        });
    };
    
    module.exports = {
        textToSpeech
    };
    
    • Parâmetros - O arquivo obtém as dependências para usar o SDK, fluxos, buffers e o sistema de arquivos (fs). A textToSpeech função usa quatro argumentos. Se um nome de arquivo com caminho local for enviado, o texto será convertido em um arquivo de áudio. Se um nome de arquivo não for enviado, um fluxo de áudio na memória será criado.
    • Método Speech SDK - O método Speech SDK synthesizer.speakTextAsync retorna diferentes tipos, com base na configuração que recebe. O método retorna o resultado, que difere com base no que o método foi solicitado a fazer:
      • Criar ficheiro
      • Criar fluxo na memória como uma matriz de buffers
    • Formato de áudio - O formato de áudio selecionado é MP3, mas existem outros formatos , juntamente com outros métodos de configuração de áudio.

    O método local, textToSpeech, encapsula e converte a função de retorno de chamada do SDK em uma promessa.

Criar uma nova rota para o aplicativo Express.js

  1. Abra o ficheiro src/server.js.

  2. Adicione o azure-cognitiveservices-speech.js módulo como uma dependência na parte superior do arquivo:

    const { textToSpeech } = require('./azure-cognitiveservices-speech');
    
  3. Adicione uma nova rota de API para chamar o método textToSpeech criado na seção anterior do tutorial. Adicione este código após a /api/hello rota.

    // creates a temp file on server, the streams to client
    /* eslint-disable no-unused-vars */
    app.get('/text-to-speech', async (req, res, next) => {
        
        const { key, region, phrase, file } = req.query;
        
        if (!key || !region || !phrase) res.status(404).send('Invalid query string');
        
        let fileName = null;
        
        // stream from file or memory
        if (file && file === true) {
            fileName = `./temp/stream-from-file-${timeStamp()}.mp3`;
        }
        
        const audioStream = await textToSpeech(key, region, phrase, fileName);
        res.set({
            'Content-Type': 'audio/mpeg',
            'Transfer-Encoding': 'chunked'
        });
        audioStream.pipe(res);
    });
    

    Esse método usa os parâmetros necessários e opcionais para o textToSpeech método da querystring. Se um arquivo precisar ser criado, um nome de arquivo exclusivo será desenvolvido. O textToSpeech método é chamado de forma assíncrona e canaliza o resultado para o objeto response (res).

Atualizar a página da Web do cliente com um formulário

Atualize a página da Web HTML do cliente com um formulário que coleta os parâmetros necessários. O parâmetro opcional é passado com base em qual controle de áudio o usuário seleciona. Como este tutorial fornece um mecanismo para chamar o serviço de Fala do Azure do cliente, esse JavaScript também é fornecido.

Abra o ficheiro e substitua o /public/client.html seu conteúdo pelo seguinte:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>Microsoft Cognitive Services Demo</title>
  <meta charset="utf-8" />
</head>

<body>

  <div id="content" style="display:none">
    <h1 style="font-weight:500;">Microsoft Cognitive Services Speech </h1>
    <h2>npm: microsoft-cognitiveservices-speech-sdk</h2>
    <table width="100%">
      <tr>
        <td></td>
        <td>
          <a href="https://docs.microsoft.com/azure/cognitive-services/speech-service/get-started" target="_blank">Azure
            Cognitive Services Speech Documentation</a>
        </td>
      </tr>
      <tr>
        <td align="right">Your Speech Resource Key</td>
        <td>

          <input id="resourceKey" type="text" size="40" placeholder="Your resource key (32 characters)" value=""
            onblur="updateSrc()">

      </tr>
      <tr>
        <td align="right">Your Speech Resource region</td>
        <td>
          <input id="resourceRegion" type="text" size="40" placeholder="Your resource region" value="eastus"
            onblur="updateSrc()">

        </td>
      </tr>
      <tr>
        <td align="right" valign="top">Input Text (max 255 char)</td>
        <td><textarea id="phraseDiv" style="display: inline-block;width:500px;height:50px" maxlength="255"
            onblur="updateSrc()">all good men must come to the aid</textarea></td>
      </tr>
      <tr>
        <td align="right">
          Stream directly from Azure Cognitive Services
        </td>
        <td>
          <div>
            <button id="clientAudioAzure" onclick="getSpeechFromAzure()">Get directly from Azure</button>
          </div>
        </td>
      </tr>

      <tr>
        <td align="right">
          Stream audio from file on server</td>
        <td>
          <audio id="serverAudioFile" controls preload="none" onerror="DisplayError()">
          </audio>
        </td>
      </tr>

      <tr>
        <td align="right">Stream audio from buffer on server</td>
        <td>
          <audio id="serverAudioStream" controls preload="none" onerror="DisplayError()">
          </audio>
        </td>
      </tr>
    </table>
  </div>

  <!-- Speech SDK reference sdk. -->
  <script
    src="https://cdn.jsdelivr.net/npm/microsoft-cognitiveservices-speech-sdk@latest/distrib/browser/microsoft.cognitiveservices.speech.sdk.bundle-min.js">
    </script>

  <!-- Speech SDK USAGE -->
  <script>
    // status fields and start button in UI
    var phraseDiv;
    var resultDiv;

    // subscription key and region for speech services.
    var resourceKey = null;
    var resourceRegion = "eastus";
    var authorizationToken;
    var SpeechSDK;
    var synthesizer;

    var phrase = "all good men must come to the aid"
    var queryString = null;

    var audioType = "audio/mpeg";
    var serverSrc = "/text-to-speech";

    document.getElementById('serverAudioStream').disabled = true;
    document.getElementById('serverAudioFile').disabled = true;
    document.getElementById('clientAudioAzure').disabled = true;

    // update src URL query string for Express.js server
    function updateSrc() {

      // input values
      resourceKey = document.getElementById('resourceKey').value.trim();
      resourceRegion = document.getElementById('resourceRegion').value.trim();
      phrase = document.getElementById('phraseDiv').value.trim();

      // server control - by file
      var serverAudioFileControl = document.getElementById('serverAudioFile');
      queryString += `%file=true`;
      const fileQueryString = `file=true&region=${resourceRegion}&key=${resourceKey}&phrase=${phrase}`;
      serverAudioFileControl.src = `${serverSrc}?${fileQueryString}`;
      console.log(serverAudioFileControl.src)
      serverAudioFileControl.type = "audio/mpeg";
      serverAudioFileControl.disabled = false;

      // server control - by stream
      var serverAudioStreamControl = document.getElementById('serverAudioStream');
      const streamQueryString = `region=${resourceRegion}&key=${resourceKey}&phrase=${phrase}`;
      serverAudioStreamControl.src = `${serverSrc}?${streamQueryString}`;
      console.log(serverAudioStreamControl.src)
      serverAudioStreamControl.type = "audio/mpeg";
      serverAudioStreamControl.disabled = false;

      // client control
      var clientAudioAzureControl = document.getElementById('clientAudioAzure');
      clientAudioAzureControl.disabled = false;

    }

    function DisplayError(error) {
      window.alert(JSON.stringify(error));
    }

    // Client-side request directly to Azure Cognitive Services
    function getSpeechFromAzure() {

      // authorization for Speech service
      var speechConfig = SpeechSDK.SpeechConfig.fromSubscription(resourceKey, resourceRegion);

      // new Speech object
      synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig);

      synthesizer.speakTextAsync(
        phrase,
        function (result) {

          // Success function

          // display status
          if (result.reason === SpeechSDK.ResultReason.SynthesizingAudioCompleted) {

            // load client-side audio control from Azure response
            audioElement = document.getElementById("clientAudioAzure");
            const blob = new Blob([result.audioData], { type: "audio/mpeg" });
            const url = window.URL.createObjectURL(blob);

          } else if (result.reason === SpeechSDK.ResultReason.Canceled) {
            // display Error
            throw (result.errorDetails);
          }

          // clean up
          synthesizer.close();
          synthesizer = undefined;
        },
        function (err) {

          // Error function
          throw (err);
          audioElement = document.getElementById("audioControl");
          audioElement.disabled = true;

          // clean up
          synthesizer.close();
          synthesizer = undefined;
        });

    }

    // Initialization
    document.addEventListener("DOMContentLoaded", function () {

      var clientAudioAzureControl = document.getElementById("clientAudioAzure");
      var resultDiv = document.getElementById("resultDiv");

      resourceKey = document.getElementById('resourceKey').value;
      resourceRegion = document.getElementById('resourceRegion').value;
      phrase = document.getElementById('phraseDiv').value;
      if (!!window.SpeechSDK) {
        SpeechSDK = window.SpeechSDK;
        clientAudioAzure.disabled = false;

        document.getElementById('content').style.display = 'block';
      }
    });

  </script>
</body>

</html>

Linhas realçadas no ficheiro:

  • Linha 74: O SDK de Fala do Azure é puxado para a biblioteca do cliente, usando o cdn.jsdelivr.net site para entregar o pacote NPM.
  • Linha 102: O updateSrc método atualiza a URL dos src controles de áudio com a cadeia de caracteres de consulta, incluindo a chave, a região e o texto.
  • Linha 137: Se um usuário selecionar o Get directly from Azure botão, a página da Web chamará diretamente para o Azure a partir da página do cliente e processará o resultado.

Criar um recurso de Fala do Azure AI

Crie o recurso de Fala com comandos da CLI do Azure em um Azure Cloud Shell.

  1. Faça logon no Azure Cloud Shell. Isso requer que você se autentique em um navegador com sua conta, que tem permissão em uma Assinatura válida do Azure.

  2. Crie um grupo de recursos para o recurso de Fala.

    az group create \
        --location eastus \
        --name tutorial-resource-group-eastus
    
  3. Crie um recurso de Fala no grupo de recursos.

    az cognitiveservices account create \
        --kind SpeechServices \
        --location eastus \
        --name tutorial-speech \
        --resource-group tutorial-resource-group-eastus \
        --sku F0
    

    Este comando falhará se o seu único recurso de liberdade de expressão já tiver sido criado.

  4. Use o comando para obter os valores-chave para o novo recurso de fala.

    az cognitiveservices account keys list \
        --name tutorial-speech \
        --resource-group tutorial-resource-group-eastus \
        --output table
    
  5. Copie uma das chaves.

    Use a chave colando-a no formulário da Web do aplicativo Express para autenticar no serviço de Fala do Azure.

Execute o aplicativo Express.js para converter texto em fala

  1. Inicie o aplicativo com o seguinte comando bash.

    npm start
    
  2. Abra o aplicativo Web em um navegador.

    http://localhost:3000    
    
  3. Cole a tecla Fala na caixa de texto realçada.

    Captura de tela do navegador do formulário da Web com o campo de entrada de tecla de fala realçado.

  4. Opcionalmente, altere o texto para algo novo.

  5. Selecione um dos três botões para iniciar a conversão para o formato de áudio:

    • Obter diretamente do Azure - chamada do lado do cliente para o Azure
    • Controle de áudio para áudio de arquivo
    • Controle de áudio para áudio do buffer

    Você pode notar um pequeno atraso entre a seleção do controle e a reprodução de áudio.

Criar novo serviço de Aplicativo do Azure no Visual Studio Code

  1. Na paleta de comandos (Ctrl+Shift+P), digite "create web" e selecione Azure App Service: Create New Web App... Avançado. Você usa o comando avançado para ter controle total sobre a implantação, incluindo grupo de recursos, Plano de Serviço de Aplicativo e sistema operacional, em vez de usar os padrões do Linux.

  2. Responda às solicitações da seguinte maneira:

    • Selecione a sua conta de Subscrição .
    • Para Insira um nome globalmente exclusivo como my-text-to-speech-app.
      • Insira um nome exclusivo em todo o Azure. Utilizar apenas carateres alfanuméricos («A-Z», «a-z» e «0-9») e hífenes («-»)
    • Selecione tutorial-resource-group-eastus para o grupo de recursos.
    • Selecione uma pilha de tempo de execução de uma versão que inclua Node e LTS.
    • Selecione o sistema operacional Linux.
    • Selecione Criar um novo plano do Serviço de Aplicativo, forneça um nome como my-text-to-speech-app-plan.
    • Selecione o nível de preço gratuito da F1. Se a sua subscrição já tiver uma aplicação Web gratuita, selecione o Basic nível.
    • Selecione Ignorar por enquanto para o recurso do Application Insights.
    • Selecione o eastus local.
  3. Após um curto período de tempo, o Visual Studio Code notifica que a criação foi concluída. Feche a notificação com o botão X .

Implantar aplicativo Express.js local no serviço de aplicativo remoto no Visual Studio Code

  1. Com o aplicativo Web instalado, implante seu código a partir do computador local. Selecione o ícone do Azure para abrir o explorador do Serviço de Aplicativo do Azure, expanda o nó de assinatura, clique com o botão direito do mouse no nome do aplicativo Web que você acabou de criar e selecione Implantar no Aplicativo Web.

  2. Se houver prompts de implantação, selecione a pasta raiz do aplicativo Express.js, selecione sua conta de assinatura novamente e, em seguida, selecione o nome do aplicativo Web, my-text-to-speech-appcriado anteriormente.

  3. Se for solicitado a executar npm install durante a implantação no Linux, selecione Sim se for solicitado a atualizar sua configuração para ser executada npm install no servidor de destino.

    Prompt para atualizar a configuração no servidor Linux de destino

  4. Quando a implantação estiver concluída, selecione Procurar site no prompt para exibir seu aplicativo Web recém-implantado.

  5. (Opcional): você pode fazer alterações em seus arquivos de código e, em seguida, usar a opção Implantar no Aplicativo Web, na extensão de serviço do Aplicativo do Azure, para atualizar o aplicativo Web.

Transmitir logs de serviço remoto no Visual Studio Code

Visualize (cauda) qualquer saída que o aplicativo em execução gera por meio de chamadas para console.log. Essa saída aparece na janela Saída no Visual Studio Code.

  1. No explorador do Serviço de Aplicativo do Azure, clique com o botão direito do mouse no novo nó do aplicativo e escolha Iniciar Logs de Streaming.

     Starting Live Log Stream ---
     
  2. Atualize a página da Web algumas vezes no navegador para ver a saída de log adicional.

Limpar recursos removendo o grupo de recursos

Depois de concluir este tutorial, você precisa remover o grupo de recursos, que inclui o recurso, para garantir que você não seja cobrado por mais uso.

No Azure Cloud Shell, use o comando Azure CLI para excluir o grupo de recursos:

az group delete --name tutorial-resource-group-eastus  -y

Este comando pode demorar alguns minutos.

Próximos passos