Синтез речи по шаблонам с помощью API v3

Синтез по шаблонам в Brand Voice Premium и Brand Voice Self Service доступен только для голосов SpeechKit Brand Voice.

Важно

Сервисы Brand Voice Premium и Brand Voice Self Service предоставляются по запросу. Для доступа к технологии заполните форму на сайте.

Чтобы синтезировать фразу по шаблону:

  1. Подготовьте шаблон аудиозаписи.
  2. Отправьте данные в API v3.

Перед началом работы

  1. Клонируйте репозиторий Yandex Cloud API:

    git clone https://github.com/yandex-cloud/cloudapi
            
  2. Создайте сервисный аккаунт для работы с API SpeechKit.

  3. Назначьте сервисному аккаунту роль ai.speechkit-tts.user или выше на каталог, в котором он был создан.

  4. Получите IAM-токен для сервисного аккаунта.

Подготовьте шаблон аудиозаписи

Шаблон состоит из аудиозаписи шаблонной фразы и размеченного текста фразы.

Ограничения на параметры шаблона:

  • Максимальная длительность фразы для синтеза — 24 секунды (ограничение API) вместе с переменной частью. Оптимальная для восприятия длительность фразы — не более 16 секунд, как в разговорной речи.
  • Длина шаблона — не более 250 символов нормализованного текста.
  • Нормализованный текст переменной части занимает не больше 25% от длины шаблона. То же ограничение действует на длительность переменной части относительно длительности итоговой аудиозаписи.

Важно

Отправляйте в API синтеза шаблоны с переменными частями. Неизменяемые фразы отправлять не нужно.

Примеры неизменяемых фраз:

Здравствуйте, с вами говорят из клиники "МедСити".

Добрый день, это компания по вывозу строительного мусора "Вывозов".

Чтобы подготовить шаблон:

  1. Запишите аудио шаблонной фразы.

  2. Разметьте текст шаблонной фразы согласно требованиям и оберните переменные части в скобки {}.

    Пример размеченного текста: Напоминаем, что {date} в {time} к вам приедет машина с контейнером для вывоза мусора.
    Список переменных: variable_name = '{date}', variable_value = 'завтра', variable_name = '{time}', variable_value = 'четырнадцать часов'.

  3. Определите для каждой переменной части время начала и ее длительность в аудиозаписи (в миллисекундах).

Отправьте данные в API v3

Создайте и запустите клиентское приложение для отправки данных:

  1. Склонируйте репозиторий Yandex Cloud API:

    git clone https://github.com/yandex-cloud/cloudapi
            
  2. Установите зависимости с помощью менеджера пакетов pip:

    pip install grpcio-tools && \
            pip install pydub
            

    Пакет grpcio-tools нужен для генерации кода интерфейса клиента API v3 синтеза.

    Пакет pydub нужен для обработки полученных аудиофайлов.

  3. Скачайте утилиту FFmpeg для корректной работы пакета pydub.

  4. Добавьте путь к папке, в которой находится исполняемый файл FFmpeg, в переменную PATH:

    export PATH=$PATH:<путь_к_папке_с_исполняемым_файлом_FFmpeg>
            
  5. Перейдите в папку с клонированным репозиторием Yandex Cloud API, создайте папку output и сгенерируйте в ней код интерфейса клиента:

    cd <путь_к_папке_cloudapi> && \
            mkdir output && \
            python3 -m grpc_tools.protoc -I . -I third_party/googleapis \
              --python_out=output \
              --grpc_python_out=output \
              google/api/http.proto \
              google/api/annotations.proto \
              yandex/cloud/api/operation.proto \
              google/rpc/status.proto \
              yandex/cloud/ai/tts/v3/tts_service.proto \
              yandex/cloud/ai/tts/v3/tts.proto
            

    В папке output будут созданы файлы с интерфейсом клиента: tts_pb2.py, tts_pb2_grpc.py, tts_service_pb2.py, tts_service_pb2_grpc.py и файлы зависимостей.

  6. В корне папки output создайте файл test.py и добавьте в него код для синтеза API v3 по шаблонам.

    test.py
    import io
            import pydub
            import argparse
            
            import yandex.cloud.ai.tts.v3.tts_pb2 as tts_pb2
            import yandex.cloud.ai.tts.v3.tts_service_pb2_grpc as tts_service_pb2_grpc
            
            def synthesize(iam_token, bytes_array) -> pydub.AudioSegment:
                template = "<шаблонная_фраза_с_разметкой>"
                # Пример шаблона: 'Напоминаем, что {date} в {time}, ваш ребенок записан на процедуру {procedure}.'
                request = tts_pb2.UtteranceSynthesisRequest(
                    output_audio_spec=tts_pb2.AudioFormatOptions(
                        container_audio=tts_pb2.ContainerAudio(
                            container_audio_type=tts_pb2.ContainerAudio.WAV
                        )
                    ),
                    loudness_normalization_type=tts_pb2.UtteranceSynthesisRequest.LUFS,
                    text_template = tts_pb2.TextTemplate(
                        text_template = template,
                        variables = [
                            # Задайте список переменных шаблона.
                            # Количество элементов tts_pb2.TextVariable() в списке определяется количеством переменных в шаблоне.
                            tts_pb2.TextVariable(
                                variable_name = "<имя_переменной_в_template>",
                                # Пример: '{time}'
                                variable_value = "<текст_для_синтеза>"
                                # Пример: 'восемь часов тридцать минут'
                            )
                        ]
                    ),
                    hints = [
                        tts_pb2.Hints(
                            audio_template = tts_pb2.AudioTemplate(
                                audio = tts_pb2.AudioContent(
                                    # Загрузите исходное аудио для шаблона.
                                    content = bytes_array,
                                    audio_spec = tts_pb2.AudioFormatOptions(
                                        container_audio = tts_pb2.ContainerAudio(
                                            container_audio_type = tts_pb2.ContainerAudio.WAV
                                        )
                                    )
                                ),
                                text_template = tts_pb2.TextTemplate(
                                    text_template = template,
                                    variables = [
                                        # Задайте список переменных шаблона.
                                        # Количество элементов tts_pb2.TextVariable() в списке определяется количеством переменных в шаблоне.
                                        tts_pb2.TextVariable(
                                            variable_name = "<имя_переменной_в_template>",
                                            variable_value = "<текст_переменной_части_фразы_в_звуковом_файле_шаблона>"
                                        )
                                    ]
                                ),
                                variables = [
                                    # Задайте список аудиопараметров переменных шаблона.
                                    # Количество элементов tts_pb2.AudioVariable() в списке определяется количеством переменных в шаблоне.
                                    tts_pb2.AudioVariable(
                                        variable_name = "<имя_переменной_в_template>",
                                        # Длина переменной части фразы в аудио шаблона (в миллисекундах).
                                        variable_length_ms = <длина_переменной>,
                                        # Начало переменной части фразы в аудио шаблона (в миллисекундах).
                                        variable_start_ms = <время_начала_переменной>
                                    )
                                ]
                            )
                       ),
                       tts_pb2.Hints(
                           voice = "<идентификатор_вашего_голоса>"
                       )
                    ],
                )
            
                # Установите соединение с сервером.
                cred = grpc.ssl_channel_credentials()
                channel = grpc.secure_channel('tts.api.cloud.yandex.net:443', cred)
                stub = tts_service_pb2_grpc.SynthesizerStub(channel)
            
                # Отправьте данные для синтеза.
                it = stub.UtteranceSynthesis(request, metadata=(
                    ("authorization", f"Bearer {iam_token}"),
                ))
            
                # Обработайте ответы сервера и запишите результат в файл.
                try:
                    audio = io.BytesIO()
                    for response in it:
                        audio.write(response.audio_chunk.data)
                    audio.seek(0)
                    return pydub.AudioSegment.from_wav(audio)
                except grpc._channel._Rendezvous as err:
                    print(f'Error code {err._state.code}, message: {err._state.details}')
                    raise err
            
            
            if __name__ == '__main__':
                parser = argparse.ArgumentParser()
                parser.add_argument('--token', required=True, help='IAM token')
                parser.add_argument('--input', required=True, help='Template WAV file')
                parser.add_argument('--output', required=True, help='Output WAV file with synthesized speech')
                args = parser.parse_args()
            
                with open(args.input, 'rb') as file:
                    speech = file.read()
            
                audio = synthesize(args.token, speech)
                with open(args.output, 'wb') as fp:
                    audio.export(fp, format='wav')
            
  7. Выполните файл test.py:

    export IAM_TOKEN=<IAM-токен_сервисного_аккаунта> && \
            python3 output/test.py \
              --token ${IAM_TOKEN} \
              --input sample.wav \
              --output speech.wav
            

    Где:

В папке cloudapi будет создан файл speech.wav с синтезированной по шаблону фразой.

См. также