Синтезирование речи на основе текста
Справочные примеры пакета документации | (NuGet) | Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Выбор языка и голоса для синтеза
Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.
Укажите язык или голос для сопоставления входного SpeechConfig
текста и используйте указанный голос. В следующем фрагменте кода показано, как работает этот метод:
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speechConfig.SpeechSynthesisLanguage = "en-US";
speechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
}
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке, это "я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural
, текст говорится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.
Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.
- Если вы не задаете
SpeechSynthesisVoiceName
илиSpeechSynthesisLanguage
используете голосовую связь по умолчанию дляen-US
разговоров. - Если задано только значение по умолчанию для указанного языкового стандарта
SpeechSynthesisLanguage
. - Если заданы и
SpeechSynthesisVoiceName
, иSpeechSynthesisLanguage
, параметрSpeechSynthesisLanguage
игнорируется. Заданный голос с помощьюSpeechSynthesisVoiceName
речи. - Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),
SpeechSynthesisVoiceName
SpeechSynthesisLanguage
параметры игнорируются.
В итоге порядок приоритета можно описать следующим образом:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Результат |
---|---|---|---|
✗ | ✗ | ✗ | Голос по умолчанию для en-US разговоров |
✗ | ✔ | ✗ | Голосовая связь по умолчанию для указанного языкового стандарта. |
✔ | ✔ | ✗ | Заданный голос с помощью SpeechSynthesisVoiceName речи. |
✔ | ✔ | ✔ | Заданный голос с помощью SSML говорит. |
Синтезирование речи в файл
Создайте объект SpeechSynthesizer. Этот объект, показанный в следующих фрагментах кода, выполняет преобразование речи и выходные данные в динамики, файлы или другие выходные потоки. SpeechSynthesizer
принимает в качестве параметров:
- Объект SpeechConfig, созданный на предыдущем шаге.
- Объект AudioConfig, указывающий способ обработки выходных результатов.
AudioConfig
Создайте экземпляр для автоматической записи выходных данных в файл .wav с помощьюFromWavFileOutput()
функции. Создайте экземпляр с помощью инструкцииusing
.static async Task SynthesizeAudioAsync() { var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion"); using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav"); }
Инструкция
using
в этом контексте автоматически удаляет неуправляемые ресурсы и выводит объект из области после его удаления.Создайте
SpeechSynthesizer
экземпляр с другойusing
инструкцией. Передайте объектыspeechConfig
иaudioConfig
в качестве параметров. Чтобы синтезировать речь и записывать в файл, запуститеSpeakTextAsync()
строку текста.
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav");
using var speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
}
При запуске программы создается синтезированный .wav-файл , который записывается в указанное расположение. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ в виде потока в памяти для работы с пользовательскими сценариями.
Синтезирование выходных данных для вывода на динамики
Чтобы вывести синтезированную речь на текущее активное выходное устройство, например динамик, опустите AudioConfig
параметр при создании экземпляра SpeechSynthesizer
. Приведем пример:
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
using var speechSynthesizer = new SpeechSynthesizer(speechConfig);
await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
}
Получение результата в виде потока в памяти
Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:
- абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
- интегрировать полученные данные с другими API или службами;
- изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.
Это изменение можно внести в предыдущий пример. Во-первых, удалите AudioConfig
блок, так как вы управляете поведением выходных данных вручную с этой точки, чтобы увеличить контроль. Передайте null
в AudioConfig
SpeechSynthesizer
конструктор.
Примечание.
AudioConfig
Передача null
для , а не опущений, как в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.
Сохраните результат в переменной SpeechSynthesisResult . Свойство AudioData
содержит экземпляр byte []
выходных данных. Вы можете работать с этим byte []
экземпляром вручную или использовать класс AudioDataStream для управления потоком в памяти.
В этом примере используется статическая функция AudioDataStream.FromResult()
для получения потока из результата:
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
var result = await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
using var stream = AudioDataStream.FromResult(result);
}
На этом этапе можно реализовать любое пользовательское поведение с помощью результирующего stream
объекта.
Настройка звукового формата
Можно настроить атрибуты вывода звука, в том числе:
- тип звукового файла;
- Частота выборки
- глубину в битах.
Чтобы изменить звуковой формат, используйте функцию SetSpeechSynthesisOutputFormat()
для объекта SpeechConfig
. Эта функция ожидает enum
экземпляр типа SpeechSynthesisOutputFormat. enum
Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.
Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm
, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.
- Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
- Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.
В этом примере указывается формат Riff24Khz16BitMonoPcm
RIFF с высокой точностью, задав SpeechSynthesisOutputFormat
объект SpeechConfig
. Как и в примере в предыдущем разделе, вы используете AudioDataStream для получения потока результата в памяти, а затем записываете его в файл.
static async Task SynthesizeAudioAsync()
{
var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
speechConfig.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);
using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
var result = await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
using var stream = AudioDataStream.FromResult(result);
await stream.SaveToWaveFileAsync("path/to/write/file.wav");
}
При запуске программы он записывает файл .wav в указанный путь.
Настройка характеристик речи с использованием SSML
SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".
Чтобы начать использовать SSML для настройки, необходимо внести незначительные изменения, которые переключают голос.
Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
В этом примере файл ssml.xml. Корневым элементом всегда является
<speak>
, а перенос текста в элемент<voice>
позволяет менять голос с помощью параметраname
. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос аналогичен использовавшемуся нами ранее, но вместо функции
SpeakTextAsync()
содержитSpeakSsmlAsync()
. Эта функция ожидает XML-строку. Сначала загрузите конфигурацию SSML в виде строки с помощьюFile.ReadAllText()
. С этого момента объект результата точно совпадает с предыдущими примерами.Примечание.
Если вы используете Visual Studio, то конфигурация сборки вероятнее всего не найдет XML-файл по умолчанию. Щелкните ПРАВОй кнопкой мыши XML-файл и выберите "Свойства". Изменение действия сборки на содержимое. Всегда изменяйте копирование в выходной каталог для копирования.
public static async Task SynthesizeAudioAsync() { var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion"); using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null); var ssml = File.ReadAllText("./ssml.xml"); var result = await speechSynthesizer.SpeakSsmlAsync(ssml); using var stream = AudioDataStream.FromResult(result); await stream.SaveToWaveFileAsync("path/to/write/file.wav"); }
Примечание.
Чтобы изменить голос без использования SSML, можно задать свойство в SpeechConfig
с помощью SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
.
Подписка на события синтезатора
Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
Мероприятие | Description | Вариант использования |
---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить отмену синтеза. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить при запуске синтеза. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят. |
Примечание.
События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".
Вы можете следовать инструкциям в кратком руководстве, но замените содержимое этого файла Program.cs следующим кодом C#:
using Microsoft.CognitiveServices.Speech;
class Program
{
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
static string speechKey = Environment.GetEnvironmentVariable("SPEECH_KEY");
static string speechRegion = Environment.GetEnvironmentVariable("SPEECH_REGION");
async static Task Main(string[] args)
{
var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);
var speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
var ssml = @$"<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name='{speechSynthesisVoiceName}'>
<mstts:viseme type='redlips_front'/>
The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
</voice>
</speak>";
// Required for sentence-level WordBoundary events
speechConfig.SetProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");
using (var speechSynthesizer = new SpeechSynthesizer(speechConfig))
{
// Subscribe to events
speechSynthesizer.BookmarkReached += (s, e) =>
{
Console.WriteLine($"BookmarkReached event:" +
$"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
$"\r\n\tText: \"{e.Text}\".");
};
speechSynthesizer.SynthesisCanceled += (s, e) =>
{
Console.WriteLine("SynthesisCanceled event");
};
speechSynthesizer.SynthesisCompleted += (s, e) =>
{
Console.WriteLine($"SynthesisCompleted event:" +
$"\r\n\tAudioData: {e.Result.AudioData.Length} bytes" +
$"\r\n\tAudioDuration: {e.Result.AudioDuration}");
};
speechSynthesizer.SynthesisStarted += (s, e) =>
{
Console.WriteLine("SynthesisStarted event");
};
speechSynthesizer.Synthesizing += (s, e) =>
{
Console.WriteLine($"Synthesizing event:" +
$"\r\n\tAudioData: {e.Result.AudioData.Length} bytes");
};
speechSynthesizer.VisemeReceived += (s, e) =>
{
Console.WriteLine($"VisemeReceived event:" +
$"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
$"\r\n\tVisemeId: {e.VisemeId}");
};
speechSynthesizer.WordBoundary += (s, e) =>
{
Console.WriteLine($"WordBoundary event:" +
// Word, Punctuation, or Sentence
$"\r\n\tBoundaryType: {e.BoundaryType}" +
$"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
$"\r\n\tDuration: {e.Duration}" +
$"\r\n\tText: \"{e.Text}\"" +
$"\r\n\tTextOffset: {e.TextOffset}" +
$"\r\n\tWordLength: {e.WordLength}");
};
// Synthesize the SSML
Console.WriteLine($"SSML to synthesize: \r\n{ssml}");
var speechSynthesisResult = await speechSynthesizer.SpeakSsmlAsync(ssml);
// Output the results
switch (speechSynthesisResult.Reason)
{
case ResultReason.SynthesizingAudioCompleted:
Console.WriteLine("SynthesizingAudioCompleted result");
break;
case ResultReason.Canceled:
var cancellation = SpeechSynthesisCancellationDetails.FromResult(speechSynthesisResult);
Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");
if (cancellation.Reason == CancellationReason.Error)
{
Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");
Console.WriteLine($"CANCELED: ErrorDetails=[{cancellation.ErrorDetails}]");
Console.WriteLine($"CANCELED: Did you set the speech resource key and region values?");
}
break;
default:
break;
}
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
Дополнительные текстовые примеры для речи можно найти на сайте GitHub.
Использование пользовательской конечной точки
Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов на речь.
Одно из различий заключается в том, что EndpointId
его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью EndpointId
и SpeechSynthesisVoiceName
.
var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);
speechConfig.SpeechSynthesisVoiceName = "YourCustomVoiceName";
speechConfig.EndpointId = "YourEndpointId";
Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.
Справочные примеры пакета документации | (NuGet) | Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Выбор языка и голоса для синтеза
Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Полный список поддерживаемых языковых стандартов речи или попробуйте использовать их в коллекции голосовых данных.
Укажите язык или голос класса SpeechConfig для сопоставления входного текста и использования указанного голоса. В следующем фрагменте кода показано, как работает этот метод:
void synthesizeSpeech()
{
auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speechConfig->SetSpeechSynthesisLanguage("en-US");
speechConfig->SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural
, текст говорится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.
Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.
- Если вы не задаете
SpeechSynthesisVoiceName
илиSpeechSynthesisLanguage
используете голосовую связь по умолчанию дляen-US
разговоров. - Если задано только значение по умолчанию для указанного языкового стандарта
SpeechSynthesisLanguage
. - Если заданы и
SpeechSynthesisVoiceName
, иSpeechSynthesisLanguage
, параметрSpeechSynthesisLanguage
игнорируется. Заданный голос с помощьюSpeechSynthesisVoiceName
речи. - Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),
SpeechSynthesisVoiceName
SpeechSynthesisLanguage
параметры игнорируются.
В итоге порядок приоритета можно описать следующим образом:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Результат |
---|---|---|---|
✗ | ✗ | ✗ | Голос по умолчанию для en-US разговоров |
✗ | ✔ | ✗ | Голосовая связь по умолчанию для указанного языкового стандарта. |
✔ | ✔ | ✗ | Заданный голос с помощью SpeechSynthesisVoiceName речи. |
✔ | ✔ | ✔ | Заданный голос с помощью SSML говорит. |
Синтезирование речи в файл
Создайте объект SpeechSynthesizer. Этот объект, показанный в следующих фрагментах кода, выполняет преобразование речи и выходные данные в динамики, файлы или другие выходные потоки. SpeechSynthesizer
принимает в качестве параметров:
- Объект SpeechConfig, созданный на предыдущем шаге.
- Объект AudioConfig, указывающий способ обработки выходных результатов.
AudioConfig
Создайте экземпляр для автоматической записи выходных данных в файл .wav с помощьюFromWavFileOutput()
функции:void synthesizeSpeech() { auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion"); auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav"); }
Создание экземпляра
SpeechSynthesizer
. Передайте объектыspeechConfig
иaudioConfig
в качестве параметров. Чтобы синтезировать речь и записывать в файл, запуститеSpeakTextAsync()
строку текста.void synthesizeSpeech() { auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion"); auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav"); auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig, audioConfig); auto result = speechSynthesizer->SpeakTextAsync("A simple test to write to a file.").get(); }
При запуске программы создается синтезированный .wav-файл , который записывается в указанное расположение. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ в виде потока в памяти для работы с пользовательскими сценариями.
Синтезирование выходных данных для вывода на динамики
Чтобы вывести синтезированную речь на текущее активное устройство вывода, например динамик, опустите AudioConfig
параметр при создании экземпляра SpeechSynthesizer
. Приведем пример:
void synthesizeSpeech()
{
auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
auto result = speechSynthesizer->SpeakTextAsync("I'm excited to try text to speech").get();
}
Получение результата в виде потока в памяти
Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:
- абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
- интегрировать полученные данные с другими API или службами;
- изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.
Это изменение можно внести в предыдущий пример. Во-первых, удалите AudioConfig
блок, так как вы управляете поведением выходных данных вручную с этой точки, чтобы увеличить контроль. Передайте NULL
в AudioConfig
SpeechSynthesizer
конструктор.
Примечание.
AudioConfig
Передача NULL
для , а не опущений, как в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.
Сохраните результат в переменной SpeechSynthesisResult . Метод получения GetAudioData
возвращает экземпляр byte []
выходных данных. Вы можете работать с этим byte []
экземпляром вручную или использовать класс AudioDataStream для управления потоком в памяти.
В этом примере используйте AudioDataStream.FromResult()
статическую функцию для получения потока из результата:
void synthesizeSpeech()
{
auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
auto result = speechSynthesizer->SpeakTextAsync("Getting the response as an in-memory stream.").get();
auto stream = AudioDataStream::FromResult(result);
}
На этом этапе можно реализовать любое пользовательское поведение с помощью результирующего stream
объекта.
Настройка звукового формата
Можно настроить атрибуты вывода звука, в том числе:
- тип звукового файла;
- Частота выборки
- глубину в битах.
Чтобы изменить формат звука, используйте SetSpeechSynthesisOutputFormat()
функцию в объекте SpeechConfig
. Эта функция ожидает enum
экземпляр типа SpeechSynthesisOutputFormat. enum
Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.
Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm
, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.
- Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
- Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.
В этом примере указывается формат Riff24Khz16BitMonoPcm
RIFF с высокой точностью, задав SpeechSynthesisOutputFormat
объект SpeechConfig
. Как и в примере из предыдущего раздела, мы будем использовать AudioDataStream
для получения результата в виде потока в памяти, а затем записывать его в файл.
void synthesizeSpeech()
{
auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
speechConfig->SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat::Riff24Khz16BitMonoPcm);
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
auto result = speechSynthesizer->SpeakTextAsync("A simple test to write to a file.").get();
auto stream = AudioDataStream::FromResult(result);
stream->SaveToWavFileAsync("path/to/write/file.wav").get();
}
При запуске программы он записывает файл .wav в указанный путь.
Настройка характеристик речи с использованием SSML
SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".
Чтобы начать использовать SSML для настройки, внесите незначительные изменения, которые переключают голос.
Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
В этом примере файл ssml.xml. Корневым элементом всегда является
<speak>
, а перенос текста в элемент<voice>
позволяет менять голос с помощью параметраname
. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос в основном совпадает. Вместо использования
SpeakTextAsync()
функции вы используетеSpeakSsmlAsync()
. Эта функция ожидает XML-строку. Сначала загрузите конфигурацию SSML в виде строки. С этого момента объект результата точно совпадает с предыдущими примерами.void synthesizeSpeech() { auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion"); auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig); std::ifstream file("./ssml.xml"); std::string ssml, line; while (std::getline(file, line)) { ssml += line; ssml.push_back('\n'); } auto result = speechSynthesizer->SpeakSsmlAsync(ssml).get(); auto stream = AudioDataStream::FromResult(result); stream->SaveToWavFileAsync("path/to/write/file.wav").get(); }
Примечание.
Чтобы изменить голос без использования SSML, можно задать свойство в SpeechConfig
с помощью SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural")
.
Подписка на события синтезатора
Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
Мероприятие | Description | Вариант использования |
---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить отмену синтеза. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить при запуске синтеза. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят. |
Примечание.
События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".
Вы можете выполнить инструкции в кратком руководстве, но заменить содержимое этого файла main.cpp следующим кодом:
#include <iostream>
#include <stdlib.h>
#include <speechapi_cxx.h>
using namespace Microsoft::CognitiveServices::Speech;
using namespace Microsoft::CognitiveServices::Speech::Audio;
std::string getEnvironmentVariable(const char* name);
int main()
{
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
auto speechKey = getEnvironmentVariable("SPEECH_KEY");
auto speechRegion = getEnvironmentVariable("SPEECH_REGION");
if ((size(speechKey) == 0) || (size(speechRegion) == 0)) {
std::cout << "Please set both SPEECH_KEY and SPEECH_REGION environment variables." << std::endl;
return -1;
}
auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);
// Required for WordBoundary event sentences.
speechConfig->SetProperty(PropertyId::SpeechServiceResponse_RequestSentenceBoundary, "true");
const auto ssml = R"(<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name = 'en-US-AvaMultilingualNeural'>
<mstts:viseme type = 'redlips_front' />
The rainbow has seven colors : <bookmark mark = 'colors_list_begin' />Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark = 'colors_list_end' />.
</voice>
</speak>)";
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
// Subscribe to events
speechSynthesizer->BookmarkReached += [](const SpeechSynthesisBookmarkEventArgs& e)
{
std::cout << "Bookmark reached. "
<< "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
<< "\r\n\tText: " << e.Text << std::endl;
};
speechSynthesizer->SynthesisCanceled += [](const SpeechSynthesisEventArgs& e)
{
std::cout << "SynthesisCanceled event" << std::endl;
};
speechSynthesizer->SynthesisCompleted += [](const SpeechSynthesisEventArgs& e)
{
auto audioDuration = std::chrono::duration_cast<std::chrono::milliseconds>(e.Result->AudioDuration).count();
std::cout << "SynthesisCompleted event:"
<< "\r\n\tAudioData: " << e.Result->GetAudioData()->size() << "bytes"
<< "\r\n\tAudioDuration: " << audioDuration << std::endl;
};
speechSynthesizer->SynthesisStarted += [](const SpeechSynthesisEventArgs& e)
{
std::cout << "SynthesisStarted event" << std::endl;
};
speechSynthesizer->Synthesizing += [](const SpeechSynthesisEventArgs& e)
{
std::cout << "Synthesizing event:"
<< "\r\n\tAudioData: " << e.Result->GetAudioData()->size() << "bytes" << std::endl;
};
speechSynthesizer->VisemeReceived += [](const SpeechSynthesisVisemeEventArgs& e)
{
std::cout << "VisemeReceived event:"
<< "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
<< "\r\n\tVisemeId: " << e.VisemeId << std::endl;
};
speechSynthesizer->WordBoundary += [](const SpeechSynthesisWordBoundaryEventArgs& e)
{
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(e.Duration).count();
auto boundaryType = "";
switch (e.BoundaryType) {
case SpeechSynthesisBoundaryType::Punctuation:
boundaryType = "Punctuation";
break;
case SpeechSynthesisBoundaryType::Sentence:
boundaryType = "Sentence";
break;
case SpeechSynthesisBoundaryType::Word:
boundaryType = "Word";
break;
}
std::cout << "WordBoundary event:"
// Word, Punctuation, or Sentence
<< "\r\n\tBoundaryType: " << boundaryType
<< "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
<< "\r\n\tDuration: " << duration
<< "\r\n\tText: \"" << e.Text << "\""
<< "\r\n\tTextOffset: " << e.TextOffset
<< "\r\n\tWordLength: " << e.WordLength << std::endl;
};
auto result = speechSynthesizer->SpeakSsmlAsync(ssml).get();
// Checks result.
if (result->Reason == ResultReason::SynthesizingAudioCompleted)
{
std::cout << "SynthesizingAudioCompleted result" << std::endl;
}
else if (result->Reason == ResultReason::Canceled)
{
auto cancellation = SpeechSynthesisCancellationDetails::FromResult(result);
std::cout << "CANCELED: Reason=" << (int)cancellation->Reason << std::endl;
if (cancellation->Reason == CancellationReason::Error)
{
std::cout << "CANCELED: ErrorCode=" << (int)cancellation->ErrorCode << std::endl;
std::cout << "CANCELED: ErrorDetails=[" << cancellation->ErrorDetails << "]" << std::endl;
std::cout << "CANCELED: Did you set the speech resource key and region values?" << std::endl;
}
}
std::cout << "Press enter to exit..." << std::endl;
std::cin.get();
}
std::string getEnvironmentVariable(const char* name)
{
#if defined(_MSC_VER)
size_t requiredSize = 0;
(void)getenv_s(&requiredSize, nullptr, 0, name);
if (requiredSize == 0)
{
return "";
}
auto buffer = std::make_unique<char[]>(requiredSize);
(void)getenv_s(&requiredSize, buffer.get(), requiredSize, name);
return buffer.get();
#else
auto value = getenv(name);
return value ? value : "";
#endif
}
Дополнительные текстовые примеры для речи можно найти на сайте GitHub.
Использование пользовательской конечной точки
Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов речи.
Одно из различий заключается в том, что EndpointId
его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью EndpointId
и SpeechSynthesisVoiceName
.
auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);
speechConfig->SetSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig->SetEndpointId("YourEndpointId");
Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.
Справочные примеры пакета документации | (Go) | Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Необходимые компоненты
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс службы "Речь" в портал Azure.
- Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.
Установка пакета SDK Речи
Прежде чем выполнять какие-либо действия, необходимо установить пакет SDK службы "Речь" для Go.
Текст для речи на говорящего
Используйте следующий пример кода для запуска синтеза речи на устройство вывода аудио по умолчанию. Замените переменные subscription
и region
своим ключом службы "Речь" и расположением или регионом. Выполнение скрипта говорит входной текст с динамиком по умолчанию.
package main
import (
"bufio"
"fmt"
"os"
"strings"
"time"
"github.com/Microsoft/cognitive-services-speech-sdk-go/audio"
"github.com/Microsoft/cognitive-services-speech-sdk-go/common"
"github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)
func synthesizeStartedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Synthesis started.")
}
func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Printf("Synthesizing, audio chunk size %d.\n", len(event.Result.AudioData))
}
func synthesizedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Printf("Synthesized, audio length %d.\n", len(event.Result.AudioData))
}
func cancelledHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Received a cancellation.")
}
func main() {
subscription := "YourSpeechKey"
region := "YourSpeechRegion"
audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer audioConfig.Close()
speechConfig, err := speech.NewSpeechConfigFromSubscription(subscription, region)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechConfig.Close()
speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, audioConfig)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechSynthesizer.Close()
speechSynthesizer.SynthesisStarted(synthesizeStartedHandler)
speechSynthesizer.Synthesizing(synthesizingHandler)
speechSynthesizer.SynthesisCompleted(synthesizedHandler)
speechSynthesizer.SynthesisCanceled(cancelledHandler)
for {
fmt.Printf("Enter some text that you want to speak, or enter empty text to exit.\n> ")
text, _ := bufio.NewReader(os.Stdin).ReadString('\n')
text = strings.TrimSuffix(text, "\n")
if len(text) == 0 {
break
}
task := speechSynthesizer.SpeakTextAsync(text)
var outcome speech.SpeechSynthesisOutcome
select {
case outcome = <-task:
case <-time.After(60 * time.Second):
fmt.Println("Timed out")
return
}
defer outcome.Close()
if outcome.Error != nil {
fmt.Println("Got an error: ", outcome.Error)
return
}
if outcome.Result.Reason == common.SynthesizingAudioCompleted {
fmt.Printf("Speech synthesized to speaker for text [%s].\n", text)
} else {
cancellation, _ := speech.NewCancellationDetailsFromSpeechSynthesisResult(outcome.Result)
fmt.Printf("CANCELED: Reason=%d.\n", cancellation.Reason)
if cancellation.Reason == common.Error {
fmt.Printf("CANCELED: ErrorCode=%d\nCANCELED: ErrorDetails=[%s]\nCANCELED: Did you set the speech resource key and region values?\n",
cancellation.ErrorCode,
cancellation.ErrorDetails)
}
}
}
}
Выполните приведенные ниже команды, чтобы создать файл go.mod со ссылкой на компоненты, размещенные в GitHub:
go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go
Теперь можно приступить к сборке и выполнению кода:
go build
go run quickstart
Подробные сведения о классах см. в справочной документации по SpeechConfig
и SpeechSynthesizer
.
Текст для преобразования речи в поток в памяти
Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:
- абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
- интегрировать полученные данные с другими API или службами;
- изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.
Это изменение можно внести в предыдущий пример. Удалите блок, так как вы управляете AudioConfig
поведением выходных данных вручную с этого момента для повышения контроля. Затем передайте nil
для AudioConfig
в конструкторе SpeechSynthesizer
.
Примечание.
Передача значения nil
для AudioConfig
вместо его пропуска, как это сделано в предыдущем примере с выводом на динамики, не позволит по умолчанию воспроизводить звук на активном устройстве вывода.
Сохраните результат в переменной SpeechSynthesisResult
. Свойство AudioData
возвращает экземпляр []byte
выходных данных. Вы можете работать с экземпляром []byte
вручную или использовать класс AudioDataStream
для управления потоком в памяти.
В этом примере используется статическая функция NewAudioDataStreamFromSpeechSynthesisResult()
для получения потока из результата.
Замените переменные subscription
и region
своим ключом службы "Речь" и данными о расположении или регионе:
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
"time"
"github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)
func synthesizeStartedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Synthesis started.")
}
func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Printf("Synthesizing, audio chunk size %d.\n", len(event.Result.AudioData))
}
func synthesizedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Printf("Synthesized, audio length %d.\n", len(event.Result.AudioData))
}
func cancelledHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Received a cancellation.")
}
func main() {
subscription := "YourSpeechKey"
region := "YourSpeechRegion"
speechConfig, err := speech.NewSpeechConfigFromSubscription(subscription, region)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechConfig.Close()
speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, nil)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechSynthesizer.Close()
speechSynthesizer.SynthesisStarted(synthesizeStartedHandler)
speechSynthesizer.Synthesizing(synthesizingHandler)
speechSynthesizer.SynthesisCompleted(synthesizedHandler)
speechSynthesizer.SynthesisCanceled(cancelledHandler)
for {
fmt.Printf("Enter some text that you want to speak, or enter empty text to exit.\n> ")
text, _ := bufio.NewReader(os.Stdin).ReadString('\n')
text = strings.TrimSuffix(text, "\n")
if len(text) == 0 {
break
}
// StartSpeakingTextAsync sends the result to channel when the synthesis starts.
task := speechSynthesizer.StartSpeakingTextAsync(text)
var outcome speech.SpeechSynthesisOutcome
select {
case outcome = <-task:
case <-time.After(60 * time.Second):
fmt.Println("Timed out")
return
}
defer outcome.Close()
if outcome.Error != nil {
fmt.Println("Got an error: ", outcome.Error)
return
}
// In most cases, we want to streaming receive the audio to lower the latency.
// We can use AudioDataStream to do so.
stream, err := speech.NewAudioDataStreamFromSpeechSynthesisResult(outcome.Result)
defer stream.Close()
if err != nil {
fmt.Println("Got an error: ", err)
return
}
var all_audio []byte
audio_chunk := make([]byte, 2048)
for {
n, err := stream.Read(audio_chunk)
if err == io.EOF {
break
}
all_audio = append(all_audio, audio_chunk[:n]...)
}
fmt.Printf("Read [%d] bytes from audio data stream.\n", len(all_audio))
}
}
Выполните приведенные ниже команды, чтобы создать файл go.mod со ссылкой на компоненты, размещенные в GitHub:
go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go
Теперь можно приступить к сборке и выполнению кода:
go build
go run quickstart
Подробные сведения о классах см. в справочной документации по SpeechConfig
и SpeechSynthesizer
.
Выбор языка и голоса для синтеза
Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.
Укажите язык или голос для сопоставления входного SpeechConfig
текста и используйте указанный голос:
speechConfig, err := speech.NewSpeechConfigFromSubscription(key, region)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechConfig.Close()
speechConfig.SetSpeechSynthesisLanguage("en-US")
speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural")
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural
, текст говорится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.
Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.
- Если вы не задаете
SpeechSynthesisVoiceName
илиSpeechSynthesisLanguage
используете голосовую связь по умолчанию дляen-US
разговоров. - Если задано только значение по умолчанию для указанного языкового стандарта
SpeechSynthesisLanguage
. - Если заданы и
SpeechSynthesisVoiceName
, иSpeechSynthesisLanguage
, параметрSpeechSynthesisLanguage
игнорируется. Заданный голос с помощьюSpeechSynthesisVoiceName
речи. - Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),
SpeechSynthesisVoiceName
SpeechSynthesisLanguage
параметры игнорируются.
В итоге порядок приоритета можно описать следующим образом:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Результат |
---|---|---|---|
✗ | ✗ | ✗ | Голос по умолчанию для en-US разговоров |
✗ | ✔ | ✗ | Голосовая связь по умолчанию для указанного языкового стандарта. |
✔ | ✔ | ✗ | Заданный голос с помощью SpeechSynthesisVoiceName речи. |
✔ | ✔ | ✔ | Заданный голос с помощью SSML говорит. |
Настройка характеристик речи с использованием SSML
Вы можете использовать язык разметки синтеза речи (SSML), чтобы точно настроить поле, произношение, скорость речи, громкость и многое другое в тексте для вывода речи, отправив запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".
Чтобы начать использовать SSML для настройки, необходимо внести незначительные изменения, которые переключают голос.
Сначала создайте XML-файл для конфигурации SSML в корневом каталоге проекта. В нашем примере это значение выглядит следующим образом: ssml.xml
. Корневым элементом всегда является <speak>
, а перенос текста в элемент <voice>
позволяет менять голос с помощью параметра name
. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="en-US-AvaMultilingualNeural">
When you're on the freeway, it's a good idea to use a GPS.
</voice>
</speak>
Далее необходимо изменить запрос синтеза речи, чтобы он ссылался на XML-файл. Запрос аналогичен использовавшемуся нами ранее, но вместо функции SpeakTextAsync()
содержит SpeakSsmlAsync()
. Эта функция ожидает строку XML, поэтому сначала нужно загрузить конфигурацию SSML в виде строки. С этого момента объект результата точно совпадает с предыдущими примерами.
Примечание.
Чтобы задать голос без использования SSML, можно задать свойство в SpeechConfig
с помощью speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural")
.
Подписка на события синтезатора
Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
Мероприятие | Description | Вариант использования |
---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить отмену синтеза. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить при запуске синтеза. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят. |
Примечание.
События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".
Вы можете следовать инструкциям в кратком руководстве, но заменить содержимое этого speech-synthesis.go
файла следующим кодом Go:
package main
import (
"fmt"
"os"
"time"
"github.com/Microsoft/cognitive-services-speech-sdk-go/audio"
"github.com/Microsoft/cognitive-services-speech-sdk-go/common"
"github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)
func bookmarkReachedHandler(event speech.SpeechSynthesisBookmarkEventArgs) {
defer event.Close()
fmt.Println("BookmarkReached event")
}
func synthesisCanceledHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("SynthesisCanceled event")
}
func synthesisCompletedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("SynthesisCompleted event")
fmt.Printf("\tAudioData: %d bytes\n", len(event.Result.AudioData))
fmt.Printf("\tAudioDuration: %d\n", event.Result.AudioDuration)
}
func synthesisStartedHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("SynthesisStarted event")
}
func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
defer event.Close()
fmt.Println("Synthesizing event")
fmt.Printf("\tAudioData %d bytes\n", len(event.Result.AudioData))
}
func visemeReceivedHandler(event speech.SpeechSynthesisVisemeEventArgs) {
defer event.Close()
fmt.Println("VisemeReceived event")
fmt.Printf("\tAudioOffset: %dms\n", (event.AudioOffset+5000)/10000)
fmt.Printf("\tVisemeID %d\n", event.VisemeID)
}
func wordBoundaryHandler(event speech.SpeechSynthesisWordBoundaryEventArgs) {
defer event.Close()
boundaryType := ""
switch event.BoundaryType {
case 0:
boundaryType = "Word"
case 1:
boundaryType = "Punctuation"
case 2:
boundaryType = "Sentence"
}
fmt.Println("WordBoundary event")
fmt.Printf("\tBoundaryType %v\n", boundaryType)
fmt.Printf("\tAudioOffset: %dms\n", (event.AudioOffset+5000)/10000)
fmt.Printf("\tDuration %d\n", event.Duration)
fmt.Printf("\tText %s\n", event.Text)
fmt.Printf("\tTextOffset %d\n", event.TextOffset)
fmt.Printf("\tWordLength %d\n", event.WordLength)
}
func main() {
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
speechKey := os.Getenv("SPEECH_KEY")
speechRegion := os.Getenv("SPEECH_REGION")
audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer audioConfig.Close()
speechConfig, err := speech.NewSpeechConfigFromSubscription(speechKey, speechRegion)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechConfig.Close()
// Required for WordBoundary event sentences.
speechConfig.SetProperty(common.SpeechServiceResponseRequestSentenceBoundary, "true")
speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, audioConfig)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer speechSynthesizer.Close()
speechSynthesizer.BookmarkReached(bookmarkReachedHandler)
speechSynthesizer.SynthesisCanceled(synthesisCanceledHandler)
speechSynthesizer.SynthesisCompleted(synthesisCompletedHandler)
speechSynthesizer.SynthesisStarted(synthesisStartedHandler)
speechSynthesizer.Synthesizing(synthesizingHandler)
speechSynthesizer.VisemeReceived(visemeReceivedHandler)
speechSynthesizer.WordBoundary(wordBoundaryHandler)
speechSynthesisVoiceName := "en-US-AvaMultilingualNeural"
ssml := fmt.Sprintf(`<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name='%s'>
<mstts:viseme type='redlips_front'/>
The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
</voice>
</speak>`, speechSynthesisVoiceName)
// Synthesize the SSML
fmt.Printf("SSML to synthesize: \n\t%s\n", ssml)
task := speechSynthesizer.SpeakSsmlAsync(ssml)
var outcome speech.SpeechSynthesisOutcome
select {
case outcome = <-task:
case <-time.After(60 * time.Second):
fmt.Println("Timed out")
return
}
defer outcome.Close()
if outcome.Error != nil {
fmt.Println("Got an error: ", outcome.Error)
return
}
if outcome.Result.Reason == common.SynthesizingAudioCompleted {
fmt.Println("SynthesizingAudioCompleted result")
} else {
cancellation, _ := speech.NewCancellationDetailsFromSpeechSynthesisResult(outcome.Result)
fmt.Printf("CANCELED: Reason=%d.\n", cancellation.Reason)
if cancellation.Reason == common.Error {
fmt.Printf("CANCELED: ErrorCode=%d\nCANCELED: ErrorDetails=[%s]\nCANCELED: Did you set the speech resource key and region values?\n",
cancellation.ErrorCode,
cancellation.ErrorDetails)
}
}
}
Дополнительные текстовые примеры для речи можно найти на сайте GitHub.
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.
Справочная документация | по Дополнительным примерам на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Выбор языка и голоса для синтеза
Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.
Укажите язык или голос SpeechConfig для сопоставления входного текста и используйте указанный голос. В следующем фрагменте кода показано, как работает этот метод:
public static void main(String[] args) {
SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speechConfig.setSpeechSynthesisLanguage("en-US");
speechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural
, текст говорится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.
Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.
- Если вы не задаете
SpeechSynthesisVoiceName
илиSpeechSynthesisLanguage
используете голосовую связь по умолчанию дляen-US
разговоров. - Если задано только значение по умолчанию для указанного языкового стандарта
SpeechSynthesisLanguage
. - Если заданы и
SpeechSynthesisVoiceName
, иSpeechSynthesisLanguage
, параметрSpeechSynthesisLanguage
игнорируется. Голос, указанный с помощьюSpeechSynthesisVoiceName
речи. - Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),
SpeechSynthesisVoiceName
SpeechSynthesisLanguage
параметры игнорируются.
В итоге порядок приоритета можно описать следующим образом:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Результат |
---|---|---|---|
✗ | ✗ | ✗ | Голос по умолчанию для en-US разговоров |
✗ | ✔ | ✗ | Голосовая связь по умолчанию для указанного языкового стандарта. |
✔ | ✔ | ✗ | Заданный голос с помощью SpeechSynthesisVoiceName речи. |
✔ | ✔ | ✔ | Заданный голос с помощью SSML говорит. |
Синтезирование речи в файл
Создание объекта SpeechSynthesizer
. Этот объект выполняет текст для преобразования речи и выходных данных в динамики, файлы или другие выходные потоки. SpeechSynthesizer
принимает в качестве параметров:
- Объект
SpeechConfig
, созданный на предыдущем шаге. - Объект, указывающий
AudioConfig
способ обработки выходных результатов.
AudioConfig
Создайте экземпляр для автоматической записи выходных данных в файл .wav с помощьюfromWavFileOutput()
статической функции:public static void main(String[] args) { SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion"); AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav"); }
Создание экземпляра
SpeechSynthesizer
. Передайте объектыspeechConfig
иaudioConfig
в качестве параметров. Чтобы синтезировать речь и записывать в файл, запуститеSpeakText()
строку текста.public static void main(String[] args) { SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion"); AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav"); SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig); speechSynthesizer.SpeakText("I'm excited to try text to speech"); }
При запуске программы создается синтезированный .wav-файл , который записывается в указанное расположение. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ в виде потока в памяти для работы с пользовательскими сценариями.
Синтезирование выходных данных для вывода на динамики
Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Чтобы вывести синтезированную речь на текущее активное выходное устройство, например динамик, создайте экземпляр AudioConfig
с помощью fromDefaultSpeakerOutput()
статической функции. Приведем пример:
public static void main(String[] args) {
SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
AudioConfig audioConfig = AudioConfig.fromDefaultSpeakerOutput();
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
speechSynthesizer.SpeakText("I'm excited to try text to speech");
}
Получение результата в виде потока в памяти
Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:
- абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
- интегрировать полученные данные с другими API или службами;
- изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.
Это изменение можно внести в предыдущий пример. Во-первых, удалите AudioConfig
блок, так как вы управляете поведением выходных данных вручную с этой точки, чтобы увеличить контроль. Затем передайте null
для AudioConfig
в конструкторе SpeechSynthesizer
.
Примечание.
AudioConfig
Передачаnull
, а не пропускание, как и в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.
Сохраните результат в переменной SpeechSynthesisResult
. Функция SpeechSynthesisResult.getAudioData()
возвращает экземпляр byte []
выходных данных. Вы можете работать с экземпляром byte []
вручную или использовать класс AudioDataStream
для управления потоком в памяти.
В этом примере используйте AudioDataStream.fromResult()
статическую функцию для получения потока из результата:
public static void main(String[] args) {
SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
SpeechSynthesisResult result = speechSynthesizer.SpeakText("I'm excited to try text to speech");
AudioDataStream stream = AudioDataStream.fromResult(result);
System.out.print(stream.getStatus());
}
На этом этапе можно реализовать любое пользовательское поведение с помощью результирующего stream
объекта.
Настройка звукового формата
Можно настроить атрибуты вывода звука, в том числе:
- тип звукового файла;
- Частота выборки
- глубину в битах.
Чтобы изменить звуковой формат, используйте функцию setSpeechSynthesisOutputFormat()
для объекта SpeechConfig
. Эта функция ожидает enum
экземпляр типа SpeechSynthesisOutputFormat. enum
Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.
Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm
, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.
- Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
- Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.
В этом примере указывается формат Riff24Khz16BitMonoPcm
RIFF с высокой точностью, задав SpeechSynthesisOutputFormat
объект SpeechConfig
. Как и в примере из предыдущего раздела, мы будем использовать AudioDataStream
для получения результата в виде потока в памяти, а затем записывать его в файл.
public static void main(String[] args) {
SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
// set the output format
speechConfig.setSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
SpeechSynthesisResult result = speechSynthesizer.SpeakText("I'm excited to try text to speech");
AudioDataStream stream = AudioDataStream.fromResult(result);
stream.saveToWavFile("path/to/write/file.wav");
}
При запуске программы он записывает файл .wav в указанный путь.
Настройка характеристик речи с использованием SSML
SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в статье о руководстве по SSML.
Чтобы начать использовать SSML для настройки, необходимо внести незначительные изменения, которые переключают голос.
Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
В этом примере файл ssml.xml. Корневым элементом всегда является
<speak>
, а перенос текста в элемент<voice>
позволяет менять голос с помощью параметраname
. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос в основном совпадает. Вместо использования
SpeakText()
функции вы используетеSpeakSsml()
. Эта функция ожидает XML-строку, поэтому сначала создайте функцию для загрузки XML-файла и возвратите его в виде строки:private static String xmlToString(String filePath) { File file = new File(filePath); StringBuilder fileContents = new StringBuilder((int)file.length()); try (Scanner scanner = new Scanner(file)) { while(scanner.hasNextLine()) { fileContents.append(scanner.nextLine() + System.lineSeparator()); } return fileContents.toString().trim(); } catch (FileNotFoundException ex) { return "File not found."; } }
На этом этапе результирующий объект точно совпадает с предыдущими примерами:
public static void main(String[] args) { SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion"); SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null); String ssml = xmlToString("ssml.xml"); SpeechSynthesisResult result = speechSynthesizer.SpeakSsml(ssml); AudioDataStream stream = AudioDataStream.fromResult(result); stream.saveToWavFile("path/to/write/file.wav"); }
Примечание.
Чтобы изменить голос без использования SSML, задайте свойство SpeechConfig
с помощью .SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
Подписка на события синтезатора
Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
Мероприятие | Description | Вариант использования |
---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить отмену синтеза. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить при запуске синтеза. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят. |
Примечание.
События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".
Вы можете следовать инструкциям в кратком руководстве, но заменить содержимое этого файла SpeechSynthesis.java следующим кодом Java:
import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.audio.*;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
public class SpeechSynthesis {
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
private static String speechKey = System.getenv("SPEECH_KEY");
private static String speechRegion = System.getenv("SPEECH_REGION");
public static void main(String[] args) throws InterruptedException, ExecutionException {
SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
// Required for WordBoundary event sentences.
speechConfig.setProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");
String speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
String ssml = String.format("<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>"
.concat(String.format("<voice name='%s'>", speechSynthesisVoiceName))
.concat("<mstts:viseme type='redlips_front'/>")
.concat("The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.")
.concat("</voice>")
.concat("</speak>"));
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig);
{
// Subscribe to events
speechSynthesizer.BookmarkReached.addEventListener((o, e) -> {
System.out.println("BookmarkReached event:");
System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
System.out.println("\tText: " + e.getText());
});
speechSynthesizer.SynthesisCanceled.addEventListener((o, e) -> {
System.out.println("SynthesisCanceled event");
});
speechSynthesizer.SynthesisCompleted.addEventListener((o, e) -> {
SpeechSynthesisResult result = e.getResult();
byte[] audioData = result.getAudioData();
System.out.println("SynthesisCompleted event:");
System.out.println("\tAudioData: " + audioData.length + " bytes");
System.out.println("\tAudioDuration: " + result.getAudioDuration());
result.close();
});
speechSynthesizer.SynthesisStarted.addEventListener((o, e) -> {
System.out.println("SynthesisStarted event");
});
speechSynthesizer.Synthesizing.addEventListener((o, e) -> {
SpeechSynthesisResult result = e.getResult();
byte[] audioData = result.getAudioData();
System.out.println("Synthesizing event:");
System.out.println("\tAudioData: " + audioData.length + " bytes");
result.close();
});
speechSynthesizer.VisemeReceived.addEventListener((o, e) -> {
System.out.println("VisemeReceived event:");
System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
System.out.println("\tVisemeId: " + e.getVisemeId());
});
speechSynthesizer.WordBoundary.addEventListener((o, e) -> {
System.out.println("WordBoundary event:");
System.out.println("\tBoundaryType: " + e.getBoundaryType());
System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
System.out.println("\tDuration: " + e.getDuration());
System.out.println("\tText: " + e.getText());
System.out.println("\tTextOffset: " + e.getTextOffset());
System.out.println("\tWordLength: " + e.getWordLength());
});
// Synthesize the SSML
System.out.println("SSML to synthesize:");
System.out.println(ssml);
SpeechSynthesisResult speechSynthesisResult = speechSynthesizer.SpeakSsmlAsync(ssml).get();
if (speechSynthesisResult.getReason() == ResultReason.SynthesizingAudioCompleted) {
System.out.println("SynthesizingAudioCompleted result");
}
else if (speechSynthesisResult.getReason() == ResultReason.Canceled) {
SpeechSynthesisCancellationDetails cancellation = SpeechSynthesisCancellationDetails.fromResult(speechSynthesisResult);
System.out.println("CANCELED: Reason=" + cancellation.getReason());
if (cancellation.getReason() == CancellationReason.Error) {
System.out.println("CANCELED: ErrorCode=" + cancellation.getErrorCode());
System.out.println("CANCELED: ErrorDetails=" + cancellation.getErrorDetails());
System.out.println("CANCELED: Did you set the speech resource key and region values?");
}
}
}
speechSynthesizer.close();
System.exit(0);
}
}
Дополнительные текстовые примеры для речи можно найти на сайте GitHub.
Использование пользовательской конечной точки
Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов речи.
Одно из различий заключается в том, что EndpointId
его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью EndpointId
и SpeechSynthesisVoiceName
.
SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
speechConfig.setSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig.setEndpointId("YourEndpointId");
Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.
Справочные примеры пакета документации | (npm) | Дополнительные примеры в исходном коде библиотеки GitHub |
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Выбор языка и голоса для синтеза
Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.
Укажите язык или голос для сопоставления входного SpeechConfig
текста и используйте указанный голос:
function synthesizeSpeech() {
const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speechConfig.speechSynthesisLanguage = "en-US";
speechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
}
synthesizeSpeech();
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural
, текст говорится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.
Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.
- Если вы не задаете
SpeechSynthesisVoiceName
илиSpeechSynthesisLanguage
используете голосовую связь по умолчанию дляen-US
разговоров. - Если задано только значение по умолчанию для указанного языкового стандарта
SpeechSynthesisLanguage
. - Если заданы и
SpeechSynthesisVoiceName
, иSpeechSynthesisLanguage
, параметрSpeechSynthesisLanguage
игнорируется. Заданный голос с помощьюSpeechSynthesisVoiceName
речи. - Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),
SpeechSynthesisVoiceName
SpeechSynthesisLanguage
параметры игнорируются.
В итоге порядок приоритета можно описать следующим образом:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Результат |
---|---|---|---|
✗ | ✗ | ✗ | Голос по умолчанию для en-US разговоров |
✗ | ✔ | ✗ | Голосовая связь по умолчанию для указанного языкового стандарта. |
✔ | ✔ | ✗ | Заданный голос с помощью SpeechSynthesisVoiceName речи. |
✔ | ✔ | ✔ | Заданный голос с помощью SSML говорит. |
Синтезирование текста в речь
Чтобы вывести синтезированную речь на текущее активное выходное устройство, например динамик, создайте экземпляр AudioConfig
с помощью fromDefaultSpeakerOutput()
статической функции. Приведем пример:
function synthesizeSpeech() {
const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
const audioConfig = sdk.AudioConfig.fromDefaultSpeakerOutput();
const speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
speechSynthesizer.speakTextAsync(
"I'm excited to try text to speech",
result => {
if (result) {
speechSynthesizer.close();
return result.audioData;
}
},
error => {
console.log(error);
speechSynthesizer.close();
});
}
При запуске программы синтезированный звук воспроизводится из динамика. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ как поток в памяти для работы с пользовательскими сценариями.
Получение результата в виде потока в памяти
Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:
- абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
- интегрировать полученные данные с другими API или службами;
- изменять звуковые данные, записывать пользовательские заголовки
.wav
и выполнять другие связанные задачи.
Это изменение можно внести в предыдущий пример. Удалите блок, так как вы управляете AudioConfig
поведением выходных данных вручную с этого момента для повышения контроля. Затем передайте null
для AudioConfig
в конструкторе SpeechSynthesizer
.
Примечание.
AudioConfig
Передачаnull
, а не пропускание, как и в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.
Сохраните результат в переменной SpeechSynthesisResult . Свойство SpeechSynthesisResult.audioData
возвращает значение ArrayBuffer
выходных данных, тип потока браузера по умолчанию. Для кода на стороне сервера преобразуйте ArrayBuffer
в поток буфера.
Приведенный ниже код работает на стороне клиента:
function synthesizeSpeech() {
const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig);
speechSynthesizer.speakTextAsync(
"I'm excited to try text to speech",
result => {
speechSynthesizer.close();
return result.audioData;
},
error => {
console.log(error);
speechSynthesizer.close();
});
}
Вы можете реализовать любое пользовательское поведение с помощью результирующего ArrayBuffer
объекта. ArrayBuffer
— это распространенный тип для получения в браузере и воспроизведения из этого формата.
Для любого серверного кода, если необходимо работать с данными в виде потока, необходимо преобразовать в поток объект ArrayBuffer
.
function synthesizeSpeech() {
const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig);
speechSynthesizer.speakTextAsync(
"I'm excited to try text to speech",
result => {
const { audioData } = result;
speechSynthesizer.close();
// convert arrayBuffer to stream
// return stream
const bufferStream = new PassThrough();
bufferStream.end(Buffer.from(audioData));
return bufferStream;
},
error => {
console.log(error);
speechSynthesizer.close();
});
}
Настройка звукового формата
Можно настроить атрибуты вывода звука, в том числе:
- тип звукового файла;
- Частота выборки
- глубину в битах.
Чтобы изменить формат звука, используйте speechSynthesisOutputFormat
свойство объекта SpeechConfig
. Это свойство ожидает enum
экземпляр типа SpeechSynthesisOutputFormat. enum
Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.
Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm
, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.
- Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
- Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.
В этом примере указывается формат Riff24Khz16BitMonoPcm
RIFF с высокой точностью, задав speechSynthesisOutputFormat
объект SpeechConfig
. Как и в примере из предыдущего раздела, можно получить данные ArrayBuffer
для звука и взаимодействовать с ними.
function synthesizeSpeech() {
const speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
// Set the output format
speechConfig.speechSynthesisOutputFormat = sdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm;
const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, null);
speechSynthesizer.speakTextAsync(
"I'm excited to try text to speech",
result => {
// Interact with the audio ArrayBuffer data
const audioData = result.audioData;
console.log(`Audio data byte size: ${audioData.byteLength}.`)
speechSynthesizer.close();
},
error => {
console.log(error);
speechSynthesizer.close();
});
}
Настройка характеристик речи с использованием SSML
SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".
Чтобы начать использовать SSML для настройки, необходимо внести незначительные изменения, которые переключают голос.
Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
В этом примере ssml.xml. Корневым элементом всегда является
<speak>
, а перенос текста в элемент<voice>
позволяет менять голос с помощью параметраname
. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос аналогичен использовавшемуся нами ранее, но вместо функции
speakTextAsync()
содержитspeakSsmlAsync()
. Эта функция ожидает XML-строку. Создайте функцию для загрузки XML-файла и верните ее в виде строки:function xmlToString(filePath) { const xml = readFileSync(filePath, "utf8"); return xml; }
Дополнительные сведения о
readFileSync
см. здесь.Результирующий объект точно такой же, как и в предыдущих примерах:
function synthesizeSpeech() { const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion"); const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, null); const ssml = xmlToString("ssml.xml"); speechSynthesizer.speakSsmlAsync( ssml, result => { if (result.errorDetails) { console.error(result.errorDetails); } else { console.log(JSON.stringify(result)); } speechSynthesizer.close(); }, error => { console.log(error); speechSynthesizer.close(); }); }
Примечание.
Чтобы изменить голос без использования SSML, можно задать свойство в SpeechConfig
с помощью SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
.
Подписка на события синтезатора
Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
Мероприятие | Description | Вариант использования |
---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить отмену синтеза. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить при запуске синтеза. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят. |
Примечание.
События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".
Вы можете следовать инструкциям в кратком руководстве, но заменить содержимое этого файла SpeechSynthesis.js следующим кодом JavaScript.
(function() {
"use strict";
var sdk = require("microsoft-cognitiveservices-speech-sdk");
var audioFile = "YourAudioFile.wav";
// This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
const speechConfig = sdk.SpeechConfig.fromSubscription(process.env.SPEECH_KEY, process.env.SPEECH_REGION);
const audioConfig = sdk.AudioConfig.fromAudioFileOutput(audioFile);
var speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
var ssml = `<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'> \r\n \
<voice name='${speechSynthesisVoiceName}'> \r\n \
<mstts:viseme type='redlips_front'/> \r\n \
The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>. \r\n \
</voice> \r\n \
</speak>`;
// Required for WordBoundary event sentences.
speechConfig.setProperty(sdk.PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");
// Create the speech speechSynthesizer.
var speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig);
speechSynthesizer.bookmarkReached = function (s, e) {
var str = `BookmarkReached event: \
\r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
\r\n\tText: \"${e.text}\".`;
console.log(str);
};
speechSynthesizer.synthesisCanceled = function (s, e) {
console.log("SynthesisCanceled event");
};
speechSynthesizer.synthesisCompleted = function (s, e) {
var str = `SynthesisCompleted event: \
\r\n\tAudioData: ${e.result.audioData.byteLength} bytes \
\r\n\tAudioDuration: ${e.result.audioDuration}`;
console.log(str);
};
speechSynthesizer.synthesisStarted = function (s, e) {
console.log("SynthesisStarted event");
};
speechSynthesizer.synthesizing = function (s, e) {
var str = `Synthesizing event: \
\r\n\tAudioData: ${e.result.audioData.byteLength} bytes`;
console.log(str);
};
speechSynthesizer.visemeReceived = function(s, e) {
var str = `VisemeReceived event: \
\r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
\r\n\tVisemeId: ${e.visemeId}`;
console.log(str);
};
speechSynthesizer.wordBoundary = function (s, e) {
// Word, Punctuation, or Sentence
var str = `WordBoundary event: \
\r\n\tBoundaryType: ${e.boundaryType} \
\r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
\r\n\tDuration: ${e.duration} \
\r\n\tText: \"${e.text}\" \
\r\n\tTextOffset: ${e.textOffset} \
\r\n\tWordLength: ${e.wordLength}`;
console.log(str);
};
// Synthesize the SSML
console.log(`SSML to synthesize: \r\n ${ssml}`)
console.log(`Synthesize to: ${audioFile}`);
speechSynthesizer.speakSsmlAsync(ssml,
function (result) {
if (result.reason === sdk.ResultReason.SynthesizingAudioCompleted) {
console.log("SynthesizingAudioCompleted result");
} else {
console.error("Speech synthesis canceled, " + result.errorDetails +
"\nDid you set the speech resource key and region values?");
}
speechSynthesizer.close();
speechSynthesizer = null;
},
function (err) {
console.trace("err - " + err);
speechSynthesizer.close();
speechSynthesizer = null;
});
}());
Дополнительные текстовые примеры для речи можно найти на сайте GitHub.
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.
Справочный пакет документации | (скачивание) | Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Необходимые компоненты
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс службы "Речь" в портал Azure.
- Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.
Установка пакета SDK и примеров для службы "Речь"
Репозиторий Azure-Samples/cognitive-services-speech-sdk включает примеры, написанные на Objective-C для iOS и Mac. Щелкните ссылку, чтобы просмотреть инструкции по установке для каждого примера:
- Синтез речи в macOS с помощью Objective-C
- Синтез речи в iOS с помощью Objective-C
- Дополнительные примеры для Objective-C в iOS
Использование пользовательской конечной точки
Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов речи.
Одно из различий заключается в том, что EndpointId
его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью EndpointId
и SpeechSynthesisVoiceName
.
SPXSpeechConfiguration *speechConfig = [[SPXSpeechConfiguration alloc] initWithSubscription:speechKey region:speechRegion];
speechConfig.speechSynthesisVoiceName = @"YourCustomVoiceName";
speechConfig.EndpointId = @"YourEndpointId";
Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.
Справочный пакет документации | (скачивание) | Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Необходимые компоненты
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс службы "Речь" в портал Azure.
- Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.
Установка пакета SDK и примеров для службы "Речь"
Репозиторий Azure-Samples/cognitive-services-speech-sdk включает примеры, написанные на Swift для iOS и Mac. Щелкните ссылку, чтобы просмотреть инструкции по установке для каждого примера:
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.
Справочные примеры пакета документации | (PyPi) | Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Выбор языка и голоса для синтеза
Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.
Укажите язык или голос для сопоставления входного SpeechConfig
текста и используйте указанный голос:
# Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speech_config.speech_synthesis_language = "en-US"
speech_config.speech_synthesis_voice_name ="en-US-AvaMultilingualNeural"
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural
, текст говорится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.
Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.
- Если вы не задаете
SpeechSynthesisVoiceName
илиSpeechSynthesisLanguage
используете голосовую связь по умолчанию дляen-US
разговоров. - Если задано только значение по умолчанию для указанного языкового стандарта
SpeechSynthesisLanguage
. - Если заданы и
SpeechSynthesisVoiceName
, иSpeechSynthesisLanguage
, параметрSpeechSynthesisLanguage
игнорируется. Заданный голос с помощьюSpeechSynthesisVoiceName
речи. - Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),
SpeechSynthesisVoiceName
SpeechSynthesisLanguage
параметры игнорируются.
В итоге порядок приоритета можно описать следующим образом:
SpeechSynthesisVoiceName |
SpeechSynthesisLanguage |
SSML | Результат |
---|---|---|---|
✗ | ✗ | ✗ | Голос по умолчанию для en-US разговоров |
✗ | ✔ | ✗ | Голосовая связь по умолчанию для указанного языкового стандарта. |
✔ | ✔ | ✗ | Заданный голос с помощью SpeechSynthesisVoiceName речи. |
✔ | ✔ | ✔ | Заданный голос с помощью SSML говорит. |
Синтезирование речи в файл
Создайте объект SpeechSynthesizer. Этот объект выполняет текст для преобразования речи и выходных данных в динамики, файлы или другие выходные потоки. SpeechSynthesizer
принимает в качестве параметров:
- Объект
SpeechConfig
, созданный на предыдущем шаге. - Объект, указывающий
AudioOutputConfig
способ обработки выходных результатов.
AudioOutputConfig
Создайте экземпляр для автоматической записи выходных данных в файл .wav с помощью параметра конструктораfilename
:audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
Создайте
SpeechSynthesizer
экземпляр, передав объектspeech_config
иaudio_config
объект в качестве параметров. Чтобы синтезировать речь и записывать в файл, запуститеspeak_text_async()
строку текста.speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config) speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
При запуске программы создается синтезированный .wav-файл , который записывается в указанное расположение. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ в виде потока в памяти для работы с пользовательскими сценариями.
Синтезирование выходных данных для вывода на динамики
Чтобы вывести синтезированную речь на текущее активное выходное устройство, например динамик, задайте use_default_speaker
параметр при создании экземпляра AudioOutputConfig
. Приведем пример:
audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)
Получение результата в виде потока в памяти
Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:
- абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
- интегрировать полученные данные с другими API или службами;
- Измените звуковые данные, напишите пользовательские .wav заголовки и выполните связанные задачи.
Это изменение можно внести в предыдущий пример. Во-первых, удалите AudioConfig
, так как вы управляете поведением выходных данных вручную с этого момента для повышения контроля. Передайте None
в AudioConfig
SpeechSynthesizer
конструктор.
Примечание.
AudioConfig
ПередачаNone
, а не пропускание, как и в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.
Сохраните результат в переменной SpeechSynthesisResult
. Свойство audio_data
содержит объект bytes
выходных данных. Вы можете работать с этим объектом вручную или использовать класс AudioDataStream
для управления потоком в памяти.
В этом примере используйте AudioDataStream
конструктор для получения потока из результата:
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(speech_synthesis_result)
На этом этапе можно реализовать любое пользовательское поведение с помощью результирующего stream
объекта.
Настройка звукового формата
Можно настроить атрибуты вывода звука, в том числе:
- тип звукового файла;
- Частота выборки
- глубину в битах.
Чтобы изменить формат звука, используйте set_speech_synthesis_output_format()
функцию в объекте SpeechConfig
. Эта функция ожидает enum
экземпляр типа SpeechSynthesisOutputFormat. enum
Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.
Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm
, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.
- Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
- Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.
В этом примере указывается формат Riff24Khz16BitMonoPcm
RIFF с высокой точностью, задав SpeechSynthesisOutputFormat
объект SpeechConfig
. Как и в примере из предыдущего раздела, мы будем использовать AudioDataStream
для получения результата в виде потока в памяти, а затем записывать его в файл.
speech_config.set_speech_synthesis_output_format(speechsdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(speech_synthesis_result)
stream.save_to_wav_file("path/to/write/file.wav")
При запуске программы он записывает файл .wav в указанный путь.
Настройка характеристик речи с использованием SSML
SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".
Чтобы начать использовать SSML для настройки, внесите незначительные изменения, которые переключают голос.
Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US"> <voice name="en-US-AvaMultilingualNeural"> When you're on the freeway, it's a good idea to use a GPS. </voice> </speak>
В этом примере файл ssml.xml. Корневым элементом всегда является
<speak>
, а перенос текста в элемент<voice>
позволяет менять голос с помощью параметраname
. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос в основном совпадает. Вместо использования
speak_text_async()
функции используйтеspeak_ssml_async()
. Эта функция ожидает XML-строку. Сначала считывает конфигурацию SSML в виде строки. С этого момента объект результата точно совпадает с предыдущими примерами.Примечание.
Если
ssml_string
содержит
в начале строки, необходимо удалить метку порядка байтов, иначе служба вернет ошибку. Это можно сделать, задав параметруencoding
такие параметры:open("ssml.xml", "r", encoding="utf-8-sig")
.speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None) ssml_string = open("ssml.xml", "r").read() speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml_string).get() stream = speechsdk.AudioDataStream(speech_synthesis_result) stream.save_to_wav_file("path/to/write/file.wav")
Примечание.
Чтобы изменить голос без использования SSML, можно задать свойство в SpeechConfig
с помощью speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural"
.
Подписка на события синтезатора
Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
Мероприятие | Description | Вариант использования |
---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить отмену синтеза. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить при запуске синтеза. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят. |
Примечание.
События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".
Вы можете выполнить инструкции в кратком руководстве, но заменить содержимое этого файла speech-synthesis.py следующим кодом Python:
import os
import azure.cognitiveservices.speech as speechsdk
def speech_synthesizer_bookmark_reached_cb(evt: speechsdk.SessionEventArgs):
print('BookmarkReached event:')
print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
print('\tText: {}'.format(evt.text))
def speech_synthesizer_synthesis_canceled_cb(evt: speechsdk.SessionEventArgs):
print('SynthesisCanceled event')
def speech_synthesizer_synthesis_completed_cb(evt: speechsdk.SessionEventArgs):
print('SynthesisCompleted event:')
print('\tAudioData: {} bytes'.format(len(evt.result.audio_data)))
print('\tAudioDuration: {}'.format(evt.result.audio_duration))
def speech_synthesizer_synthesis_started_cb(evt: speechsdk.SessionEventArgs):
print('SynthesisStarted event')
def speech_synthesizer_synthesizing_cb(evt: speechsdk.SessionEventArgs):
print('Synthesizing event:')
print('\tAudioData: {} bytes'.format(len(evt.result.audio_data)))
def speech_synthesizer_viseme_received_cb(evt: speechsdk.SessionEventArgs):
print('VisemeReceived event:')
print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
print('\tVisemeId: {}'.format(evt.viseme_id))
def speech_synthesizer_word_boundary_cb(evt: speechsdk.SessionEventArgs):
print('WordBoundary event:')
print('\tBoundaryType: {}'.format(evt.boundary_type))
print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
print('\tDuration: {}'.format(evt.duration))
print('\tText: {}'.format(evt.text))
print('\tTextOffset: {}'.format(evt.text_offset))
print('\tWordLength: {}'.format(evt.word_length))
# This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))
# Required for WordBoundary event sentences.
speech_config.set_property(property_id=speechsdk.PropertyId.SpeechServiceResponse_RequestSentenceBoundary, value='true')
audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
# Subscribe to events
speech_synthesizer.bookmark_reached.connect(speech_synthesizer_bookmark_reached_cb)
speech_synthesizer.synthesis_canceled.connect(speech_synthesizer_synthesis_canceled_cb)
speech_synthesizer.synthesis_completed.connect(speech_synthesizer_synthesis_completed_cb)
speech_synthesizer.synthesis_started.connect(speech_synthesizer_synthesis_started_cb)
speech_synthesizer.synthesizing.connect(speech_synthesizer_synthesizing_cb)
speech_synthesizer.viseme_received.connect(speech_synthesizer_viseme_received_cb)
speech_synthesizer.synthesis_word_boundary.connect(speech_synthesizer_word_boundary_cb)
# The language of the voice that speaks.
speech_synthesis_voice_name='en-US-AvaMultilingualNeural'
ssml = """<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
<voice name='{}'>
<mstts:viseme type='redlips_front'/>
The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
</voice>
</speak>""".format(speech_synthesis_voice_name)
# Synthesize the SSML
print("SSML to synthesize: \r\n{}".format(ssml))
speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml).get()
if speech_synthesis_result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted:
print("SynthesizingAudioCompleted result")
elif speech_synthesis_result.reason == speechsdk.ResultReason.Canceled:
cancellation_details = speech_synthesis_result.cancellation_details
print("Speech synthesis canceled: {}".format(cancellation_details.reason))
if cancellation_details.reason == speechsdk.CancellationReason.Error:
if cancellation_details.error_details:
print("Error details: {}".format(cancellation_details.error_details))
print("Did you set the speech resource key and region values?")
Дополнительные текстовые примеры для речи можно найти на сайте GitHub.
Использование пользовательской конечной точки
Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов речи.
Одно из различий заключается в том, что endpoint_id
его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью endpoint_id
и speech_synthesis_voice_name
.
speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))
speech_config.endpoint_id = "YourEndpointId"
speech_config.speech_synthesis_voice_name = "YourCustomVoiceName"
Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName
.
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
<voice name="YourCustomVoiceName">
This is the text that is spoken.
</voice>
</speak>
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.
Преобразование речи в текст REST API ссылки на | речь на текстовый REST API для краткой справки по звуковой ссылке | на Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Необходимые компоненты
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс службы "Речь" в портал Azure.
- Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.
Преобразование текста в речь
В командной строке выполните приведенную ниже команду. Вставьте эти значения в команду:
- Ключ ресурса службы "Речь"
- Регион ресурса "Речь"
Также может потребоваться изменить следующие значения:
- Значение заголовка
X-Microsoft-OutputFormat
, которое определяет формат аудиовыхода. Список поддерживаемых форматов звуковых выходных данных можно найти в справочнике по REST API речи. - Голос речевого вывода. Чтобы получить список голосов, доступных для конечной точки службы "Речь", см. API голосового списка.
- Выходной файл. В этом примере мы направляем ответ от сервера в файл
output.mp3
.
curl --location --request POST 'https://YOUR_RESOURCE_REGION.tts.speech.microsoft.com/cognitiveservices/v1' \
--header 'Ocp-Apim-Subscription-Key: YOUR_RESOURCE_KEY' \
--header 'Content-Type: application/ssml+xml' \
--header 'X-Microsoft-OutputFormat: audio-16khz-128kbitrate-mono-mp3' \
--header 'User-Agent: curl' \
--data-raw '<speak version='\''1.0'\'' xml:lang='\''en-US'\''>
<voice name='\''en-US-AvaMultilingualNeural'\''>
I am excited to try text to speech
</voice>
</speak>' > output.mp3
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписывание на события и выполнение результатов.
Необходимые компоненты
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс службы "Речь" в портал Azure.
- Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.
Загрузка и установка
Выполните следующие действия и ознакомьтесь с кратким руководством по интерфейсу командной строки службы "Речь" для других требований для платформы.
Выполните следующую команду .NET CLI, чтобы установить интерфейс командной строки службы "Речь".
dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
Выполните следующие команды, чтобы настроить ключ ресурса службы "Речь" и регион. Замените ключом ресурса "Речь" и замените
SUBSCRIPTION-KEY
REGION
регионом ресурсов службы "Речь".spx config @key --set SUBSCRIPTION-KEY spx config @region --set REGION
Синтезирование речи в виде речи докладчика
Итак, все готово для запуска интерфейса командной строки службы "Речь" для синтезирования речи из текста.
В окне консоли перейдите в каталог, содержащий двоичный файл интерфейса командной строки службы "Речь". Затем выполните следующую команду.
spx synthesize --text "I'm excited to try text to speech"
Интерфейс командной строки службы "Речь" создает естественный язык на английском языке через динамик компьютера.
Синтезирование речи в файл
Выполните следующую команду, чтобы изменить выходные данные докладчика на файл .wav :
spx synthesize --text "I'm excited to try text to speech" --audio output greetings.wav
Интерфейс командной строки службы "Речь" создает естественный язык на английском языке в greetings.wav звуковой файл.
Запуск и использование контейнера
Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.