Aplikacja Express.js konwertuje tekst na mowę za pomocą usługi Mowa w usługach Cognitive Services

W tym samouczku dodaj usługę Speech w usługach Cognitive Services do istniejącej aplikacji Express.js, aby dodać konwersję z tekstu na mowę przy użyciu usługi Mowa w usługach Cognitive Services. Konwertowanie tekstu na mowę umożliwia dostarczanie dźwięku bez konieczności ręcznego generowania dźwięku.

W tym samouczku przedstawiono 3 różne sposoby konwertowania tekstu na mowę z usługi Mowa w usługach Azure Cognitive Services:

  • Klient JavaScript pobiera dźwięk bezpośrednio
  • Skrypt JavaScript serwera pobiera dźwięk z pliku (*.MP3)
  • Skrypt JavaScript serwera pobiera dźwięk z tablicy w pamięciBuffer

Architektura aplikacji

Samouczek korzysta z minimalnej aplikacji Express.js i dodaje funkcje przy użyciu kombinacji:

  • nowa trasa dla interfejsu API serwera w celu zapewnienia konwersji z tekstu na mowę, zwracając strumień MP3
  • nowa trasa formularza HTML umożliwiająca wprowadzanie informacji
  • nowy formularz HTML z językiem JavaScript zapewnia wywołanie po stronie klienta do usługi Mowa

Ta aplikacja udostępnia trzy różne wywołania, aby przekonwertować mowę na tekst:

  • Pierwsze wywołanie serwera tworzy plik na serwerze, a następnie zwraca go do klienta. Zazwyczaj używa się tego dla dłuższego tekstu lub tekstu, który powinien być obsługiwany więcej niż raz.
  • Drugie wywołanie serwera dotyczy krótszego tekstu terminowego i jest przechowywane w pamięci przed zwróceniem do klienta.
  • Wywołanie klienta demonstruje bezpośrednie wywołanie usługi Mowa przy użyciu zestawu SDK. Możesz wykonać to wywołanie, jeśli masz aplikację tylko dla klienta bez serwera.

Wymagania wstępne

  • Node.js LTS — zainstalowany na komputerze lokalnym.
  • Visual Studio Code — zainstalowany na komputerze lokalnym.
  • Rozszerzenie usługi aplikacja systemu Azure dla programu VS Code (zainstalowane z poziomu programu VS Code).
  • Git — służy do wypychania do usługi GitHub — która aktywuje akcję GitHub.
  • Korzystanie z usługi Azure Cloud Shell przy użyciu powłoki bash Embed launch
  • Jeśli chcesz, zainstaluj interfejs wiersza polecenia platformy Azure, aby móc uruchamiać polecenia referencyjne interfejsu CLI.

Pobierz przykładowe repozytorium Express.js

  1. Za pomocą narzędzia git sklonuj przykładowe repozytorium Express.js na komputer lokalny.

    git clone https://github.com/Azure-Samples/js-e2e-express-server
    
  2. Przejdź do nowego katalogu dla przykładu.

    cd js-e2e-express-server
    
  3. Otwórz projekt w programie Visual Studio Code.

    code .
    
  4. Otwórz nowy terminal w programie Visual Studio Code i zainstaluj zależności projektu.

    npm install
    

Instalowanie zestawu SPEECH SDK usług Cognitive Services dla języka JavaScript

Z poziomu terminalu programu Visual Studio Code zainstaluj zestaw SDK usługi Mowa usług Azure Cognitive Services.

npm install microsoft-cognitiveservices-speech-sdk

Tworzenie modułu rozpoznawania mowy dla aplikacji Express.js

  1. Aby zintegrować zestaw SPEECH SDK z aplikacją Express.js, utwórz plik w src folderze o nazwie azure-cognitiveservices-speech.js.

  2. Dodaj następujący kod, aby ściągnąć zależności i utworzyć funkcję, aby przekonwertować tekst na mowę.

    // 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
    };
    
    • Parametry — plik pobiera zależności dotyczące używania zestawu SDK, strumieni, buforów i systemu plików (fs). Funkcja textToSpeech przyjmuje cztery argumenty. Jeśli zostanie wysłana nazwa pliku ze ścieżką lokalną, tekst zostanie przekonwertowany na plik audio. Jeśli nazwa pliku nie zostanie wysłana, zostanie utworzony strumień audio w pamięci.
    • Metoda zestawu SPEECH SDK — metoda zestawu SPEECH SDK syntetyzator.speakTextAsync zwraca różne typy na podstawie odbieranej konfiguracji. Metoda zwraca wynik, który różni się w zależności od tego, co metoda została poproszona o zrobienie:
      • Utwórz plik
      • Tworzenie strumienia w pamięci jako tablicy buforów
    • Format audio — wybrany format audio to MP3, ale istnieją inne formaty wraz z innymi metodami konfiguracji audio.

    Metoda lokalna , textToSpeechopakowuje i konwertuje funkcję wywołania zwrotnego zestawu SDK na obietnicę.

Tworzenie nowej trasy dla aplikacji Express.js

  1. Otwórz plik src/server.js.

  2. azure-cognitiveservices-speech.js Dodaj moduł jako zależność w górnej części pliku:

    const { textToSpeech } = require('./azure-cognitiveservices-speech');
    
  3. Dodaj nową trasę interfejsu API, aby wywołać metodę textToSpeech utworzoną w poprzedniej sekcji samouczka. Dodaj ten kod po /api/hello trasie.

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

    Ta metoda pobiera wymagane i opcjonalne parametry metody textToSpeech z ciągu zapytania. Jeśli należy utworzyć plik, zostanie opracowana unikatowa nazwa pliku. Metoda textToSpeech jest wywoływana asynchronicznie i potokuje wynik do obiektu odpowiedzi (res).

Aktualizowanie strony internetowej klienta przy użyciu formularza

Zaktualizuj stronę internetową HTML klienta przy użyciu formularza, który zbiera wymagane parametry. Opcjonalny parametr jest przekazywany w oparciu o to, która kontrolka audio wybiera użytkownika. Ponieważ ten samouczek zawiera mechanizm wywoływania usługi Azure Speech z klienta, zapewnia również język JavaScript.

/public/client.html Otwórz plik i zastąp jego zawartość następującym kodem:

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

Wyróżnione wiersze w pliku:

  • Wiersz 74: Zestaw SDK usługi Azure Speech jest pobierany do biblioteki klienta przy użyciu cdn.jsdelivr.net witryny w celu dostarczenia pakietu NPM.
  • Wiersz 102: updateSrc Metoda aktualizuje adres URL kontrolek src audio za pomocą ciągu zapytania, w tym klucza, regionu i tekstu.
  • Wiersz 137: Jeśli użytkownik wybierze Get directly from Azure przycisk, strona internetowa wywołuje bezpośrednio na platformie Azure ze strony klienta i przetwarza wynik.

Tworzenie zasobu usługi Mowa w usługach Cognitive Services

Utwórz zasób usługi Mowa za pomocą poleceń interfejsu wiersza polecenia platformy Azure w usłudze Azure Cloud Shell.

  1. Zaloguj się do usługi Azure Cloud Shell. Wymaga to uwierzytelnienia w przeglądarce przy użyciu konta, które ma uprawnienia do prawidłowej subskrypcji platformy Azure.

  2. Utwórz grupę zasobów dla zasobu usługi Mowa.

    az group create \
        --location eastus \
        --name tutorial-resource-group-eastus
    
  3. Utwórz zasób usługi Mowa w grupie zasobów.

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

    To polecenie zakończy się niepowodzeniem, jeśli został już utworzony jedyny zasób bezpłatnej mowy.

  4. Użyj polecenia , aby uzyskać wartości klucza dla nowego zasobu usługi Mowa.

    az cognitiveservices account keys list \
        --name tutorial-speech \
        --resource-group tutorial-resource-group-eastus \
        --output table
    
  5. Skopiuj jeden z kluczy.

    Klucz jest używany przez wklejanie go do formularza internetowego aplikacji Express w celu uwierzytelnienia w usłudze Azure Speech.

Uruchamianie aplikacji Express.js w celu przekonwertowania tekstu na mowę

  1. Uruchom aplikację za pomocą następującego polecenia powłoki bash.

    npm start
    
  2. Otwórz aplikację internetową w przeglądarce.

    http://localhost:3000    
    
  3. Wklej klucz mowy w wyróżnionym polu tekstowym.

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

  4. Opcjonalnie zmień tekst na nowy.

  5. Wybierz jeden z trzech przycisków, aby rozpocząć konwersję na format audio:

    • Uzyskiwanie bezpośrednio z platformy Azure — wywołanie po stronie klienta na platformę Azure
    • Kontrolka audio dla dźwięku z pliku
    • Sterowanie dźwiękem dźwięku z buforu

    Może wystąpić niewielkie opóźnienie między wybraniem kontrolki a odtwarzaniem dźwięku.

Tworzenie nowej usługi aplikacja systemu Azure w programie Visual Studio Code

  1. Z palety poleceń (Ctrl+Shift+P) wpisz "create web" (Utwórz internet) i wybierz pozycję aplikacja systemu Azure Service: Create New Web App... (Utwórz nową aplikację internetową... Zaawansowane. Za pomocą zaawansowanego polecenia możesz mieć pełną kontrolę nad wdrożeniem, w tym grupą zasobów, planem usługi App Service i systemem operacyjnym, a nie domyślnymi ustawieniami systemu Linux.

  2. Odpowiedz na monity w następujący sposób:

    • Wybierz konto subskrypcji .
    • W polu Wprowadź globalnie unikatową nazwę , taką jak my-text-to-speech-app.
      • Wprowadź unikatową nazwę na całej platformie Azure. Używaj tylko znaków alfanumerycznych ('A-Z', 'a-z' i '0-9') i łączników ('-')
    • Wybierz tutorial-resource-group-eastus grupę zasobów.
    • Wybierz stos środowiska uruchomieniowego wersji, w tym Node i LTS.
    • Wybierz system operacyjny Linux.
    • Wybierz pozycję Utwórz nowy plan usługi App Service, podaj nazwę, taką jak my-text-to-speech-app-plan.
    • Wybierz bezpłatną warstwę cenową F1. Jeśli Twoja subskrypcja ma już bezpłatną aplikację internetową, wybierz warstwę Basic .
    • Wybierz pozycję Pomiń teraz dla zasobu Application Szczegółowe informacje.
    • Wybierz lokalizację eastus .
  3. Po krótkim czasie program Visual Studio Code powiadamia o zakończeniu tworzenia. Zamknij powiadomienie za pomocą przycisku X .

Wdrażanie lokalnej aplikacji Express.js w zdalnej usłudze App Service w programie Visual Studio Code

  1. Po wdrożeniu aplikacji internetowej wdróż kod z komputera lokalnego. Wybierz ikonę platformy Azure, aby otworzyć eksploratora usługi aplikacja systemu Azure, rozwiń węzeł subskrypcji, kliknij prawym przyciskiem myszy nazwę właśnie utworzonej aplikacji internetowej i wybierz polecenie Wdróż w aplikacji internetowej.

  2. Jeśli pojawi się monit o wdrożenie, wybierz folder główny aplikacji Express.js, ponownie wybierz konto subskrypcji , a następnie wybierz nazwę aplikacji internetowej , my-text-to-speech-apputworzoną wcześniej.

  3. Jeśli zostanie wyświetlony monit o uruchomienie npm install podczas wdrażania w systemie Linux, wybierz pozycję Tak , jeśli zostanie wyświetlony monit o zaktualizowanie konfiguracji do uruchomienia npm install na serwerze docelowym.

    Prompt to update configuration on the target Linux server

  4. Po zakończeniu wdrażania wybierz pozycję Przeglądaj witrynę internetową w wierszu polecenia, aby wyświetlić nowo wdrożoną aplikację internetową.

  5. (Opcjonalnie): Możesz wprowadzić zmiany w plikach kodu, a następnie użyć polecenia Deploy to Web App (Wdróż w aplikacji internetowej) w rozszerzeniu usługi aplikacja systemu Azure, aby zaktualizować aplikację internetową.

Przesyłanie strumieniowe dzienników usługi zdalnej w programie Visual Studio Code

Wyświetl (ogon) dowolne dane wyjściowe generowane przez uruchomioną aplikację za pomocą wywołań do elementu console.log. Te dane wyjściowe są wyświetlane w oknie Dane wyjściowe w programie Visual Studio Code.

  1. W eksploratorze usługi aplikacja systemu Azure kliknij prawym przyciskiem myszy nowy węzeł aplikacji i wybierz polecenie Uruchom dzienniki przesyłania strumieniowego.

     Starting Live Log Stream ---
     
  2. Odśwież stronę internetową kilka razy w przeglądarce, aby wyświetlić dodatkowe dane wyjściowe dziennika.

Czyszczenie zasobów przez usunięcie grupy zasobów

Po ukończeniu tego samouczka musisz usunąć grupę zasobów, która zawiera zasób, aby upewnić się, że nie są naliczane opłaty za więcej użycia.

W usłudze Azure Cloud Shell użyj polecenia interfejsu wiersza polecenia platformy Azure, aby usunąć grupę zasobów:

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

To polecenie może potrwać kilka minut.

Następne kroki