Приложение Express.js преобразует текст в речь с помощью службы "Речь" из Cognitive Services
В этом руководстве описано, как добавить службу "Речь" из Cognitive Services в существующее приложение Express.js, чтобы реализовать в нем преобразование из текста в речь с помощью этой службы. Преобразование текста в речь позволяет выводить аудио без затрат на его генерирование вручную.
В этом руководстве приведено три разных способа преобразования текста в речь с помощью службы "Речь" из Azure Cognitive Services:
- Клиент JavaScript получает аудио напрямую.
- Серверный код JavaScript получает аудио из файла (*.MP3).
- Серверный код JavaScript получает аудио из arrayBuffer в памяти.
Архитектура приложения
В этом руководстве описано, как создать простое приложение Express.js и добавить функциональные возможности с помощью таких сочетаний:
- новый маршрут для API сервера для преобразования текста в речь с результирующим потоком в формате MP3;
- новый маршрут для HTML-формы, позволяющей ввести данные;
- новая HTML-форма с JavaScript, обеспечивающая вызов к службе "Речь" на стороне клиента.
Это приложение предоставляет три разных вызова для преобразования текста в речь:
- Первый вызов сервера создает файл на сервере и возвращает его клиенту. Обычно этот вызов используется для более длинного текста или текста, который нужно озвучить более одного раза.
- Второй вызов сервера предназначен для краткосрочного текста и хранится в памяти, прежде чем вернуться клиенту.
- Вызов клиента демонстрирует прямой вызов к службе "Речь" с использованием пакета SDK. Этот вызов подходит в тех случаях, если у вас есть клиентское приложение без сервера.
Необходимые компоненты
- Node.js LTS — установлен на локальный компьютер.
- Установите на локальный компьютер Visual Studio Code.
- Расширение Службы приложений Azure для VS Code (установленное в VS Code).
- Средство Git для отправки данных в GitHub, по которым активируется действие GitHub.
- Использование Azure Cloud Shell с помощью bash
- При необходимости установите Azure CLI, чтобы выполнять справочные команды CLI.
- Если вы используете локальную установку, выполните вход с помощью команды Azure CLI az login. Чтобы выполнить аутентификацию, следуйте инструкциям в окне терминала. Сведения о дополнительных вариантах входа см. в статье Вход с помощью Azure CLI.
- Если появится запрос, установите расширения Azure CLI при первом использовании. Дополнительные сведения о расширениях см. в статье Использование расширений с Azure CLI.
- Выполните команду az version, чтобы узнать установленную версию и зависимые библиотеки. Чтобы обновиться до последней версии, выполните команду az upgrade.
Скачивание примера репозитория Express.js
С помощью Git клонируйте пример репозитория Express.js на локальный компьютер.
git clone https://github.com/Azure-Samples/js-e2e-express-server
Перейдите в новый каталог для примера.
cd js-e2e-express-server
Откройте проект в Visual Studio Code.
code .
Откройте новый терминал в Visual Studio Code и установите зависимости проекта.
npm install
Установка пакета SDK службы "Речь" из Cognitive Services для JavaScript
В терминале Visual Studio Code установите пакет SDK службы "Речь" из Azure Cognitive Services.
npm install microsoft-cognitiveservices-speech-sdk
Создание модуля службы "Речь" для приложения Express.js
Чтобы интегрировать пакет SDK службы "Речь" с приложением Express.js, создайте файл
azure-cognitiveservices-speech.js
в папкеsrc
.Добавьте следующий код для извлечения зависимостей и создайте функцию для преобразования текста в речь.
// 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 };
- Параметры — файл извлекает зависимости для использования пакета SDK, потоков, буферов и файловой системы. Функция
textToSpeech
принимает четыре аргумента. Если отправляется имя файла с локальным путем, текст преобразуется в звуковой файл. Если имя файла не отправляется, создается аудиопоток в памяти. - Метод в пакете SDK службы "Речь" — метод synthesizer.speakTextAsync возвращает различные типы в зависимости от полученной конфигурации.
Метод возвращает результат, который отличается в зависимости от того, какой метод был предложено сделать:
- Создать файл
- Создать поток в памяти в виде массива буферов.
- Формат аудио — для аудио выбран формат MP3, но существуют и другие форматы, а также другие методы настройки аудио.
Локальный метод
textToSpeech
упаковывает и преобразует функцию обратного вызова пакета SDK в обещание.- Параметры — файл извлекает зависимости для использования пакета SDK, потоков, буферов и файловой системы. Функция
Создание нового маршрута для приложения Express.js
Откройте файл
src/server.js
.Добавьте модуль
azure-cognitiveservices-speech.js
в качестве зависимости в начале файла:const { textToSpeech } = require('./azure-cognitiveservices-speech');
Добавьте новый маршрут API для вызова метода textToSpeech, создание которого описано в предыдущем разделе руководства. Добавьте этот код после
/api/hello
маршрута.// 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); });
Этот метод принимает обязательные и необязательные параметры для метода
textToSpeech
из строки запроса. Если требуется создать файл, генерируется уникальное имя файла. МетодtextToSpeech
вызывается асинхронно и передает результат в объект ответа (res
).
Обновление веб-страницы клиента с помощью формы
Обновите веб-страницу клиента в формате HTML с помощью формы, которая собирает обязательные параметры. Необязательный параметр передается в зависимости от того, какой элемент управления звуком выбрал пользователь. Поскольку в этом руководстве предоставляется механизм для вызова службы "Речь" Azure из клиента, также предоставляется код JavaScript.
Откройте файл /public/client.html
и замените имеющееся содержимое следующим кодом:
<!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®ion=${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>
Выделенные строки в файле:
- Строка 74. Пакет SDK службы "Речь Azure" извлекается в клиентную библиотеку, используя
cdn.jsdelivr.net
сайт для доставки пакета NPM. - Строка 102. Метод
updateSrc
обновляет URL-адрес элементов управленияsrc
звуком с помощью строки запроса, включая ключ, регион и текст. - Строка 137. Если пользователь выбирает
Get directly from Azure
кнопку, веб-страница вызывается непосредственно в Azure с клиентской страницы и обрабатывает результат.
Создание ресурса службы "Речь" из Cognitive Services
Создайте ресурс службы "Речь" с помощью команд Azure CLI в Azure Cloud Shell.
Войдите в Azure Cloud Shell. Для этого необходимо пройти аутентификацию в браузере с учетной записью, имеющей разрешение на действительную подписку Azure.
Создайте группу ресурсов для ресурса службы "Речь".
az group create \ --location eastus \ --name tutorial-resource-group-eastus
Создайте ресурс службы "Речь" в группе ресурсов.
az cognitiveservices account create \ --kind SpeechServices \ --location eastus \ --name tutorial-speech \ --resource-group tutorial-resource-group-eastus \ --sku F0
Эта команда завершится ошибкой, если ваш бесплатный ресурс службы "Речь" уже создан.
Используйте команду, чтобы получить значения ключей для нового ресурса службы "Речь".
az cognitiveservices account keys list \ --name tutorial-speech \ --resource-group tutorial-resource-group-eastus \ --output table
Скопируйте один из ключей.
Ключ можно использовать, вставив его в веб-форму приложения Express для аутентификации в службе Azure "Речь".
Запуск приложения Express.js для преобразования текста в речь
Запустите приложение с помощью следующей команды Bash.
npm start
Откройте веб-приложение в браузере.
http://localhost:3000
Вставьте свой ключ службы "Речь" в выделенное текстовое поле.
При необходимости измените текст на другой.
Чтобы начать преобразование в аудиоформат, нажмите одну из трех кнопок:
- Получить напрямую из Azure — используется вызов на стороне клиента в Azure.
- Элемент управления аудио для получения аудио из файла.
- Элемент управления аудио для получения аудио из буфера.
Вы можете заметить небольшую задержку между выбором элемента управления и воспроизведением аудио.
Создание Службы приложений Azure в Visual Studio Code
В палитре команд (CTRL+SHIFT+P) введите "Создать интернет" и выберите службу приложение Azure: создать веб-приложение... Дополнительно. Используйте расширенные параметры для полного управления развертыванием, в том числе группой ресурсов, планом Службы приложений и операционной системой, чтобы не использовать значения по умолчанию для Linux.
Ответьте на запросы следующим образом:
- Выберите учетную запись своей подписки.
- В поле Введите глобально уникальное имя (например,
my-text-to-speech-app
):- введите имя, уникальное в пределах Azure. Используйте только буквенно-цифровые символы (A–Z, a–z и 0–9) и дефисы (-).
- Выберите
tutorial-resource-group-eastus
для группы ресурсов. - Выберите стек среды выполнения для версии, которая включает
Node
иLTS
. - Выберите операционную систему Linux.
- Выберите Создать план службы приложений и укажите имя, например
my-text-to-speech-app-plan
. - Выберите F1 в бесплатной ценовой категории. Если в вашей подписке уже есть бесплатное веб-приложение, выберите уровень
Basic
. - Выберите Пропустить для ресурса Application Insights.
- Выберите расположение
eastus
.
Через некоторое время в Visual Studio Code появится уведомление о завершении создания. Закройте уведомление с помощью кнопки X.
Развертывание локального приложения Express.js в удаленной Службе приложений в Visual Studio Code
Так как веб-приложение уже готово, разверните код с локального компьютера. Щелкните значок Azure, чтобы открыть обозреватель Службы приложений Azure, разверните узел подписки, щелкните правой кнопкой мыши имя только что созданного веб-приложения и выберите Развернуть в веб-приложении.
При появлении запросов при разработке выберите корневую папку приложения Express.js, снова выберите свою учетную запись в подписке, а затем выберите имя созданного веб-приложения (
my-text-to-speech-app
).При появлении запроса на выполнение
npm install
нажмите Да, когда появится запрос на обновление конфигурации, чтобы выполнитьnpm install
на целевом сервере.По завершении развертывания щелкните Обзор веб-сайта в диалоговом окне с предложением просмотреть только что развернутое веб-приложение.
(Необязательно): вы можете внести изменения в файлы кода, а затем использовать развертывание в веб-приложении в расширении службы приложение Azure для обновления веб-приложения.
Потоковая передача журналов удаленной службы в Visual Studio Code
Просматривайте любые выходные данные или выводите последний фрагмент данных, которые выполняющееся приложение создает в результате вызовов к console.log
. Эти выходные данные отображаются в окне Вывод в Visual Studio Code.
В обозревателе Службы приложений Azure щелкните узел нового приложения правой кнопкой мыши и выберите Начать потоковую передачу журналов.
Starting Live Log Stream ---
Несколько раз обновите веб-страницу в браузере и убедитесь, что отображаются дополнительные выходные данные журнала.
Удаление ресурсов путем удаления группы ресурсов
Завершив работу с этим руководством, удалите группу ресурсов с ресурсом, чтобы с вас не взималась плата за потребление.
Чтобы удалить группу ресурсов, в Azure Cloud Shell выполните команду Azure CLI:
az group delete --name tutorial-resource-group-eastus -y
Эта команда может выполняться несколько минут.