Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
API REST преобразования речи в текст: справка | API REST преобразования речи в текст для краткой аудиозаписи: справка | Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи из текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписка на события и реагирование на результаты.
Предварительные требования
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс Foundry для функции «Речь» на портале 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-Ava:DragonHDLatestNeural'\''>
I am excited to try text to speech
</voice>
</speak>' > output.mp3
Справочные примеры пакета документации | (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-Ava:DragonHDLatestNeural"
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Мне не терпится попробовать озвучивание текста", и вы выбираете es-ES-Ximena:DragonHDLatestNeural, текст произносится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный по каждому языковому стандарту из Voice List 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 в AudioConfigSpeechSynthesizer конструктор.
Примечание.
NoneПередача AudioConfig вместо его пропуска, как в предыдущем примере, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.
Сохраните результат в переменной 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-Ava:DragonHDLatestNeural"> 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содержитв начале строки, необходимо удалить метку порядка байтов (BOM), иначе служба вернет ошибку. Это можно сделать, задав параметру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-Ava:DragonHDLatestNeural".
Подпишитесь на события синтезатора
Вам может потребоваться больше сведений о преобразовании текста в речь и результатах. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
| Мероприятие | Описание | Вариант использования |
|---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, в bookmark требуется элемент . Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не произносятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить, что синтез отменен. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить, когда начался синтез. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления ключевых поз в речи часто используются виземы. Ключевые позы включают положение губ, челюсти и языка при произнесении определенной фонемы. Вы можете использовать виземы для анимации лица персонажа, синхронизируя её с воспроизведением речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового произнесённого слова, знака препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова по мере их произнесения. |
Примечание.
События инициируются по мере того, как выходные аудиоданные становятся доступны, и это происходит быстрее, чем их воспроизведение через выходное устройство. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Используйте ключи API с осторожностью. Не включайте ключ API непосредственно в код и никогда не публикуйте его. Если вы используете ключ API, сохраните его безопасно в Azure Key Vault. Дополнительные сведения об использовании ключей API безопасно в приложениях см. в разделе "Ключи API" с помощью Azure Key Vault.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ 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.
Справочная документация | Пакет (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-Ava:DragonHDLatestNeural";
}
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке — это "Мне интересно попробовать технологию текст в речь", и вы выбираете es-ES-Ximena:DragonHDLatestNeural, текст произносится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный по каждому языковому стандарту из Voice List 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 в AudioConfigSpeechSynthesizer конструктор.
Примечание.
nullПередача AudioConfig, вместо его пропуска, как в предыдущем примере вывода звука, по умолчанию не воспроизводит аудио на текущем активном выходном устройстве.
Сохраните результат в переменной 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-Ava:DragonHDLatestNeural"> 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-Ava:DragonHDLatestNeural";.
Подпишитесь на события синтезатора
Вам может потребоваться больше сведений о преобразовании текста в речь и результатах. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
| Мероприятие | Описание | Вариант использования |
|---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, в bookmark требуется элемент . Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не произносятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить, что синтез отменен. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить, когда начался синтез. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления ключевых поз в речи часто используются виземы. Ключевые позы включают положение губ, челюсти и языка при произнесении определенной фонемы. Вы можете использовать виземы для анимации лица персонажа, синхронизируя её с воспроизведением речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового произнесённого слова, знака препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова по мере их произнесения. |
Примечание.
События инициируются по мере того, как выходные аудиоданные становятся доступны, и это происходит быстрее, чем их воспроизведение через выходное устройство. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Используйте ключи API с осторожностью. Не включайте ключ API непосредственно в код и никогда не публикуйте его. Если вы используете ключ API, сохраните его безопасно в Azure Key Vault. Дополнительные сведения об использовании ключей API безопасно в приложениях см. в разделе "Ключи API" с помощью Azure Key Vault.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ 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.
Справочная документация | Пакет (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-Ava:DragonHDLatestNeural";
}
synthesizeSpeech();
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Мне не терпится попробовать озвучивание текста", и вы выбираете es-ES-Ximena:DragonHDLatestNeural, текст произносится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный по каждому языковому стандарту из Voice List 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.
Примечание.
nullПередача AudioConfig вместо его пропуска, как в предыдущем примере, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.
Сохраните результат в переменной 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-Ava:DragonHDLatestNeural"> 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см. в разделе Файловая система Node.js.Результирующий объект точно такой же, как и в предыдущих примерах:
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-Ava:DragonHDLatestNeural";.
Подпишитесь на события синтезатора
Вам может потребоваться больше сведений о преобразовании текста в речь и результатах. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
| Мероприятие | Описание | Вариант использования |
|---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, в bookmark требуется элемент . Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не произносятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить, что синтез отменен. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить, когда начался синтез. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления ключевых поз в речи часто используются виземы. Ключевые позы включают положение губ, челюсти и языка при произнесении определенной фонемы. Вы можете использовать виземы для анимации лица персонажа, синхронизируя её с воспроизведением речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового произнесённого слова, знака препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова по мере их произнесения. |
Примечание.
События инициируются по мере того, как выходные аудиоданные становятся доступны, и это происходит быстрее, чем их воспроизведение через выходное устройство. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Используйте ключи API с осторожностью. Не включайте ключ API непосредственно в код и никогда не публикуйте его. Если вы используете ключ API, сохраните его безопасно в Azure Key Vault. Дополнительные сведения об использовании ключей API безопасно в приложениях см. в разделе "Ключи API" с помощью Azure Key Vault.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ 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 (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписка на события и реагирование на результаты.
Выбор языка и голоса для синтеза
Функция преобразования текста в речь в службе "Речь" поддерживает более 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-Ava:DragonHDLatestNeural");
}
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Мне не терпится попробовать озвучивание текста", и вы выбираете es-ES-Ximena:DragonHDLatestNeural, текст произносится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный по каждому языковому стандарту из Voice List 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.
Примечание.
nullПередача AudioConfig вместо его пропуска, как в предыдущем примере, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.
Сохраните результат в переменной 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-Ava:DragonHDLatestNeural"> 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-Ava:DragonHDLatestNeural");.
Подпишитесь на события синтезатора
Вам может потребоваться больше сведений о преобразовании текста в речь и результатах. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
| Мероприятие | Описание | Вариант использования |
|---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, в bookmark требуется элемент . Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не произносятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить, что синтез отменен. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить, когда начался синтез. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления ключевых поз в речи часто используются виземы. Ключевые позы включают положение губ, челюсти и языка при произнесении определенной фонемы. Вы можете использовать виземы для анимации лица персонажа, синхронизируя её с воспроизведением речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового произнесённого слова, знака препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова по мере их произнесения. |
Примечание.
События инициируются по мере того, как выходные аудиоданные становятся доступны, и это происходит быстрее, чем их воспроизведение через выходное устройство. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Используйте ключи API с осторожностью. Не включайте ключ API непосредственно в код и никогда не публикуйте его. Если вы используете ключ API, сохраните его безопасно в Azure Key Vault. Дополнительные сведения об использовании ключей API безопасно в приложениях см. в разделе "Ключи API" с помощью Azure Key Vault.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ 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.
Справочная документация | Пакет (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-Ava:DragonHDLatestNeural");
}
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Мне не терпится попробовать озвучивание текста", и вы выбираете es-ES-Ximena:DragonHDLatestNeural, текст произносится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный по каждому языковому стандарту из Voice List 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 в AudioConfigSpeechSynthesizer конструктор.
Примечание.
NULLПередача AudioConfig, вместо его пропуска, как в предыдущем примере вывода звука, по умолчанию не воспроизводит аудио на текущем активном выходном устройстве.
Сохраните результат в переменной 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-Ava:DragonHDLatestNeural"> 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-Ava:DragonHDLatestNeural").
Подпишитесь на события синтезатора
Вам может потребоваться больше сведений о преобразовании текста в речь и результатах. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
| Мероприятие | Описание | Вариант использования |
|---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, в bookmark требуется элемент . Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не произносятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить, что синтез отменен. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить, когда начался синтез. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления ключевых поз в речи часто используются виземы. Ключевые позы включают положение губ, челюсти и языка при произнесении определенной фонемы. Вы можете использовать виземы для анимации лица персонажа, синхронизируя её с воспроизведением речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового произнесённого слова, знака препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова по мере их произнесения. |
Примечание.
События инициируются по мере того, как выходные аудиоданные становятся доступны, и это происходит быстрее, чем их воспроизведение через выходное устройство. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Используйте ключи API с осторожностью. Не включайте ключ API непосредственно в код и никогда не публикуйте его. Если вы используете ключ API, сохраните его безопасно в Azure Key Vault. Дополнительные сведения об использовании ключей API безопасно в приложениях см. в разделе "Ключи API" с помощью Azure Key Vault.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ 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 (std::string(speechKey).empty() || std::string(endpoint).empty()) {
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. Вы можете создать бесплатную учетную запись.
- Создайте ресурс Foundry для функции «Речь» на портале Azure.
- Получите ключ ресурса 'Речь' и регион. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу, чтобы просмотреть ключи и управлять ими.
Установка SDK пакета Речи
Прежде чем выполнять какие-либо действия, необходимо установить Speech 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-Ava:DragonHDLatestNeural")
Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Мне не терпится попробовать озвучивание текста", и вы выбираете es-ES-Ximena:DragonHDLatestNeural, текст произносится на английском языке с испанским акцентом.
Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".
Примечание.
Голос по умолчанию — это первый голос, возвращенный по каждому языковому стандарту из Voice List 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-Ava:DragonHDLatestNeural">
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-Ava:DragonHDLatestNeural").
Подпишитесь на события синтезатора
Вам может потребоваться больше сведений о преобразовании текста в речь и результатах. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.
Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:
| Мероприятие | Описание | Вариант использования |
|---|---|---|
BookmarkReached |
Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, в bookmark требуется элемент . Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не произносятся. |
Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов. |
SynthesisCanceled |
Сигнализирует о том, что синтез речи был отменен. | Вы можете подтвердить, что синтез отменен. |
SynthesisCompleted |
Сигнализирует о завершении синтеза речи. | Вы можете подтвердить завершение синтеза. |
SynthesisStarted |
Сигнализирует о начале синтеза речи. | Вы можете подтвердить, когда начался синтез. |
Synthesizing |
Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". | Вы можете подтвердить, когда выполняется синтез. |
VisemeReceived |
Сигнализирует о получении события viseme. | Для представления ключевых поз в речи часто используются виземы. Ключевые позы включают положение губ, челюсти и языка при произнесении определенной фонемы. Вы можете использовать виземы для анимации лица персонажа, синхронизируя её с воспроизведением речи. |
WordBoundary |
Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового произнесённого слова, знака препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. | Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова по мере их произнесения. |
Примечание.
События инициируются по мере того, как выходные аудиоданные становятся доступны, и это происходит быстрее, чем их воспроизведение через выходное устройство. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.
Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.
Внимание
Используйте ключи API с осторожностью. Не включайте ключ API непосредственно в код и никогда не публикуйте его. Если вы используете ключ API, сохраните его безопасно в Azure Key Vault. Дополнительные сведения об использовании ключей API безопасно в приложениях см. в разделе "Ключи API" с помощью Azure Key Vault.
Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ 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 (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписка на события и реагирование на результаты.
Предварительные требования
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс Foundry для функции «Речь» на портале Azure.
- Получите ключ ресурса 'Речь' и регион. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу, чтобы просмотреть ключи и управлять ими.
Установка Speech 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.
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи из текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписка на события и реагирование на результаты.
Предварительные требования
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс Foundry для функции «Речь» на портале Azure.
- Получите ключ ресурса 'Речь' и регион. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу, чтобы просмотреть ключи и управлять ими.
Загрузка и установка
Выполните следующие действия и ознакомьтесь с кратким руководством по интерфейсу командной строки службы распознавания речи для других требований к вашей платформе.
Выполните следующую команду .NET CLI, чтобы установить Speech CLI.
dotnet tool install --global Microsoft.CognitiveServices.Speech.CLIВыполните следующие команды, чтобы настроить ключ вашего ресурса 'Speech' и регион. Замените
SUBSCRIPTION-KEYвашим ключом ресурса для сервиса 'Speech' иREGIONвашим регионом ресурса для сервиса 'Speech'.spx config @key --set SUBSCRIPTION-KEY spx config @region --set REGION
Синтез речи для говорящего
Итак, все готово для запуска интерфейса командной строки службы "Речь" для синтезирования речи из текста.
В окне консоли перейдите в каталог, содержащий двоичный файл интерфейса командной строки Speech CLI. Затем выполните следующую команду.
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.
Справочный пакет документации | (скачивание) | Дополнительные примеры на GitHub
В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи из текста.
Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?
- Получение ответов в виде потоков в памяти.
- Настройка частоты выборки и скорости передачи выходных данных.
- Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
- Использование нейронных голосовых моделей.
- Подписка на события и реагирование на результаты.
Предварительные требования
- Подписка Azure. Вы можете создать бесплатную учетную запись.
- Создайте ресурс Foundry для функции «Речь» на портале Azure.
- Получите ключ ресурса 'Речь' и регион. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу, чтобы просмотреть ключи и управлять ими.
Установка Speech SDK и образцов
Репозиторий Azure-Samples/cognitive-services-speech-sdk включает примеры, написанные на Swift для iOS и Mac. Щелкните ссылку, чтобы просмотреть инструкции по установке для каждого примера:
Запуск и использование контейнера
Контейнеры распознавания речи предоставляют API конечных точек для запросов на основе websocket, которые доступны через SDK для работы с речью и CLI для работы с речью. По умолчанию пакет SDK службы Речь и CLI службы Речь используют публичную службу Речь. Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.
Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.