Бөлісу құралы:


Синтезирование речи на основе текста

Справочные примеры пакета документации | (NuGet) | Дополнительные примеры на GitHub

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Выбор языка и голоса для синтеза

Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.

Укажите язык или голос для сопоставления входного SpeechConfig текста и используйте указанный голос. В следующем фрагменте кода показано, как работает этот метод:

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig.SpeechSynthesisLanguage = "en-US"; 
    speechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
}

Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке, это "я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural, текст говорится на английском языке с испанским акцентом.

Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".

Примечание.

Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.

Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.

  • Если вы не задаете SpeechSynthesisVoiceName или SpeechSynthesisLanguageиспользуете голосовую связь по умолчанию для en-US разговоров.
  • Если задано только значение по умолчанию для указанного языкового стандарта SpeechSynthesisLanguage.
  • Если заданы и SpeechSynthesisVoiceName, и SpeechSynthesisLanguage, параметр SpeechSynthesisLanguage игнорируется. Заданный голос с помощью SpeechSynthesisVoiceName речи.
  • Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),SpeechSynthesisVoiceName SpeechSynthesisLanguage параметры игнорируются.

В итоге порядок приоритета можно описать следующим образом:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Результат
Голос по умолчанию для en-US разговоров
Голосовая связь по умолчанию для указанного языкового стандарта.
Заданный голос с помощью SpeechSynthesisVoiceName речи.
Заданный голос с помощью SSML говорит.

Синтезирование речи в файл

Создайте объект SpeechSynthesizer. Этот объект, показанный в следующих фрагментах кода, выполняет преобразование речи и выходные данные в динамики, файлы или другие выходные потоки. SpeechSynthesizer принимает в качестве параметров:

  1. 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 в этом контексте автоматически удаляет неуправляемые ресурсы и выводит объект из области после его удаления.

  2. Создайте SpeechSynthesizer экземпляр с другой using инструкцией. Передайте объекты speechConfig и audioConfig в качестве параметров. Чтобы синтезировать речь и записывать в файл, запустите SpeakTextAsync() строку текста.

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    using var audioConfig = AudioConfig.FromWavFileOutput("path/to/write/file.wav");
    using var speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
}

При запуске программы создается синтезированный .wav-файл , который записывается в указанное расположение. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ в виде потока в памяти для работы с пользовательскими сценариями.

Синтезирование выходных данных для вывода на динамики

Чтобы вывести синтезированную речь на текущее активное выходное устройство, например динамик, опустите AudioConfig параметр при создании экземпляра SpeechSynthesizer . Приведем пример:

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    using var speechSynthesizer = new SpeechSynthesizer(speechConfig);
    await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
}

Получение результата в виде потока в памяти

Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:

  • абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
  • интегрировать полученные данные с другими API или службами;
  • изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.

Это изменение можно внести в предыдущий пример. Во-первых, удалите AudioConfig блок, так как вы управляете поведением выходных данных вручную с этой точки, чтобы увеличить контроль. Передайте null в AudioConfig SpeechSynthesizer конструктор.

Примечание.

AudioConfigПередача null для , а не опущений, как в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.

Сохраните результат в переменной SpeechSynthesisResult . Свойство AudioData содержит экземпляр byte [] выходных данных. Вы можете работать с этим byte [] экземпляром вручную или использовать класс AudioDataStream для управления потоком в памяти.

В этом примере используется статическая функция AudioDataStream.FromResult() для получения потока из результата:

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);

    var result = await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");
    using var stream = AudioDataStream.FromResult(result);
}

На этом этапе можно реализовать любое пользовательское поведение с помощью результирующего stream объекта.

Настройка звукового формата

Можно настроить атрибуты вывода звука, в том числе:

  • тип звукового файла;
  • Частота выборки
  • глубину в битах.

Чтобы изменить звуковой формат, используйте функцию SetSpeechSynthesisOutputFormat() для объекта SpeechConfig. Эта функция ожидает enum экземпляр типа SpeechSynthesisOutputFormat. enum Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.

Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.

  • Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
  • Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.

В этом примере указывается формат Riff24Khz16BitMonoPcm RIFF с высокой точностью, задав SpeechSynthesisOutputFormat объект SpeechConfig . Как и в примере в предыдущем разделе, вы используете AudioDataStream для получения потока результата в памяти, а затем записываете его в файл.

static async Task SynthesizeAudioAsync()
{
    var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
    speechConfig.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);

    using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
    var result = await speechSynthesizer.SpeakTextAsync("I'm excited to try text to speech");

    using var stream = AudioDataStream.FromResult(result);
    await stream.SaveToWaveFileAsync("path/to/write/file.wav");
}

При запуске программы он записывает файл .wav в указанный путь.

Настройка характеристик речи с использованием SSML

SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".

Чтобы начать использовать SSML для настройки, необходимо внести незначительные изменения, которые переключают голос.

  1. Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.

    <speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
      <voice name="en-US-AvaMultilingualNeural">
        When you're on the freeway, it's a good idea to use a GPS.
      </voice>
    </speak>
    

    В этом примере файл ssml.xml. Корневым элементом всегда является <speak>, а перенос текста в элемент <voice> позволяет менять голос с помощью параметра name. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.

  2. Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос аналогичен использовавшемуся нами ранее, но вместо функции SpeakTextAsync() содержит SpeakSsmlAsync(). Эта функция ожидает XML-строку. Сначала загрузите конфигурацию SSML в виде строки с помощью File.ReadAllText(). С этого момента объект результата точно совпадает с предыдущими примерами.

    Примечание.

    Если вы используете Visual Studio, то конфигурация сборки вероятнее всего не найдет XML-файл по умолчанию. Щелкните ПРАВОй кнопкой мыши XML-файл и выберите "Свойства". Изменение действия сборки на содержимое. Всегда изменяйте копирование в выходной каталог для копирования.

    public static async Task SynthesizeAudioAsync()
    {
        var speechConfig = SpeechConfig.FromSubscription("YourSpeechKey", "YourSpeechRegion");
        using var speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
    
        var ssml = File.ReadAllText("./ssml.xml");
        var result = await speechSynthesizer.SpeakSsmlAsync(ssml);
    
        using var stream = AudioDataStream.FromResult(result);
        await stream.SaveToWaveFileAsync("path/to/write/file.wav");
    }
    

Примечание.

Чтобы изменить голос без использования SSML, можно задать свойство в SpeechConfig с помощью SpeechConfig.SpeechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

Подписка на события синтезатора

Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.

Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:

Мероприятие Description Вариант использования
BookmarkReached Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов.
SynthesisCanceled Сигнализирует о том, что синтез речи был отменен. Вы можете подтвердить отмену синтеза.
SynthesisCompleted Сигнализирует о завершении синтеза речи. Вы можете подтвердить завершение синтеза.
SynthesisStarted Сигнализирует о начале синтеза речи. Вы можете подтвердить при запуске синтеза.
Synthesizing Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". Вы можете подтвердить, когда выполняется синтез.
VisemeReceived Сигнализирует о получении события viseme. Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи.
WordBoundary Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят.

Примечание.

События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.

Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.

Внимание

Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.

Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".

Вы можете следовать инструкциям в кратком руководстве, но замените содержимое этого файла Program.cs следующим кодом C#:

using Microsoft.CognitiveServices.Speech;

class Program 
{
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    static string speechKey = Environment.GetEnvironmentVariable("SPEECH_KEY");
    static string speechRegion = Environment.GetEnvironmentVariable("SPEECH_REGION");

    async static Task Main(string[] args)
    {
        var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);
         
        var speechSynthesisVoiceName  = "en-US-AvaMultilingualNeural";  
        var ssml = @$"<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
            <voice name='{speechSynthesisVoiceName}'>
                <mstts:viseme type='redlips_front'/>
                The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
            </voice>
        </speak>";

        // Required for sentence-level WordBoundary events
        speechConfig.SetProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");

        using (var speechSynthesizer = new SpeechSynthesizer(speechConfig))
        {
            // Subscribe to events

            speechSynthesizer.BookmarkReached += (s, e) =>
            {
                Console.WriteLine($"BookmarkReached event:" +
                    $"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
                    $"\r\n\tText: \"{e.Text}\".");
            };

            speechSynthesizer.SynthesisCanceled += (s, e) =>
            {
                Console.WriteLine("SynthesisCanceled event");
            };

            speechSynthesizer.SynthesisCompleted += (s, e) =>
            {                
                Console.WriteLine($"SynthesisCompleted event:" +
                    $"\r\n\tAudioData: {e.Result.AudioData.Length} bytes" +
                    $"\r\n\tAudioDuration: {e.Result.AudioDuration}");
            };

            speechSynthesizer.SynthesisStarted += (s, e) =>
            {
                Console.WriteLine("SynthesisStarted event");
            };

            speechSynthesizer.Synthesizing += (s, e) =>
            {
                Console.WriteLine($"Synthesizing event:" +
                    $"\r\n\tAudioData: {e.Result.AudioData.Length} bytes");
            };

            speechSynthesizer.VisemeReceived += (s, e) =>
            {
                Console.WriteLine($"VisemeReceived event:" +
                    $"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
                    $"\r\n\tVisemeId: {e.VisemeId}");
            };

            speechSynthesizer.WordBoundary += (s, e) =>
            {
                Console.WriteLine($"WordBoundary event:" +
                    // Word, Punctuation, or Sentence
                    $"\r\n\tBoundaryType: {e.BoundaryType}" +
                    $"\r\n\tAudioOffset: {(e.AudioOffset + 5000) / 10000}ms" +
                    $"\r\n\tDuration: {e.Duration}" +
                    $"\r\n\tText: \"{e.Text}\"" +
                    $"\r\n\tTextOffset: {e.TextOffset}" +
                    $"\r\n\tWordLength: {e.WordLength}");
            };

            // Synthesize the SSML
            Console.WriteLine($"SSML to synthesize: \r\n{ssml}");
            var speechSynthesisResult = await speechSynthesizer.SpeakSsmlAsync(ssml);

            // Output the results
            switch (speechSynthesisResult.Reason)
            {
                case ResultReason.SynthesizingAudioCompleted:
                    Console.WriteLine("SynthesizingAudioCompleted result");
                    break;
                case ResultReason.Canceled:
                    var cancellation = SpeechSynthesisCancellationDetails.FromResult(speechSynthesisResult);
                    Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");

                    if (cancellation.Reason == CancellationReason.Error)
                    {
                        Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");
                        Console.WriteLine($"CANCELED: ErrorDetails=[{cancellation.ErrorDetails}]");
                        Console.WriteLine($"CANCELED: Did you set the speech resource key and region values?");
                    }
                    break;
                default:
                    break;
            }
        }

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }
}

Дополнительные текстовые примеры для речи можно найти на сайте GitHub.

Использование пользовательской конечной точки

Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов на речь.

Одно из различий заключается в том, что EndpointId его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью EndpointId и SpeechSynthesisVoiceName.

var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);     
speechConfig.SpeechSynthesisVoiceName = "YourCustomVoiceName";
speechConfig.EndpointId = "YourEndpointId";

Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Справочные примеры пакета документации | (NuGet) | Дополнительные примеры на GitHub

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Выбор языка и голоса для синтеза

Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Полный список поддерживаемых языковых стандартов речи или попробуйте использовать их в коллекции голосовых данных.

Укажите язык или голос класса SpeechConfig для сопоставления входного текста и использования указанного голоса. В следующем фрагменте кода показано, как работает этот метод:

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig->SetSpeechSynthesisLanguage("en-US"); 
    speechConfig->SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}

Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural, текст говорится на английском языке с испанским акцентом.

Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".

Примечание.

Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.

Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.

  • Если вы не задаете SpeechSynthesisVoiceName или SpeechSynthesisLanguageиспользуете голосовую связь по умолчанию для en-US разговоров.
  • Если задано только значение по умолчанию для указанного языкового стандарта SpeechSynthesisLanguage.
  • Если заданы и SpeechSynthesisVoiceName, и SpeechSynthesisLanguage, параметр SpeechSynthesisLanguage игнорируется. Заданный голос с помощью SpeechSynthesisVoiceName речи.
  • Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),SpeechSynthesisVoiceName SpeechSynthesisLanguage параметры игнорируются.

В итоге порядок приоритета можно описать следующим образом:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Результат
Голос по умолчанию для en-US разговоров
Голосовая связь по умолчанию для указанного языкового стандарта.
Заданный голос с помощью SpeechSynthesisVoiceName речи.
Заданный голос с помощью SSML говорит.

Синтезирование речи в файл

Создайте объект SpeechSynthesizer. Этот объект, показанный в следующих фрагментах кода, выполняет преобразование речи и выходные данные в динамики, файлы или другие выходные потоки. SpeechSynthesizer принимает в качестве параметров:

  1. AudioConfig Создайте экземпляр для автоматической записи выходных данных в файл .wav с помощью FromWavFileOutput() функции:

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Создание экземпляра SpeechSynthesizer . Передайте объекты speechConfig и audioConfig в качестве параметров. Чтобы синтезировать речь и записывать в файл, запустите SpeakTextAsync() строку текста.

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto audioConfig = AudioConfig::FromWavFileOutput("path/to/write/file.wav");
        auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig, audioConfig);
        auto result = speechSynthesizer->SpeakTextAsync("A simple test to write to a file.").get();
    }
    

При запуске программы создается синтезированный .wav-файл , который записывается в указанное расположение. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ в виде потока в памяти для работы с пользовательскими сценариями.

Синтезирование выходных данных для вывода на динамики

Чтобы вывести синтезированную речь на текущее активное устройство вывода, например динамик, опустите AudioConfig параметр при создании экземпляра SpeechSynthesizer . Приведем пример:

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
    auto result = speechSynthesizer->SpeakTextAsync("I'm excited to try text to speech").get();
}

Получение результата в виде потока в памяти

Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:

  • абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
  • интегрировать полученные данные с другими API или службами;
  • изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.

Это изменение можно внести в предыдущий пример. Во-первых, удалите AudioConfig блок, так как вы управляете поведением выходных данных вручную с этой точки, чтобы увеличить контроль. Передайте NULL в AudioConfig SpeechSynthesizer конструктор.

Примечание.

AudioConfigПередача NULL для , а не опущений, как в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.

Сохраните результат в переменной SpeechSynthesisResult . Метод получения GetAudioData возвращает экземпляр byte [] выходных данных. Вы можете работать с этим byte [] экземпляром вручную или использовать класс AudioDataStream для управления потоком в памяти.

В этом примере используйте AudioDataStream.FromResult() статическую функцию для получения потока из результата:

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);

    auto result = speechSynthesizer->SpeakTextAsync("Getting the response as an in-memory stream.").get();
    auto stream = AudioDataStream::FromResult(result);
}

На этом этапе можно реализовать любое пользовательское поведение с помощью результирующего stream объекта.

Настройка звукового формата

Можно настроить атрибуты вывода звука, в том числе:

  • тип звукового файла;
  • Частота выборки
  • глубину в битах.

Чтобы изменить формат звука, используйте SetSpeechSynthesisOutputFormat() функцию в объекте SpeechConfig . Эта функция ожидает enum экземпляр типа SpeechSynthesisOutputFormat. enum Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.

Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.

  • Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
  • Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.

В этом примере указывается формат Riff24Khz16BitMonoPcm RIFF с высокой точностью, задав SpeechSynthesisOutputFormat объект SpeechConfig . Как и в примере из предыдущего раздела, мы будем использовать AudioDataStream для получения результата в виде потока в памяти, а затем записывать его в файл.

void synthesizeSpeech()
{
    auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
    speechConfig->SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat::Riff24Khz16BitMonoPcm);

    auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
    auto result = speechSynthesizer->SpeakTextAsync("A simple test to write to a file.").get();

    auto stream = AudioDataStream::FromResult(result);
    stream->SaveToWavFileAsync("path/to/write/file.wav").get();
}

При запуске программы он записывает файл .wav в указанный путь.

Настройка характеристик речи с использованием SSML

SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".

Чтобы начать использовать SSML для настройки, внесите незначительные изменения, которые переключают голос.

  1. Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.

    <speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
      <voice name="en-US-AvaMultilingualNeural">
        When you're on the freeway, it's a good idea to use a GPS.
      </voice>
    </speak>
    

    В этом примере файл ssml.xml. Корневым элементом всегда является <speak>, а перенос текста в элемент <voice> позволяет менять голос с помощью параметра name. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.

  2. Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос в основном совпадает. Вместо использования SpeakTextAsync() функции вы используете SpeakSsmlAsync(). Эта функция ожидает XML-строку. Сначала загрузите конфигурацию SSML в виде строки. С этого момента объект результата точно совпадает с предыдущими примерами.

    void synthesizeSpeech()
    {
        auto speechConfig = SpeechConfig::FromSubscription("YourSpeechKey", "YourSpeechRegion");
        auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
    
        std::ifstream file("./ssml.xml");
        std::string ssml, line;
        while (std::getline(file, line))
        {
            ssml += line;
            ssml.push_back('\n');
        }
        auto result = speechSynthesizer->SpeakSsmlAsync(ssml).get();
    
        auto stream = AudioDataStream::FromResult(result);
        stream->SaveToWavFileAsync("path/to/write/file.wav").get();
    }
    

Примечание.

Чтобы изменить голос без использования SSML, можно задать свойство в SpeechConfig с помощью SpeechConfig.SetSpeechSynthesisVoiceName("en-US-AndrewMultilingualNeural").

Подписка на события синтезатора

Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.

Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:

Мероприятие Description Вариант использования
BookmarkReached Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов.
SynthesisCanceled Сигнализирует о том, что синтез речи был отменен. Вы можете подтвердить отмену синтеза.
SynthesisCompleted Сигнализирует о завершении синтеза речи. Вы можете подтвердить завершение синтеза.
SynthesisStarted Сигнализирует о начале синтеза речи. Вы можете подтвердить при запуске синтеза.
Synthesizing Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". Вы можете подтвердить, когда выполняется синтез.
VisemeReceived Сигнализирует о получении события viseme. Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи.
WordBoundary Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят.

Примечание.

События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.

Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.

Внимание

Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.

Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".

Вы можете выполнить инструкции в кратком руководстве, но заменить содержимое этого файла main.cpp следующим кодом:

#include <iostream> 
#include <stdlib.h>
#include <speechapi_cxx.h>

using namespace Microsoft::CognitiveServices::Speech;
using namespace Microsoft::CognitiveServices::Speech::Audio;

std::string getEnvironmentVariable(const char* name);

int main()
{
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    auto speechKey = getEnvironmentVariable("SPEECH_KEY");
    auto speechRegion = getEnvironmentVariable("SPEECH_REGION");

    if ((size(speechKey) == 0) || (size(speechRegion) == 0)) {
        std::cout << "Please set both SPEECH_KEY and SPEECH_REGION environment variables." << std::endl;
        return -1;
    }

    auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);

    // Required for WordBoundary event sentences.
    speechConfig->SetProperty(PropertyId::SpeechServiceResponse_RequestSentenceBoundary, "true");

    const auto ssml = R"(<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
        <voice name = 'en-US-AvaMultilingualNeural'>
            <mstts:viseme type = 'redlips_front' />
            The rainbow has seven colors : <bookmark mark = 'colors_list_begin' />Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark = 'colors_list_end' />.
        </voice>
        </speak>)";

    auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);

    // Subscribe to events

    speechSynthesizer->BookmarkReached += [](const SpeechSynthesisBookmarkEventArgs& e)
    {
        std::cout << "Bookmark reached. "
            << "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
            << "\r\n\tText: " << e.Text << std::endl;
    };

    speechSynthesizer->SynthesisCanceled += [](const SpeechSynthesisEventArgs& e)
    {
        std::cout << "SynthesisCanceled event" << std::endl;
    };

    speechSynthesizer->SynthesisCompleted += [](const SpeechSynthesisEventArgs& e)
    {
        auto audioDuration = std::chrono::duration_cast<std::chrono::milliseconds>(e.Result->AudioDuration).count();

        std::cout << "SynthesisCompleted event:"
            << "\r\n\tAudioData: " << e.Result->GetAudioData()->size() << "bytes"
            << "\r\n\tAudioDuration: " << audioDuration << std::endl;
    };

    speechSynthesizer->SynthesisStarted += [](const SpeechSynthesisEventArgs& e)
    {
        std::cout << "SynthesisStarted event" << std::endl;
    };

    speechSynthesizer->Synthesizing += [](const SpeechSynthesisEventArgs& e)
    {
        std::cout << "Synthesizing event:"
            << "\r\n\tAudioData: " << e.Result->GetAudioData()->size() << "bytes" << std::endl;
    };

    speechSynthesizer->VisemeReceived += [](const SpeechSynthesisVisemeEventArgs& e)
    {
        std::cout << "VisemeReceived event:"
            << "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
            << "\r\n\tVisemeId: " << e.VisemeId << std::endl;
    };

    speechSynthesizer->WordBoundary += [](const SpeechSynthesisWordBoundaryEventArgs& e)
    {
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(e.Duration).count();
        
        auto boundaryType = "";
        switch (e.BoundaryType) {
        case SpeechSynthesisBoundaryType::Punctuation:
            boundaryType = "Punctuation";
            break;
        case SpeechSynthesisBoundaryType::Sentence:
            boundaryType = "Sentence";
            break;
        case SpeechSynthesisBoundaryType::Word:
            boundaryType = "Word";
            break;
        }

        std::cout << "WordBoundary event:"
            // Word, Punctuation, or Sentence
            << "\r\n\tBoundaryType: " << boundaryType
            << "\r\n\tAudioOffset: " << round(e.AudioOffset / 10000) << "ms"
            << "\r\n\tDuration: " << duration
            << "\r\n\tText: \"" << e.Text << "\""
            << "\r\n\tTextOffset: " << e.TextOffset
            << "\r\n\tWordLength: " << e.WordLength << std::endl;
    };

    auto result = speechSynthesizer->SpeakSsmlAsync(ssml).get();

    // Checks result.
    if (result->Reason == ResultReason::SynthesizingAudioCompleted)
    {
        std::cout << "SynthesizingAudioCompleted result" << std::endl;
    }
    else if (result->Reason == ResultReason::Canceled)
    {
        auto cancellation = SpeechSynthesisCancellationDetails::FromResult(result);
        std::cout << "CANCELED: Reason=" << (int)cancellation->Reason << std::endl;

        if (cancellation->Reason == CancellationReason::Error)
        {
            std::cout << "CANCELED: ErrorCode=" << (int)cancellation->ErrorCode << std::endl;
            std::cout << "CANCELED: ErrorDetails=[" << cancellation->ErrorDetails << "]" << std::endl;
            std::cout << "CANCELED: Did you set the speech resource key and region values?" << std::endl;
        }
    }

    std::cout << "Press enter to exit..." << std::endl;
    std::cin.get();
}

std::string getEnvironmentVariable(const char* name)
{
#if defined(_MSC_VER)
    size_t requiredSize = 0;
    (void)getenv_s(&requiredSize, nullptr, 0, name);
    if (requiredSize == 0)
    {
        return "";
    }
    auto buffer = std::make_unique<char[]>(requiredSize);
    (void)getenv_s(&requiredSize, buffer.get(), requiredSize, name);
    return buffer.get();
#else
    auto value = getenv(name);
    return value ? value : "";
#endif
}

Дополнительные текстовые примеры для речи можно найти на сайте GitHub.

Использование пользовательской конечной точки

Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов речи.

Одно из различий заключается в том, что EndpointId его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью EndpointId и SpeechSynthesisVoiceName.

auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);
speechConfig->SetSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig->SetEndpointId("YourEndpointId");

Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Справочные примеры пакета документации | (Go) | Дополнительные примеры на GitHub

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Необходимые компоненты

  • Подписка Azure. Вы можете создать бесплатную учетную запись.
  • Создайте ресурс службы "Речь" в портал Azure.
  • Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.

Установка пакета SDK Речи

Прежде чем выполнять какие-либо действия, необходимо установить пакет SDK службы "Речь" для Go.

Текст для речи на говорящего

Используйте следующий пример кода для запуска синтеза речи на устройство вывода аудио по умолчанию. Замените переменные subscription и region своим ключом службы "Речь" и расположением или регионом. Выполнение скрипта говорит входной текст с динамиком по умолчанию.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "time"

    "github.com/Microsoft/cognitive-services-speech-sdk-go/audio"
    "github.com/Microsoft/cognitive-services-speech-sdk-go/common"
    "github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)

func synthesizeStartedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("Synthesis started.")
}

func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Printf("Synthesizing, audio chunk size %d.\n", len(event.Result.AudioData))
}

func synthesizedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Printf("Synthesized, audio length %d.\n", len(event.Result.AudioData))
}

func cancelledHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("Received a cancellation.")
}

func main() {
    subscription := "YourSpeechKey"
    region := "YourSpeechRegion"

    audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer audioConfig.Close()
    speechConfig, err := speech.NewSpeechConfigFromSubscription(subscription, region)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechConfig.Close()
    speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, audioConfig)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechSynthesizer.Close()

    speechSynthesizer.SynthesisStarted(synthesizeStartedHandler)
    speechSynthesizer.Synthesizing(synthesizingHandler)
    speechSynthesizer.SynthesisCompleted(synthesizedHandler)
    speechSynthesizer.SynthesisCanceled(cancelledHandler)

    for {
        fmt.Printf("Enter some text that you want to speak, or enter empty text to exit.\n> ")
        text, _ := bufio.NewReader(os.Stdin).ReadString('\n')
        text = strings.TrimSuffix(text, "\n")
        if len(text) == 0 {
            break
        }

        task := speechSynthesizer.SpeakTextAsync(text)
        var outcome speech.SpeechSynthesisOutcome
        select {
        case outcome = <-task:
        case <-time.After(60 * time.Second):
            fmt.Println("Timed out")
            return
        }
        defer outcome.Close()
        if outcome.Error != nil {
            fmt.Println("Got an error: ", outcome.Error)
            return
        }

        if outcome.Result.Reason == common.SynthesizingAudioCompleted {
            fmt.Printf("Speech synthesized to speaker for text [%s].\n", text)
        } else {
            cancellation, _ := speech.NewCancellationDetailsFromSpeechSynthesisResult(outcome.Result)
            fmt.Printf("CANCELED: Reason=%d.\n", cancellation.Reason)

            if cancellation.Reason == common.Error {
                fmt.Printf("CANCELED: ErrorCode=%d\nCANCELED: ErrorDetails=[%s]\nCANCELED: Did you set the speech resource key and region values?\n",
                    cancellation.ErrorCode,
                    cancellation.ErrorDetails)
            }
        }
    }
}

Выполните приведенные ниже команды, чтобы создать файл go.mod со ссылкой на компоненты, размещенные в GitHub:

go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go

Теперь можно приступить к сборке и выполнению кода:

go build
go run quickstart

Подробные сведения о классах см. в справочной документации по SpeechConfig и SpeechSynthesizer.

Текст для преобразования речи в поток в памяти

Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:

  • абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
  • интегрировать полученные данные с другими API или службами;
  • изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.

Это изменение можно внести в предыдущий пример. Удалите блок, так как вы управляете AudioConfig поведением выходных данных вручную с этого момента для повышения контроля. Затем передайте nil для AudioConfig в конструкторе SpeechSynthesizer.

Примечание.

Передача значения nil для AudioConfig вместо его пропуска, как это сделано в предыдущем примере с выводом на динамики, не позволит по умолчанию воспроизводить звук на активном устройстве вывода.

Сохраните результат в переменной SpeechSynthesisResult . Свойство AudioData возвращает экземпляр []byte выходных данных. Вы можете работать с экземпляром []byte вручную или использовать класс AudioDataStream для управления потоком в памяти. В этом примере используется статическая функция NewAudioDataStreamFromSpeechSynthesisResult() для получения потока из результата.

Замените переменные subscription и region своим ключом службы "Речь" и данными о расположении или регионе:

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
    "strings"
    "time"

    "github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)

func synthesizeStartedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("Synthesis started.")
}

func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Printf("Synthesizing, audio chunk size %d.\n", len(event.Result.AudioData))
}

func synthesizedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Printf("Synthesized, audio length %d.\n", len(event.Result.AudioData))
}

func cancelledHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("Received a cancellation.")
}

func main() {
    subscription := "YourSpeechKey"
    region := "YourSpeechRegion"

    speechConfig, err := speech.NewSpeechConfigFromSubscription(subscription, region)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechConfig.Close()
    speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, nil)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechSynthesizer.Close()

    speechSynthesizer.SynthesisStarted(synthesizeStartedHandler)
    speechSynthesizer.Synthesizing(synthesizingHandler)
    speechSynthesizer.SynthesisCompleted(synthesizedHandler)
    speechSynthesizer.SynthesisCanceled(cancelledHandler)

    for {
        fmt.Printf("Enter some text that you want to speak, or enter empty text to exit.\n> ")
        text, _ := bufio.NewReader(os.Stdin).ReadString('\n')
        text = strings.TrimSuffix(text, "\n")
        if len(text) == 0 {
            break
        }

        // StartSpeakingTextAsync sends the result to channel when the synthesis starts.
        task := speechSynthesizer.StartSpeakingTextAsync(text)
        var outcome speech.SpeechSynthesisOutcome
        select {
        case outcome = <-task:
        case <-time.After(60 * time.Second):
            fmt.Println("Timed out")
            return
        }
        defer outcome.Close()
        if outcome.Error != nil {
            fmt.Println("Got an error: ", outcome.Error)
            return
        }

        // In most cases, we want to streaming receive the audio to lower the latency.
        // We can use AudioDataStream to do so.
        stream, err := speech.NewAudioDataStreamFromSpeechSynthesisResult(outcome.Result)
        defer stream.Close()
        if err != nil {
            fmt.Println("Got an error: ", err)
            return
        }

        var all_audio []byte
        audio_chunk := make([]byte, 2048)
        for {
            n, err := stream.Read(audio_chunk)

            if err == io.EOF {
                break
            }

            all_audio = append(all_audio, audio_chunk[:n]...)
        }

        fmt.Printf("Read [%d] bytes from audio data stream.\n", len(all_audio))
    }
}

Выполните приведенные ниже команды, чтобы создать файл go.mod со ссылкой на компоненты, размещенные в GitHub:

go mod init quickstart
go get github.com/Microsoft/cognitive-services-speech-sdk-go

Теперь можно приступить к сборке и выполнению кода:

go build
go run quickstart

Подробные сведения о классах см. в справочной документации по SpeechConfig и SpeechSynthesizer.

Выбор языка и голоса для синтеза

Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.

Укажите язык или голос для сопоставления входного SpeechConfig текста и используйте указанный голос:

speechConfig, err := speech.NewSpeechConfigFromSubscription(key, region)
if err != nil {
    fmt.Println("Got an error: ", err)
    return
}
defer speechConfig.Close()

speechConfig.SetSpeechSynthesisLanguage("en-US")
speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural")

Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural, текст говорится на английском языке с испанским акцентом.

Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".

Примечание.

Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.

Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.

  • Если вы не задаете SpeechSynthesisVoiceName или SpeechSynthesisLanguageиспользуете голосовую связь по умолчанию для en-US разговоров.
  • Если задано только значение по умолчанию для указанного языкового стандарта SpeechSynthesisLanguage.
  • Если заданы и SpeechSynthesisVoiceName, и SpeechSynthesisLanguage, параметр SpeechSynthesisLanguage игнорируется. Заданный голос с помощью SpeechSynthesisVoiceName речи.
  • Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),SpeechSynthesisVoiceName SpeechSynthesisLanguage параметры игнорируются.

В итоге порядок приоритета можно описать следующим образом:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Результат
Голос по умолчанию для en-US разговоров
Голосовая связь по умолчанию для указанного языкового стандарта.
Заданный голос с помощью SpeechSynthesisVoiceName речи.
Заданный голос с помощью SSML говорит.

Настройка характеристик речи с использованием SSML

Вы можете использовать язык разметки синтеза речи (SSML), чтобы точно настроить поле, произношение, скорость речи, громкость и многое другое в тексте для вывода речи, отправив запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".

Чтобы начать использовать SSML для настройки, необходимо внести незначительные изменения, которые переключают голос.

Сначала создайте XML-файл для конфигурации SSML в корневом каталоге проекта. В нашем примере это значение выглядит следующим образом: ssml.xml. Корневым элементом всегда является <speak>, а перенос текста в элемент <voice> позволяет менять голос с помощью параметра name. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.

<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
  <voice name="en-US-AvaMultilingualNeural">
    When you're on the freeway, it's a good idea to use a GPS.
  </voice>
</speak>

Далее необходимо изменить запрос синтеза речи, чтобы он ссылался на XML-файл. Запрос аналогичен использовавшемуся нами ранее, но вместо функции SpeakTextAsync() содержит SpeakSsmlAsync(). Эта функция ожидает строку XML, поэтому сначала нужно загрузить конфигурацию SSML в виде строки. С этого момента объект результата точно совпадает с предыдущими примерами.

Примечание.

Чтобы задать голос без использования SSML, можно задать свойство в SpeechConfig с помощью speechConfig.SetSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural").

Подписка на события синтезатора

Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.

Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:

Мероприятие Description Вариант использования
BookmarkReached Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов.
SynthesisCanceled Сигнализирует о том, что синтез речи был отменен. Вы можете подтвердить отмену синтеза.
SynthesisCompleted Сигнализирует о завершении синтеза речи. Вы можете подтвердить завершение синтеза.
SynthesisStarted Сигнализирует о начале синтеза речи. Вы можете подтвердить при запуске синтеза.
Synthesizing Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". Вы можете подтвердить, когда выполняется синтез.
VisemeReceived Сигнализирует о получении события viseme. Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи.
WordBoundary Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят.

Примечание.

События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.

Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.

Внимание

Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.

Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".

Вы можете следовать инструкциям в кратком руководстве, но заменить содержимое этого speech-synthesis.go файла следующим кодом Go:

package main

import (
    "fmt"
    "os"
    "time"

    "github.com/Microsoft/cognitive-services-speech-sdk-go/audio"
    "github.com/Microsoft/cognitive-services-speech-sdk-go/common"
    "github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)

func bookmarkReachedHandler(event speech.SpeechSynthesisBookmarkEventArgs) {
    defer event.Close()
    fmt.Println("BookmarkReached event")
}

func synthesisCanceledHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("SynthesisCanceled event")
}

func synthesisCompletedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("SynthesisCompleted event")
    fmt.Printf("\tAudioData: %d bytes\n", len(event.Result.AudioData))
    fmt.Printf("\tAudioDuration: %d\n", event.Result.AudioDuration)
}

func synthesisStartedHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("SynthesisStarted event")
}

func synthesizingHandler(event speech.SpeechSynthesisEventArgs) {
    defer event.Close()
    fmt.Println("Synthesizing event")
    fmt.Printf("\tAudioData %d bytes\n", len(event.Result.AudioData))
}

func visemeReceivedHandler(event speech.SpeechSynthesisVisemeEventArgs) {
    defer event.Close()
    fmt.Println("VisemeReceived event")
    fmt.Printf("\tAudioOffset: %dms\n", (event.AudioOffset+5000)/10000)
    fmt.Printf("\tVisemeID %d\n", event.VisemeID)
}

func wordBoundaryHandler(event speech.SpeechSynthesisWordBoundaryEventArgs) {
    defer event.Close()
    boundaryType := ""
    switch event.BoundaryType {
    case 0:
        boundaryType = "Word"
    case 1:
        boundaryType = "Punctuation"
    case 2:
        boundaryType = "Sentence"
    }
    fmt.Println("WordBoundary event")
    fmt.Printf("\tBoundaryType %v\n", boundaryType)
    fmt.Printf("\tAudioOffset: %dms\n", (event.AudioOffset+5000)/10000)
    fmt.Printf("\tDuration %d\n", event.Duration)
    fmt.Printf("\tText %s\n", event.Text)
    fmt.Printf("\tTextOffset %d\n", event.TextOffset)
    fmt.Printf("\tWordLength %d\n", event.WordLength)
}

func main() {
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    speechKey := os.Getenv("SPEECH_KEY")
    speechRegion := os.Getenv("SPEECH_REGION")

    audioConfig, err := audio.NewAudioConfigFromDefaultSpeakerOutput()
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer audioConfig.Close()
    speechConfig, err := speech.NewSpeechConfigFromSubscription(speechKey, speechRegion)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechConfig.Close()

    // Required for WordBoundary event sentences.
    speechConfig.SetProperty(common.SpeechServiceResponseRequestSentenceBoundary, "true")

    speechSynthesizer, err := speech.NewSpeechSynthesizerFromConfig(speechConfig, audioConfig)
    if err != nil {
        fmt.Println("Got an error: ", err)
        return
    }
    defer speechSynthesizer.Close()

    speechSynthesizer.BookmarkReached(bookmarkReachedHandler)
    speechSynthesizer.SynthesisCanceled(synthesisCanceledHandler)
    speechSynthesizer.SynthesisCompleted(synthesisCompletedHandler)
    speechSynthesizer.SynthesisStarted(synthesisStartedHandler)
    speechSynthesizer.Synthesizing(synthesizingHandler)
    speechSynthesizer.VisemeReceived(visemeReceivedHandler)
    speechSynthesizer.WordBoundary(wordBoundaryHandler)

    speechSynthesisVoiceName := "en-US-AvaMultilingualNeural"

    ssml := fmt.Sprintf(`<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
            <voice name='%s'>
                <mstts:viseme type='redlips_front'/>
                The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
            </voice>
        </speak>`, speechSynthesisVoiceName)

    // Synthesize the SSML
    fmt.Printf("SSML to synthesize: \n\t%s\n", ssml)
    task := speechSynthesizer.SpeakSsmlAsync(ssml)

    var outcome speech.SpeechSynthesisOutcome
    select {
    case outcome = <-task:
    case <-time.After(60 * time.Second):
        fmt.Println("Timed out")
        return
    }
    defer outcome.Close()
    if outcome.Error != nil {
        fmt.Println("Got an error: ", outcome.Error)
        return
    }

    if outcome.Result.Reason == common.SynthesizingAudioCompleted {
        fmt.Println("SynthesizingAudioCompleted result")
    } else {
        cancellation, _ := speech.NewCancellationDetailsFromSpeechSynthesisResult(outcome.Result)
        fmt.Printf("CANCELED: Reason=%d.\n", cancellation.Reason)

        if cancellation.Reason == common.Error {
            fmt.Printf("CANCELED: ErrorCode=%d\nCANCELED: ErrorDetails=[%s]\nCANCELED: Did you set the speech resource key and region values?\n",
                cancellation.ErrorCode,
                cancellation.ErrorDetails)
        }
    }
}

Дополнительные текстовые примеры для речи можно найти на сайте GitHub.

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Справочная документация | по Дополнительным примерам на GitHub

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Выбор языка и голоса для синтеза

Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.

Укажите язык или голос SpeechConfig для сопоставления входного текста и используйте указанный голос. В следующем фрагменте кода показано, как работает этот метод:

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig.setSpeechSynthesisLanguage("en-US"); 
    speechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");
}

Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural, текст говорится на английском языке с испанским акцентом.

Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".

Примечание.

Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.

Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.

  • Если вы не задаете SpeechSynthesisVoiceName или SpeechSynthesisLanguageиспользуете голосовую связь по умолчанию для en-US разговоров.
  • Если задано только значение по умолчанию для указанного языкового стандарта SpeechSynthesisLanguage.
  • Если заданы и SpeechSynthesisVoiceName, и SpeechSynthesisLanguage, параметр SpeechSynthesisLanguage игнорируется. Голос, указанный с помощью SpeechSynthesisVoiceName речи.
  • Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),SpeechSynthesisVoiceName SpeechSynthesisLanguage параметры игнорируются.

В итоге порядок приоритета можно описать следующим образом:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Результат
Голос по умолчанию для en-US разговоров
Голосовая связь по умолчанию для указанного языкового стандарта.
Заданный голос с помощью SpeechSynthesisVoiceName речи.
Заданный голос с помощью SSML говорит.

Синтезирование речи в файл

Создание объекта SpeechSynthesizer. Этот объект выполняет текст для преобразования речи и выходных данных в динамики, файлы или другие выходные потоки. SpeechSynthesizer принимает в качестве параметров:

  • Объект SpeechConfig , созданный на предыдущем шаге.
  • Объект, указывающий AudioConfig способ обработки выходных результатов.
  1. AudioConfig Создайте экземпляр для автоматической записи выходных данных в файл .wav с помощью fromWavFileOutput() статической функции:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    }
    
  2. Создание экземпляра SpeechSynthesizer . Передайте объекты speechConfig и audioConfig в качестве параметров. Чтобы синтезировать речь и записывать в файл, запустите SpeakText() строку текста.

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        AudioConfig audioConfig = AudioConfig.fromWavFileOutput("path/to/write/file.wav");
    
        SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
        speechSynthesizer.SpeakText("I'm excited to try text to speech");
    }
    

При запуске программы создается синтезированный .wav-файл , который записывается в указанное расположение. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ в виде потока в памяти для работы с пользовательскими сценариями.

Синтезирование выходных данных для вывода на динамики

Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.

Чтобы вывести синтезированную речь на текущее активное выходное устройство, например динамик, создайте экземпляр AudioConfig с помощью fromDefaultSpeakerOutput() статической функции. Приведем пример:

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    AudioConfig audioConfig = AudioConfig.fromDefaultSpeakerOutput();

    SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    speechSynthesizer.SpeakText("I'm excited to try text to speech");
}

Получение результата в виде потока в памяти

Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:

  • абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
  • интегрировать полученные данные с другими API или службами;
  • изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.

Это изменение можно внести в предыдущий пример. Во-первых, удалите AudioConfig блок, так как вы управляете поведением выходных данных вручную с этой точки, чтобы увеличить контроль. Затем передайте null для AudioConfig в конструкторе SpeechSynthesizer.

Примечание.

AudioConfigПередачаnull, а не пропускание, как и в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.

Сохраните результат в переменной SpeechSynthesisResult . Функция SpeechSynthesisResult.getAudioData() возвращает экземпляр byte [] выходных данных. Вы можете работать с экземпляром byte [] вручную или использовать класс AudioDataStream для управления потоком в памяти.

В этом примере используйте AudioDataStream.fromResult() статическую функцию для получения потока из результата:

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);

    SpeechSynthesisResult result = speechSynthesizer.SpeakText("I'm excited to try text to speech");
    AudioDataStream stream = AudioDataStream.fromResult(result);
    System.out.print(stream.getStatus());
}

На этом этапе можно реализовать любое пользовательское поведение с помощью результирующего stream объекта.

Настройка звукового формата

Можно настроить атрибуты вывода звука, в том числе:

  • тип звукового файла;
  • Частота выборки
  • глубину в битах.

Чтобы изменить звуковой формат, используйте функцию setSpeechSynthesisOutputFormat() для объекта SpeechConfig. Эта функция ожидает enum экземпляр типа SpeechSynthesisOutputFormat. enum Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.

Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.

  • Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
  • Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.

В этом примере указывается формат Riff24Khz16BitMonoPcm RIFF с высокой точностью, задав SpeechSynthesisOutputFormat объект SpeechConfig . Как и в примере из предыдущего раздела, мы будем использовать AudioDataStream для получения результата в виде потока в памяти, а затем записывать его в файл.

public static void main(String[] args) {
    SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");

    // set the output format
    speechConfig.setSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);

    SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
    SpeechSynthesisResult result = speechSynthesizer.SpeakText("I'm excited to try text to speech");
    AudioDataStream stream = AudioDataStream.fromResult(result);
    stream.saveToWavFile("path/to/write/file.wav");
}

При запуске программы он записывает файл .wav в указанный путь.

Настройка характеристик речи с использованием SSML

SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в статье о руководстве по SSML.

Чтобы начать использовать SSML для настройки, необходимо внести незначительные изменения, которые переключают голос.

  1. Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.

    <speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
      <voice name="en-US-AvaMultilingualNeural">
        When you're on the freeway, it's a good idea to use a GPS.
      </voice>
    </speak>
    

    В этом примере файл ssml.xml. Корневым элементом всегда является <speak>, а перенос текста в элемент <voice> позволяет менять голос с помощью параметра name. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.

  2. Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос в основном совпадает. Вместо использования SpeakText() функции вы используете SpeakSsml(). Эта функция ожидает XML-строку, поэтому сначала создайте функцию для загрузки XML-файла и возвратите его в виде строки:

    private static String xmlToString(String filePath) {
        File file = new File(filePath);
        StringBuilder fileContents = new StringBuilder((int)file.length());
    
        try (Scanner scanner = new Scanner(file)) {
            while(scanner.hasNextLine()) {
                fileContents.append(scanner.nextLine() + System.lineSeparator());
            }
            return fileContents.toString().trim();
        } catch (FileNotFoundException ex) {
            return "File not found.";
        }
    }
    

    На этом этапе результирующий объект точно совпадает с предыдущими примерами:

    public static void main(String[] args) {
        SpeechConfig speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
    
        String ssml = xmlToString("ssml.xml");
        SpeechSynthesisResult result = speechSynthesizer.SpeakSsml(ssml);
        AudioDataStream stream = AudioDataStream.fromResult(result);
        stream.saveToWavFile("path/to/write/file.wav");
    }
    

Примечание.

Чтобы изменить голос без использования SSML, задайте свойство SpeechConfig с помощью .SpeechConfig.setSpeechSynthesisVoiceName("en-US-AvaMultilingualNeural");

Подписка на события синтезатора

Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.

Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:

Мероприятие Description Вариант использования
BookmarkReached Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов.
SynthesisCanceled Сигнализирует о том, что синтез речи был отменен. Вы можете подтвердить отмену синтеза.
SynthesisCompleted Сигнализирует о завершении синтеза речи. Вы можете подтвердить завершение синтеза.
SynthesisStarted Сигнализирует о начале синтеза речи. Вы можете подтвердить при запуске синтеза.
Synthesizing Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". Вы можете подтвердить, когда выполняется синтез.
VisemeReceived Сигнализирует о получении события viseme. Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи.
WordBoundary Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят.

Примечание.

События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.

Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.

Внимание

Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.

Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".

Вы можете следовать инструкциям в кратком руководстве, но заменить содержимое этого файла SpeechSynthesis.java следующим кодом Java:

import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.audio.*;

import java.util.Scanner;
import java.util.concurrent.ExecutionException;

public class SpeechSynthesis {
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    private static String speechKey = System.getenv("SPEECH_KEY");
    private static String speechRegion = System.getenv("SPEECH_REGION");

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
        
        // Required for WordBoundary event sentences.
        speechConfig.setProperty(PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");

        String speechSynthesisVoiceName = "en-US-AvaMultilingualNeural"; 
        
        String ssml = String.format("<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>"
            .concat(String.format("<voice name='%s'>", speechSynthesisVoiceName))
            .concat("<mstts:viseme type='redlips_front'/>")
            .concat("The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.")
            .concat("</voice>")
            .concat("</speak>"));

        SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(speechConfig);
        {
            // Subscribe to events

            speechSynthesizer.BookmarkReached.addEventListener((o, e) -> {
                System.out.println("BookmarkReached event:");
                System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
                System.out.println("\tText: " + e.getText());
            });

            speechSynthesizer.SynthesisCanceled.addEventListener((o, e) -> {
                System.out.println("SynthesisCanceled event");
            });

            speechSynthesizer.SynthesisCompleted.addEventListener((o, e) -> {
                SpeechSynthesisResult result = e.getResult();                
                byte[] audioData = result.getAudioData();
                System.out.println("SynthesisCompleted event:");
                System.out.println("\tAudioData: " + audioData.length + " bytes");
                System.out.println("\tAudioDuration: " + result.getAudioDuration());
                result.close();
            });
            
            speechSynthesizer.SynthesisStarted.addEventListener((o, e) -> {
                System.out.println("SynthesisStarted event");
            });

            speechSynthesizer.Synthesizing.addEventListener((o, e) -> {
                SpeechSynthesisResult result = e.getResult();
                byte[] audioData = result.getAudioData();
                System.out.println("Synthesizing event:");
                System.out.println("\tAudioData: " + audioData.length + " bytes");
                result.close();
            });

            speechSynthesizer.VisemeReceived.addEventListener((o, e) -> {
                System.out.println("VisemeReceived event:");
                System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
                System.out.println("\tVisemeId: " + e.getVisemeId());
            });

            speechSynthesizer.WordBoundary.addEventListener((o, e) -> {
                System.out.println("WordBoundary event:");
                System.out.println("\tBoundaryType: " + e.getBoundaryType());
                System.out.println("\tAudioOffset: " + ((e.getAudioOffset() + 5000) / 10000) + "ms");
                System.out.println("\tDuration: " + e.getDuration());
                System.out.println("\tText: " + e.getText());
                System.out.println("\tTextOffset: " + e.getTextOffset());
                System.out.println("\tWordLength: " + e.getWordLength());
            });

            // Synthesize the SSML
            System.out.println("SSML to synthesize:");
            System.out.println(ssml);
            SpeechSynthesisResult speechSynthesisResult = speechSynthesizer.SpeakSsmlAsync(ssml).get();

            if (speechSynthesisResult.getReason() == ResultReason.SynthesizingAudioCompleted) {
                System.out.println("SynthesizingAudioCompleted result");
            }
            else if (speechSynthesisResult.getReason() == ResultReason.Canceled) {
                SpeechSynthesisCancellationDetails cancellation = SpeechSynthesisCancellationDetails.fromResult(speechSynthesisResult);
                System.out.println("CANCELED: Reason=" + cancellation.getReason());

                if (cancellation.getReason() == CancellationReason.Error) {
                    System.out.println("CANCELED: ErrorCode=" + cancellation.getErrorCode());
                    System.out.println("CANCELED: ErrorDetails=" + cancellation.getErrorDetails());
                    System.out.println("CANCELED: Did you set the speech resource key and region values?");
                }
            }
        }
        speechSynthesizer.close();

        System.exit(0);
    }
}

Дополнительные текстовые примеры для речи можно найти на сайте GitHub.

Использование пользовательской конечной точки

Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов речи.

Одно из различий заключается в том, что EndpointId его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью EndpointId и SpeechSynthesisVoiceName.

SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
speechConfig.setSpeechSynthesisVoiceName("YourCustomVoiceName");
speechConfig.setEndpointId("YourEndpointId");

Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Справочные примеры пакета документации | (npm) | Дополнительные примеры в исходном коде библиотеки GitHub |

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Выбор языка и голоса для синтеза

Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.

Укажите язык или голос для сопоставления входного SpeechConfig текста и используйте указанный голос:

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    // Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
    speechConfig.speechSynthesisLanguage = "en-US"; 
    speechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
}

synthesizeSpeech();

Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural, текст говорится на английском языке с испанским акцентом.

Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".

Примечание.

Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.

Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.

  • Если вы не задаете SpeechSynthesisVoiceName или SpeechSynthesisLanguageиспользуете голосовую связь по умолчанию для en-US разговоров.
  • Если задано только значение по умолчанию для указанного языкового стандарта SpeechSynthesisLanguage.
  • Если заданы и SpeechSynthesisVoiceName, и SpeechSynthesisLanguage, параметр SpeechSynthesisLanguage игнорируется. Заданный голос с помощью SpeechSynthesisVoiceName речи.
  • Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),SpeechSynthesisVoiceName SpeechSynthesisLanguage параметры игнорируются.

В итоге порядок приоритета можно описать следующим образом:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Результат
Голос по умолчанию для en-US разговоров
Голосовая связь по умолчанию для указанного языкового стандарта.
Заданный голос с помощью SpeechSynthesisVoiceName речи.
Заданный голос с помощью SSML говорит.

Синтезирование текста в речь

Чтобы вывести синтезированную речь на текущее активное выходное устройство, например динамик, создайте экземпляр AudioConfig с помощью fromDefaultSpeakerOutput() статической функции. Приведем пример:

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    const audioConfig = sdk.AudioConfig.fromDefaultSpeakerOutput();

    const speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
    speechSynthesizer.speakTextAsync(
        "I'm excited to try text to speech",
        result => {
            if (result) {
                speechSynthesizer.close();
                return result.audioData;
            }
        },
        error => {
            console.log(error);
            speechSynthesizer.close();
        });
}

При запуске программы синтезированный звук воспроизводится из динамика. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ как поток в памяти для работы с пользовательскими сценариями.

Получение результата в виде потока в памяти

Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:

  • абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
  • интегрировать полученные данные с другими API или службами;
  • изменять звуковые данные, записывать пользовательские заголовки .wav и выполнять другие связанные задачи.

Это изменение можно внести в предыдущий пример. Удалите блок, так как вы управляете AudioConfig поведением выходных данных вручную с этого момента для повышения контроля. Затем передайте null для AudioConfig в конструкторе SpeechSynthesizer.

Примечание.

AudioConfigПередачаnull, а не пропускание, как и в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.

Сохраните результат в переменной SpeechSynthesisResult . Свойство SpeechSynthesisResult.audioData возвращает значение ArrayBuffer выходных данных, тип потока браузера по умолчанию. Для кода на стороне сервера преобразуйте ArrayBuffer в поток буфера.

Приведенный ниже код работает на стороне клиента:

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig);

    speechSynthesizer.speakTextAsync(
        "I'm excited to try text to speech",
        result => {
            speechSynthesizer.close();
            return result.audioData;
        },
        error => {
            console.log(error);
            speechSynthesizer.close();
        });
}

Вы можете реализовать любое пользовательское поведение с помощью результирующего ArrayBuffer объекта. ArrayBuffer — это распространенный тип для получения в браузере и воспроизведения из этого формата.

Для любого серверного кода, если необходимо работать с данными в виде потока, необходимо преобразовать в поток объект ArrayBuffer.

function synthesizeSpeech() {
    const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
    const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig);

    speechSynthesizer.speakTextAsync(
        "I'm excited to try text to speech",
        result => {
            const { audioData } = result;

            speechSynthesizer.close();

            // convert arrayBuffer to stream
            // return stream
            const bufferStream = new PassThrough();
            bufferStream.end(Buffer.from(audioData));
            return bufferStream;
        },
        error => {
            console.log(error);
            speechSynthesizer.close();
        });
}

Настройка звукового формата

Можно настроить атрибуты вывода звука, в том числе:

  • тип звукового файла;
  • Частота выборки
  • глубину в битах.

Чтобы изменить формат звука, используйте speechSynthesisOutputFormat свойство объекта SpeechConfig . Это свойство ожидает enum экземпляр типа SpeechSynthesisOutputFormat. enum Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.

Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.

  • Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
  • Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.

В этом примере указывается формат Riff24Khz16BitMonoPcm RIFF с высокой точностью, задав speechSynthesisOutputFormat объект SpeechConfig . Как и в примере из предыдущего раздела, можно получить данные ArrayBuffer для звука и взаимодействовать с ними.

function synthesizeSpeech() {
    const speechConfig = SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");

    // Set the output format
    speechConfig.speechSynthesisOutputFormat = sdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm;

    const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, null);
    speechSynthesizer.speakTextAsync(
        "I'm excited to try text to speech",
        result => {
            // Interact with the audio ArrayBuffer data
            const audioData = result.audioData;
            console.log(`Audio data byte size: ${audioData.byteLength}.`)

            speechSynthesizer.close();
        },
        error => {
            console.log(error);
            speechSynthesizer.close();
        });
}

Настройка характеристик речи с использованием SSML

SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".

Чтобы начать использовать SSML для настройки, необходимо внести незначительные изменения, которые переключают голос.

  1. Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.

    <speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
      <voice name="en-US-AvaMultilingualNeural">
        When you're on the freeway, it's a good idea to use a GPS.
      </voice>
    </speak>
    

    В этом примере ssml.xml. Корневым элементом всегда является <speak>, а перенос текста в элемент <voice> позволяет менять голос с помощью параметра name. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.

  2. Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос аналогичен использовавшемуся нами ранее, но вместо функции speakTextAsync() содержит speakSsmlAsync(). Эта функция ожидает XML-строку. Создайте функцию для загрузки XML-файла и верните ее в виде строки:

    function xmlToString(filePath) {
        const xml = readFileSync(filePath, "utf8");
        return xml;
    }
    

    Дополнительные сведения о readFileSync см. здесь.

    Результирующий объект точно такой же, как и в предыдущих примерах:

    function synthesizeSpeech() {
        const speechConfig = sdk.SpeechConfig.fromSubscription("YourSpeechKey", "YourSpeechRegion");
        const speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, null);
    
        const ssml = xmlToString("ssml.xml");
        speechSynthesizer.speakSsmlAsync(
            ssml,
            result => {
                if (result.errorDetails) {
                    console.error(result.errorDetails);
                } else {
                    console.log(JSON.stringify(result));
                }
    
                speechSynthesizer.close();
            },
            error => {
                console.log(error);
                speechSynthesizer.close();
            });
    }
    

Примечание.

Чтобы изменить голос без использования SSML, можно задать свойство в SpeechConfig с помощью SpeechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";.

Подписка на события синтезатора

Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.

Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:

Мероприятие Description Вариант использования
BookmarkReached Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов.
SynthesisCanceled Сигнализирует о том, что синтез речи был отменен. Вы можете подтвердить отмену синтеза.
SynthesisCompleted Сигнализирует о завершении синтеза речи. Вы можете подтвердить завершение синтеза.
SynthesisStarted Сигнализирует о начале синтеза речи. Вы можете подтвердить при запуске синтеза.
Synthesizing Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". Вы можете подтвердить, когда выполняется синтез.
VisemeReceived Сигнализирует о получении события viseme. Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи.
WordBoundary Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят.

Примечание.

События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.

Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.

Внимание

Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.

Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".

Вы можете следовать инструкциям в кратком руководстве, но заменить содержимое этого файла SpeechSynthesis.js следующим кодом JavaScript.

(function() {

    "use strict";

    var sdk = require("microsoft-cognitiveservices-speech-sdk");

    var audioFile = "YourAudioFile.wav";
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    const speechConfig = sdk.SpeechConfig.fromSubscription(process.env.SPEECH_KEY, process.env.SPEECH_REGION);
    const audioConfig = sdk.AudioConfig.fromAudioFileOutput(audioFile);

    var speechSynthesisVoiceName  = "en-US-AvaMultilingualNeural";  
    var ssml = `<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'> \r\n \
        <voice name='${speechSynthesisVoiceName}'> \r\n \
            <mstts:viseme type='redlips_front'/> \r\n \
            The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>. \r\n \
        </voice> \r\n \
    </speak>`;
    
    // Required for WordBoundary event sentences.
    speechConfig.setProperty(sdk.PropertyId.SpeechServiceResponse_RequestSentenceBoundary, "true");

    // Create the speech speechSynthesizer.
    var speechSynthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig);

    speechSynthesizer.bookmarkReached = function (s, e) {
        var str = `BookmarkReached event: \
            \r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
            \r\n\tText: \"${e.text}\".`;
        console.log(str);
    };

    speechSynthesizer.synthesisCanceled = function (s, e) {
        console.log("SynthesisCanceled event");
    };
    
    speechSynthesizer.synthesisCompleted = function (s, e) {
        var str = `SynthesisCompleted event: \
                    \r\n\tAudioData: ${e.result.audioData.byteLength} bytes \
                    \r\n\tAudioDuration: ${e.result.audioDuration}`;
        console.log(str);
    };

    speechSynthesizer.synthesisStarted = function (s, e) {
        console.log("SynthesisStarted event");
    };

    speechSynthesizer.synthesizing = function (s, e) {
        var str = `Synthesizing event: \
            \r\n\tAudioData: ${e.result.audioData.byteLength} bytes`;
        console.log(str);
    };
    
    speechSynthesizer.visemeReceived = function(s, e) {
        var str = `VisemeReceived event: \
            \r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
            \r\n\tVisemeId: ${e.visemeId}`;
        console.log(str);
    };

    speechSynthesizer.wordBoundary = function (s, e) {
        // Word, Punctuation, or Sentence
        var str = `WordBoundary event: \
            \r\n\tBoundaryType: ${e.boundaryType} \
            \r\n\tAudioOffset: ${(e.audioOffset + 5000) / 10000}ms \
            \r\n\tDuration: ${e.duration} \
            \r\n\tText: \"${e.text}\" \
            \r\n\tTextOffset: ${e.textOffset} \
            \r\n\tWordLength: ${e.wordLength}`;
        console.log(str);
    };

    // Synthesize the SSML
    console.log(`SSML to synthesize: \r\n ${ssml}`)
    console.log(`Synthesize to: ${audioFile}`);
    speechSynthesizer.speakSsmlAsync(ssml,
        function (result) {
      if (result.reason === sdk.ResultReason.SynthesizingAudioCompleted) {
        console.log("SynthesizingAudioCompleted result");
      } else {
        console.error("Speech synthesis canceled, " + result.errorDetails +
            "\nDid you set the speech resource key and region values?");
      }
      speechSynthesizer.close();
      speechSynthesizer = null;
    },
        function (err) {
      console.trace("err - " + err);
      speechSynthesizer.close();
      speechSynthesizer = null;
    });
}());

Дополнительные текстовые примеры для речи можно найти на сайте GitHub.

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Справочный пакет документации | (скачивание) | Дополнительные примеры на GitHub

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Необходимые компоненты

  • Подписка Azure. Вы можете создать бесплатную учетную запись.
  • Создайте ресурс службы "Речь" в портал Azure.
  • Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.

Установка пакета SDK и примеров для службы "Речь"

Репозиторий Azure-Samples/cognitive-services-speech-sdk включает примеры, написанные на Objective-C для iOS и Mac. Щелкните ссылку, чтобы просмотреть инструкции по установке для каждого примера:

Использование пользовательской конечной точки

Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов речи.

Одно из различий заключается в том, что EndpointId его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью EndpointId и SpeechSynthesisVoiceName.

SPXSpeechConfiguration *speechConfig = [[SPXSpeechConfiguration alloc] initWithSubscription:speechKey region:speechRegion];
speechConfig.speechSynthesisVoiceName = @"YourCustomVoiceName";
speechConfig.EndpointId = @"YourEndpointId";

Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Справочный пакет документации | (скачивание) | Дополнительные примеры на GitHub

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Необходимые компоненты

  • Подписка Azure. Вы можете создать бесплатную учетную запись.
  • Создайте ресурс службы "Речь" в портал Azure.
  • Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.

Установка пакета SDK и примеров для службы "Речь"

Репозиторий Azure-Samples/cognitive-services-speech-sdk включает примеры, написанные на Swift для iOS и Mac. Щелкните ссылку, чтобы просмотреть инструкции по установке для каждого примера:

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Справочные примеры пакета документации | (PyPi) | Дополнительные примеры на GitHub

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Выбор языка и голоса для синтеза

Функция преобразования текста в речь в службе "Речь" поддерживает более 400 голосов и более 140 языков и вариантов. Вы можете получить полный список или попробовать их в коллекции голосовых данных.

Укажите язык или голос для сопоставления входного SpeechConfig текста и используйте указанный голос:

# Set either the `SpeechSynthesisVoiceName` or `SpeechSynthesisLanguage`.
speech_config.speech_synthesis_language = "en-US" 
speech_config.speech_synthesis_voice_name ="en-US-AvaMultilingualNeural"

Все нейронные голосовые модели поддерживают несколько языков и свободно говорят на родном и английском языках. Например, если входной текст на английском языке: "Я рад попробовать текст для речи", и вы выбираете es-ES-ElviraNeural, текст говорится на английском языке с испанским акцентом.

Если голос не говорит на языке входного текста, служба "Речь" не создает синтезированный звук. Полный список поддерживаемых нейронных голосов см. в разделе "Язык" и "Поддержка голосовой связи" службы "Речь".

Примечание.

Голос по умолчанию — это первый голос, возвращенный на языковой стандарт из API списка голосов.

Голосовая модель, произносящая текст, определяется в порядке приоритета следующим образом.

  • Если вы не задаете SpeechSynthesisVoiceName или SpeechSynthesisLanguageиспользуете голосовую связь по умолчанию для en-US разговоров.
  • Если задано только значение по умолчанию для указанного языкового стандарта SpeechSynthesisLanguage.
  • Если заданы и SpeechSynthesisVoiceName, и SpeechSynthesisLanguage, параметр SpeechSynthesisLanguage игнорируется. Заданный голос с помощью SpeechSynthesisVoiceName речи.
  • Если элемент голоса задан с помощью языка разметки синтеза речи (SSML),SpeechSynthesisVoiceName SpeechSynthesisLanguage параметры игнорируются.

В итоге порядок приоритета можно описать следующим образом:

SpeechSynthesisVoiceName SpeechSynthesisLanguage SSML Результат
Голос по умолчанию для en-US разговоров
Голосовая связь по умолчанию для указанного языкового стандарта.
Заданный голос с помощью SpeechSynthesisVoiceName речи.
Заданный голос с помощью SSML говорит.

Синтезирование речи в файл

Создайте объект SpeechSynthesizer. Этот объект выполняет текст для преобразования речи и выходных данных в динамики, файлы или другие выходные потоки. SpeechSynthesizer принимает в качестве параметров:

  • Объект SpeechConfig , созданный на предыдущем шаге.
  • Объект, указывающий AudioOutputConfig способ обработки выходных результатов.
  1. AudioOutputConfig Создайте экземпляр для автоматической записи выходных данных в файл .wav с помощью параметра конструктораfilename:

    audio_config = speechsdk.audio.AudioOutputConfig(filename="path/to/write/file.wav")
    
  2. Создайте SpeechSynthesizer экземпляр, передав объект speech_config и audio_config объект в качестве параметров. Чтобы синтезировать речь и записывать в файл, запустите speak_text_async() строку текста.

    speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
    speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
    
    

При запуске программы создается синтезированный .wav-файл , который записывается в указанное расположение. Этот результат является хорошим примером наиболее простого использования. Затем можно настроить выходные данные и обрабатывать выходной ответ в виде потока в памяти для работы с пользовательскими сценариями.

Синтезирование выходных данных для вывода на динамики

Чтобы вывести синтезированную речь на текущее активное выходное устройство, например динамик, задайте use_default_speaker параметр при создании экземпляра AudioOutputConfig . Приведем пример:

audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)

Получение результата в виде потока в памяти

Полученные звуковые данные можно использовать в виде потока в памяти, а не непосредственного записи в файл. С помощью потока в памяти можно создать пользовательское поведение:

  • абстрагировать полученный массив байтов в виде потока с возможностью поиска для настраиваемых нижестоящих служб;
  • интегрировать полученные данные с другими API или службами;
  • Измените звуковые данные, напишите пользовательские .wav заголовки и выполните связанные задачи.

Это изменение можно внести в предыдущий пример. Во-первых, удалите AudioConfig, так как вы управляете поведением выходных данных вручную с этого момента для повышения контроля. Передайте None в AudioConfig SpeechSynthesizer конструктор.

Примечание.

AudioConfigПередачаNone, а не пропускание, как и в предыдущем примере выходных данных говорящего, не воспроизводит звук по умолчанию на текущем активном выходном устройстве.

Сохраните результат в переменной SpeechSynthesisResult . Свойство audio_data содержит объект bytes выходных данных. Вы можете работать с этим объектом вручную или использовать класс AudioDataStream для управления потоком в памяти.

В этом примере используйте AudioDataStream конструктор для получения потока из результата:

speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(speech_synthesis_result)

На этом этапе можно реализовать любое пользовательское поведение с помощью результирующего stream объекта.

Настройка звукового формата

Можно настроить атрибуты вывода звука, в том числе:

  • тип звукового файла;
  • Частота выборки
  • глубину в битах.

Чтобы изменить формат звука, используйте set_speech_synthesis_output_format() функцию в объекте SpeechConfig . Эта функция ожидает enum экземпляр типа SpeechSynthesisOutputFormat. enum Используйте этот формат, чтобы выбрать выходной формат. Доступные форматы см. в списке аудиоформатов.

Различные типы файлов обеспечивают разные возможности для работы с ними в зависимости от требований. По определению звуковые данные в необработанном формате, таком как Raw24Khz16BitMonoPcm, не содержат заголовки. Используйте необработанные форматы только в одной из следующих ситуаций.

  • Вы уверены, что нижестоящие службы способны декодировать необработанный битовый поток.
  • Вы планируете создавать заголовки вручную на основе глубины в битах, частоты выборки и количества каналов.

В этом примере указывается формат Riff24Khz16BitMonoPcm RIFF с высокой точностью, задав SpeechSynthesisOutputFormat объект SpeechConfig . Как и в примере из предыдущего раздела, мы будем использовать AudioDataStream для получения результата в виде потока в памяти, а затем записывать его в файл.

speech_config.set_speech_synthesis_output_format(speechsdk.SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)

speech_synthesis_result = speech_synthesizer.speak_text_async("I'm excited to try text to speech").get()
stream = speechsdk.AudioDataStream(speech_synthesis_result)
stream.save_to_wav_file("path/to/write/file.wav")

При запуске программы он записывает файл .wav в указанный путь.

Настройка характеристик речи с использованием SSML

SSML можно использовать для точной настройки шага, произношения, скорости речи, громкости и других аспектов в тексте для вывода речи, отправляя запросы из схемы XML. В этом разделе приведен пример изменения голоса. Дополнительные сведения см. в разделе "Язык разметки синтеза речи".

Чтобы начать использовать SSML для настройки, внесите незначительные изменения, которые переключают голос.

  1. Создайте XML-файл для конфигурации SSML в корневом каталоге проекта.

    <speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="en-US">
      <voice name="en-US-AvaMultilingualNeural">
        When you're on the freeway, it's a good idea to use a GPS.
      </voice>
    </speak>
    

    В этом примере файл ssml.xml. Корневым элементом всегда является <speak>, а перенос текста в элемент <voice> позволяет менять голос с помощью параметра name. Полный список поддерживаемых нейронных голосов см . на поддерживаемых языках.

  2. Измените запрос синтеза речи, чтобы ссылаться на XML-файл. Запрос в основном совпадает. Вместо использования speak_text_async() функции используйте speak_ssml_async(). Эта функция ожидает XML-строку. Сначала считывает конфигурацию SSML в виде строки. С этого момента объект результата точно совпадает с предыдущими примерами.

    Примечание.

    Если ssml_string содержит  в начале строки, необходимо удалить метку порядка байтов, иначе служба вернет ошибку. Это можно сделать, задав параметру encoding такие параметры: open("ssml.xml", "r", encoding="utf-8-sig").

    speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
    
    ssml_string = open("ssml.xml", "r").read()
    speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml_string).get()
    
    stream = speechsdk.AudioDataStream(speech_synthesis_result)
    stream.save_to_wav_file("path/to/write/file.wav")
    

Примечание.

Чтобы изменить голос без использования SSML, можно задать свойство в SpeechConfig с помощью speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural".

Подписка на события синтезатора

Вам может потребоваться больше аналитических сведений о обработке и результатах обработки речи. Например, может потребоваться знать, когда синтезатор запускается и останавливается, или вы можете знать о других событиях, встречающихся во время синтеза.

Используя средство SpeechSynthesizer для преобразования текста в речь, вы можете подписаться на события в этой таблице:

Мероприятие Description Вариант использования
BookmarkReached Сигнализирует о достижении закладки. Чтобы активировать событие достижения закладки, bookmark элемент требуется в SSML. Это событие сообщает об истечении времени вывода звука между началом синтеза и элементом bookmark . Свойство события Text — это строковое значение, заданное в атрибуте закладки mark . Элементы bookmark не говорятся. Элемент bookmark дает возможность вставлять пользовательские маркеры в SSML, чтобы сформировать смещение каждого маркера в звуковом потоке. Элемент bookmark можно использовать для ссылки на определенное место в тексте или последовательности тегов.
SynthesisCanceled Сигнализирует о том, что синтез речи был отменен. Вы можете подтвердить отмену синтеза.
SynthesisCompleted Сигнализирует о завершении синтеза речи. Вы можете подтвердить завершение синтеза.
SynthesisStarted Сигнализирует о начале синтеза речи. Вы можете подтвердить при запуске синтеза.
Synthesizing Сигнализирует о том, что синтез речи продолжается. Это событие запускается каждый раз, когда пакет SDK получает блок аудио из службы "Речь". Вы можете подтвердить, когда выполняется синтез.
VisemeReceived Сигнализирует о получении события viseme. Для представления основных положений в наблюдаемой речи часто используются виземы, такие как расположение губ, челюстей и языка при создании определенной фонемы. Вы можете использовать виземы для анимации лица символа в качестве воспроизведения речи.
WordBoundary Сигнализирует о получении границы слова. Это событие возникает в начале каждого нового слова, препинания и предложения. Событие сообщает смещение времени текущего слова в тиках с начала выходного звука. Это событие также сообщает о позиции символа во входном тексте или SSML непосредственно перед словом, которое будет говориться. Это событие часто используется для получения относительных позиций текста и соответствующего звука. Возможно, вы хотите узнать о новом слове, а затем принять меры в зависимости от времени. Например, вы можете получить информацию, которая поможет вам решить, когда и как долго выделять слова, как они говорят.

Примечание.

События создаются по мере того, как выходные звуковые данные становятся доступными, что быстрее, чем воспроизведение на выходном устройстве. Вызывающий объект должен соответствующим образом синхронизировать потоковую передачу и режим реального времени.

Ниже приведен пример, показывающий, как подписаться на события для синтеза речи.

Внимание

Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.

Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".

Вы можете выполнить инструкции в кратком руководстве, но заменить содержимое этого файла speech-synthesis.py следующим кодом Python:

import os
import azure.cognitiveservices.speech as speechsdk

def speech_synthesizer_bookmark_reached_cb(evt: speechsdk.SessionEventArgs):
    print('BookmarkReached event:')
    print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
    print('\tText: {}'.format(evt.text))

def speech_synthesizer_synthesis_canceled_cb(evt: speechsdk.SessionEventArgs):
    print('SynthesisCanceled event')

def speech_synthesizer_synthesis_completed_cb(evt: speechsdk.SessionEventArgs):
    print('SynthesisCompleted event:')
    print('\tAudioData: {} bytes'.format(len(evt.result.audio_data)))
    print('\tAudioDuration: {}'.format(evt.result.audio_duration))

def speech_synthesizer_synthesis_started_cb(evt: speechsdk.SessionEventArgs):
    print('SynthesisStarted event')

def speech_synthesizer_synthesizing_cb(evt: speechsdk.SessionEventArgs):
    print('Synthesizing event:')
    print('\tAudioData: {} bytes'.format(len(evt.result.audio_data)))

def speech_synthesizer_viseme_received_cb(evt: speechsdk.SessionEventArgs):
    print('VisemeReceived event:')
    print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
    print('\tVisemeId: {}'.format(evt.viseme_id))

def speech_synthesizer_word_boundary_cb(evt: speechsdk.SessionEventArgs):
    print('WordBoundary event:')
    print('\tBoundaryType: {}'.format(evt.boundary_type))
    print('\tAudioOffset: {}ms'.format((evt.audio_offset + 5000) / 10000))
    print('\tDuration: {}'.format(evt.duration))
    print('\tText: {}'.format(evt.text))
    print('\tTextOffset: {}'.format(evt.text_offset))
    print('\tWordLength: {}'.format(evt.word_length))

# This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))

# Required for WordBoundary event sentences.
speech_config.set_property(property_id=speechsdk.PropertyId.SpeechServiceResponse_RequestSentenceBoundary, value='true')

audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)

# Subscribe to events
speech_synthesizer.bookmark_reached.connect(speech_synthesizer_bookmark_reached_cb)
speech_synthesizer.synthesis_canceled.connect(speech_synthesizer_synthesis_canceled_cb)
speech_synthesizer.synthesis_completed.connect(speech_synthesizer_synthesis_completed_cb)
speech_synthesizer.synthesis_started.connect(speech_synthesizer_synthesis_started_cb)
speech_synthesizer.synthesizing.connect(speech_synthesizer_synthesizing_cb)
speech_synthesizer.viseme_received.connect(speech_synthesizer_viseme_received_cb)
speech_synthesizer.synthesis_word_boundary.connect(speech_synthesizer_word_boundary_cb)

# The language of the voice that speaks.
speech_synthesis_voice_name='en-US-AvaMultilingualNeural'

ssml = """<speak version='1.0' xml:lang='en-US' xmlns='http://www.w3.org/2001/10/synthesis' xmlns:mstts='http://www.w3.org/2001/mstts'>
    <voice name='{}'>
        <mstts:viseme type='redlips_front'/>
        The rainbow has seven colors: <bookmark mark='colors_list_begin'/>Red, orange, yellow, green, blue, indigo, and violet.<bookmark mark='colors_list_end'/>.
    </voice>
</speak>""".format(speech_synthesis_voice_name)

# Synthesize the SSML
print("SSML to synthesize: \r\n{}".format(ssml))
speech_synthesis_result = speech_synthesizer.speak_ssml_async(ssml).get()

if speech_synthesis_result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted:
    print("SynthesizingAudioCompleted result")
elif speech_synthesis_result.reason == speechsdk.ResultReason.Canceled:
    cancellation_details = speech_synthesis_result.cancellation_details
    print("Speech synthesis canceled: {}".format(cancellation_details.reason))
    if cancellation_details.reason == speechsdk.CancellationReason.Error:
        if cancellation_details.error_details:
            print("Error details: {}".format(cancellation_details.error_details))
            print("Did you set the speech resource key and region values?")

Дополнительные текстовые примеры для речи можно найти на сайте GitHub.

Использование пользовательской конечной точки

Пользовательская конечная точка функционально идентична стандартной конечной точке, используемой для текстовых запросов речи.

Одно из различий заключается в том, что endpoint_id его необходимо указать для использования пользовательского голоса с помощью пакета SDK службы "Речь". Вы можете начать с краткого руководства по тексту для речи, а затем обновить код с помощью endpoint_id и speech_synthesis_voice_name.

speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))
speech_config.endpoint_id = "YourEndpointId"
speech_config.speech_synthesis_voice_name = "YourCustomVoiceName"

Чтобы использовать пользовательский голос с помощью языка разметки синтеза речи (SSML), укажите имя модели в качестве имени голоса. В этом примере используется голос YourCustomVoiceName.

<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
    <voice name="YourCustomVoiceName">
        This is the text that is spoken. 
    </voice>
</speak>

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Преобразование речи в текст REST API ссылки на | речь на текстовый REST API для краткой справки по звуковой ссылке | на Дополнительные примеры на GitHub

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Необходимые компоненты

  • Подписка Azure. Вы можете создать бесплатную учетную запись.
  • Создайте ресурс службы "Речь" в портал Azure.
  • Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.

Преобразование текста в речь

В командной строке выполните приведенную ниже команду. Вставьте эти значения в команду:

  • Ключ ресурса службы "Речь"
  • Регион ресурса "Речь"

Также может потребоваться изменить следующие значения:

  • Значение заголовка X-Microsoft-OutputFormat, которое определяет формат аудиовыхода. Список поддерживаемых форматов звуковых выходных данных можно найти в справочнике по REST API речи.
  • Голос речевого вывода. Чтобы получить список голосов, доступных для конечной точки службы "Речь", см. API голосового списка.
  • Выходной файл. В этом примере мы направляем ответ от сервера в файл output.mp3.
curl --location --request POST 'https://YOUR_RESOURCE_REGION.tts.speech.microsoft.com/cognitiveservices/v1' \
--header 'Ocp-Apim-Subscription-Key: YOUR_RESOURCE_KEY' \
--header 'Content-Type: application/ssml+xml' \
--header 'X-Microsoft-OutputFormat: audio-16khz-128kbitrate-mono-mp3' \
--header 'User-Agent: curl' \
--data-raw '<speak version='\''1.0'\'' xml:lang='\''en-US'\''>
    <voice name='\''en-US-AvaMultilingualNeural'\''>
        I am excited to try text to speech
    </voice>
</speak>' > output.mp3

В этом руководстве вы узнаете о распространенных шаблонах проектирования для синтеза речи текста.

Дополнительные сведения о следующих областях см. в разделе "Что такое текст для речи"?

  • Получение ответов в виде потоков в памяти.
  • Настройка частоты выборки и скорости передачи выходных данных.
  • Отправка запросов синтеза с помощью SSML (язык разметки синтеза речи).
  • Использование нейронных голосовых моделей.
  • Подписывание на события и выполнение результатов.

Необходимые компоненты

  • Подписка Azure. Вы можете создать бесплатную учетную запись.
  • Создайте ресурс службы "Речь" в портал Azure.
  • Получение ключа ресурса службы "Речь" и региона. После развертывания ресурса службы "Речь" выберите Перейти к ресурсу для просмотра ключей и управления ими.

Загрузка и установка

Выполните следующие действия и ознакомьтесь с кратким руководством по интерфейсу командной строки службы "Речь" для других требований для платформы.

  1. Выполните следующую команду .NET CLI, чтобы установить интерфейс командной строки службы "Речь".

    dotnet tool install --global Microsoft.CognitiveServices.Speech.CLI
    
  2. Выполните следующие команды, чтобы настроить ключ ресурса службы "Речь" и регион. Замените ключом ресурса "Речь" и замените SUBSCRIPTION-KEY REGION регионом ресурсов службы "Речь".

    spx config @key --set SUBSCRIPTION-KEY
    spx config @region --set REGION
    

Синтезирование речи в виде речи докладчика

Итак, все готово для запуска интерфейса командной строки службы "Речь" для синтезирования речи из текста.

  • В окне консоли перейдите в каталог, содержащий двоичный файл интерфейса командной строки службы "Речь". Затем выполните следующую команду.

    spx synthesize --text "I'm excited to try text to speech"
    

Интерфейс командной строки службы "Речь" создает естественный язык на английском языке через динамик компьютера.

Синтезирование речи в файл

  • Выполните следующую команду, чтобы изменить выходные данные докладчика на файл .wav :

    spx synthesize --text "I'm excited to try text to speech" --audio output greetings.wav
    

Интерфейс командной строки службы "Речь" создает естественный язык на английском языке в greetings.wav звуковой файл.

Запуск и использование контейнера

Контейнеры службы "Речь" предоставляют API конечных точек запросов на основе websocket, к которым обращается пакет SDK службы "Речь" и CLI службы "Речь". По умолчанию пакет SDK службы "Речь" и cli службы "Речь" используют общедоступную службу "Речь". Чтобы использовать контейнер, вам необходимо изменить метод инициализации. Используйте URL-адрес узла контейнера вместо ключа и региона.

Дополнительные сведения о контейнерах см. в разделе "Установка и запуск контейнеров службы "Речь" с помощью Docker.

Следующие шаги