Share via


L'app Express.js converte il testo in voce con Servizi cognitivi Voce

In questa esercitazione aggiungere Servizi cognitivi Voce a un'app Express.js esistente per aggiungere la conversione da testo a voce usando il servizio Voce di Servizi cognitivi. La conversione del testo in sintesi vocale consente di fornire audio senza il costo di generare manualmente l'audio.

Questa esercitazione illustra 3 modi diversi per convertire il testo nella voce da Servizi cognitivi di Azure:

  • Il client JavaScript ottiene direttamente l'audio
  • Il server JavaScript ottiene l'audio dal file (*.MP3)
  • Il server JavaScript ottiene l'audio dalla matrice in memoriaBuffer

Architettura dell'applicazione

L'esercitazione usa un'app Express.js minima e aggiunge funzionalità usando una combinazione di:

  • nuova route per l'API server per fornire la conversione dal testo al parlato, restituendo un flusso MP3
  • nuova route per un modulo HTML per consentire di immettere le informazioni
  • nuovo modulo HTML, con JavaScript, fornisce una chiamata lato client al servizio Voce

Questa applicazione fornisce tre diverse chiamate per convertire la voce in testo:

  • La prima chiamata al server crea un file nel server e quindi lo restituisce al client. In genere, è consigliabile usarlo per un testo o un testo più lungo che si sa che deve essere servito più volte.
  • La seconda chiamata al server è per testo a breve termine e viene mantenuta in memoria prima di tornare al client.
  • La chiamata client illustra una chiamata diretta al servizio Voce usando l'SDK. È possibile scegliere di effettuare questa chiamata se si dispone di un'applicazione solo client senza un server.

Prerequisiti

Scaricare il repository Express.js di esempio

  1. Usando git, clonare il repository di esempio Express.js nel computer locale.

    git clone https://github.com/Azure-Samples/js-e2e-express-server
    
  2. Passare alla nuova directory per l'esempio.

    cd js-e2e-express-server
    
  3. Aprire il progetto in Visual Studio Code.

    code .
    
  4. Aprire un nuovo terminale in Visual Studio Code e installare le dipendenze del progetto.

    npm install
    

Installare Speech SDK di Servizi cognitivi per JavaScript

Dal terminale di Visual Studio Code installare Speech SDK di Servizi cognitivi di Azure.

npm install microsoft-cognitiveservices-speech-sdk

Creare un modulo Voce per l'app Express.js

  1. Per integrare Speech SDK nell'applicazione Express.js, creare un file nella src cartella denominata azure-cognitiveservices-speech.js.

  2. Aggiungere il codice seguente per eseguire il pull delle dipendenze e creare una funzione per convertire il testo in voce.

    // 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
    };
    
    • Parametri: il file esegue il pull delle dipendenze per l'uso dell'SDK, dei flussi, dei buffer e del file system (fs). La textToSpeech funzione accetta quattro argomenti. Se viene inviato un nome file con percorso locale, il testo viene convertito in un file audio. Se non viene inviato un nome file, viene creato un flusso audio in memoria.
    • Metodo Speech SDK: il metodo speech SDK synr.speakTextAsync restituisce tipi diversi, in base alla configurazione ricevuta. Il metodo restituisce il risultato, che differisce in base a quanto richiesto dal metodo:
      • Crea file
      • Creare un flusso in memoria come matrice di buffer
    • Formato audio: il formato audio selezionato è MP3, ma esistono altri formati , insieme ad altri metodi di configurazione audio.

    Il metodo locale, textToSpeech, esegue il wrapping e converte la funzione callback dell'SDK in una promessa.

Creare una nuova route per l'app Express.js

  1. Apri il file src/server.js.

  2. Aggiungere il azure-cognitiveservices-speech.js modulo come dipendenza all'inizio del file:

    const { textToSpeech } = require('./azure-cognitiveservices-speech');
    
  3. Aggiungere una nuova route API per chiamare il metodo textToSpeech creato nella sezione precedente dell'esercitazione. Aggiungere questo codice dopo la /api/hello route.

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

    Questo metodo accetta i parametri obbligatori e facoltativi per il textToSpeech metodo dalla querystring. Se è necessario creare un file, viene sviluppato un nome file univoco. Il textToSpeech metodo viene chiamato in modo asincrono e invia tramite pipe il risultato all'oggetto risposta (res).

Aggiornare la pagina Web client con un modulo

Aggiornare la pagina Web HTML del client con un modulo che raccoglie i parametri necessari. Il parametro facoltativo viene passato in base al controllo audio selezionato dall'utente. Poiché questa esercitazione fornisce un meccanismo per chiamare il servizio Voce di Azure dal client, viene fornito anche JavaScript.

Aprire il file e sostituirne il /public/client.html contenuto con quanto segue:

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

Righe evidenziate nel file:

  • Riga 74: Azure Speech SDK viene inserito nella libreria client, usando il cdn.jsdelivr.net sito per recapitare il pacchetto NPM.
  • Riga 102: il updateSrc metodo aggiorna l'URL dei src controlli audio con la stringa di query, inclusa la chiave, l'area e il testo.
  • Riga 137: se un utente seleziona il Get directly from Azure pulsante, la pagina Web chiama direttamente azure dalla pagina client ed elabora il risultato.

Creare una risorsa Voce di Servizi cognitivi

Creare la risorsa Voce con i comandi dell'interfaccia della riga di comando di Azure in Azure Cloud Shell.

  1. Accedere ad Azure Cloud Shell. È quindi necessario eseguire l'autenticazione in un browser con l'account, che dispone dell'autorizzazione per una sottoscrizione di Azure valida.

  2. Creare un gruppo di risorse per la risorsa Voce.

    az group create \
        --location eastus \
        --name tutorial-resource-group-eastus
    
  3. Creare una risorsa Voce nel gruppo di risorse.

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

    Questo comando avrà esito negativo se è già stata creata solo la risorsa Voce gratuita.

  4. Usare il comando per ottenere i valori delle chiavi per la nuova risorsa Voce.

    az cognitiveservices account keys list \
        --name tutorial-speech \
        --resource-group tutorial-resource-group-eastus \
        --output table
    
  5. Copiare una delle chiavi.

    La chiave viene usata incollandola nel modulo Web dell'app Express per eseguire l'autenticazione al servizio Voce di Azure.

Eseguire l'app Express.js per convertire il testo in voce

  1. Avviare l'app con il comando bash seguente.

    npm start
    
  2. Aprire l'app Web in un browser.

    http://localhost:3000    
    
  3. Incollare la chiave vocale nella casella di testo evidenziata.

    Browser screenshot of web form with Speech key input field highlighted.

  4. Facoltativamente, modificare il testo in qualcosa di nuovo.

  5. Selezionare uno dei tre pulsanti per avviare la conversione nel formato audio:

    • Ottenere direttamente da Azure - Chiamata sul lato client ad Azure
    • Controllo audio per l'audio dal file
    • Controllo audio per l'audio dal buffer

    È possibile notare un piccolo ritardo tra la selezione del controllo e la riproduzione audio.

Creare un nuovo servizio app Azure in Visual Studio Code

  1. Dal riquadro comandi (CTRL+MAIUSC+P) digitare "crea web" e selezionare app Azure Servizio: Crea nuova app Web... Avanzate. Usare il comando Avanzate per avere il controllo completo sulla distribuzione, tra cui il gruppo di risorse, il piano di servizio app e il sistema operativo, invece di usare le impostazioni predefinite di Linux.

  2. Rispondere alle richieste come segue:

    • Selezionare l'account Sottoscrizione.
    • Per Immettere un nome univoco globale, ad esempio my-text-to-speech-app.
      • Immettere un nome univoco in tutto Azure. Usare solo caratteri alfanumerici ('A-Z', 'a-z' e '0-9') e trattini ('-')
    • Selezionare tutorial-resource-group-eastus per il gruppo di risorse.
    • Selezionare uno stack di runtime di una versione che include Node e LTS.
    • Selezionare il sistema operativo Linux.
    • Selezionare Crea un nuovo piano di servizio app, specificare un nome come my-text-to-speech-app-plan.
    • Selezionare il piano tariffario F1 gratuito. Se la sottoscrizione ha già un'app Web gratuita, selezionare il Basic livello .
    • Per la risorsa di Application Insight, selezionare Ignora per adesso.
    • Selezionare il eastus percorso.
  3. Dopo un breve periodo di tempo, Visual Studio Code notifica che la creazione è stata completata. Chiudere la notifica con il pulsante X .

Distribuire l'app Express.js locale nel servizio app remoto in Visual Studio Code

  1. Con l'app Web sul posto, distribuire il codice dal computer locale. Selezionare l'icona di Azure per aprire esplora servizi app Azure, espandere il nodo della sottoscrizione, fare clic con il pulsante destro del mouse sul nome dell'app Web appena creata e scegliere Distribuisci nell'app Web.

  2. Se sono presenti richieste di distribuzione, selezionare la cartella radice dell'app Express.js, selezionare di nuovo l'account di sottoscrizione e quindi selezionare il nome dell'app Web, my-text-to-speech-app, creato in precedenza.

  3. Se viene richiesto di eseguire npm install durante la distribuzione in Linux, selezionare se viene richiesto di aggiornare la configurazione per l'esecuzione npm install nel server di destinazione.

    Prompt to update configuration on the target Linux server

  4. Una volta completata la distribuzione, selezionare Esplora sito Web nel messaggio per visualizzare l'app Web appena distribuita.

  5. (Facoltativo): per aggiornare l'app Web, è possibile apportare modifiche ai file di codice, quindi usare l'estensione Distribuisci in app Web nell'estensione del servizio app Azure.

Trasmettere i log remoti del servizio in Visual Studio Code

Visualizzare l'output generato dall'app in esecuzione tramite chiamate a console.log. Questo output viene visualizzato nella finestra Output in Visual Studio Code.

  1. In Esplora servizi di app Azure fare clic con il pulsante destro del mouse sul nuovo nodo dell'app e scegliere Avvia streaming log.

     Starting Live Log Stream ---
     
  2. Aggiornare la pagina Web alcune volte nel browser per visualizzare altro output dei log.

Pulire le risorse rimuovendo il gruppo di risorse

Dopo aver completato questa esercitazione, è necessario rimuovere il gruppo di risorse, che include la risorsa, per assicurarsi che non vengano addebitate altre spese per l'utilizzo.

In Azure Cloud Shell usare il comando dell'interfaccia della riga di comando di Azure per eliminare il gruppo di risorse:

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

L'esecuzione del comando può richiedere alcuni minuti.

Passaggi successivi