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

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

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

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

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

Важная информация

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

Использование сервиса

Создание клиентского приложения

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

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

Чтобы приложение смогло обращаться к сервису, необходимо сгенерировать код интерфейса клиента для используемого языка программирования. Сгенерируйте этот код из файла stt_service.proto из репозитория Yandex.Cloud API.

Ниже представлены примеры клиентских приложений. Помимо этого, в документации gRPC вы можете найти подробные инструкции по генерации интерфейсов и реализации клиентских приложений для различных языков программирования.

Авторизация в сервисе

В каждом запросе приложение должно передавать идентификатор каталога, на который у вас есть роль editor или выше. Подробнее в разделе Управление доступом.

Также приложение должно аутентифицироваться при каждом запросе, например при помощи IAM-токена. Подробнее об аутентификации в сервисе.

Результат распознавания

В процессе распознавания речь делится на фразы. Фраза — это фрагмент речи из одного и более слов, после которого был период тишины. Фраза может состоять из предложений, если между ними не было паузы.

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

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

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

Вы можете указать, чтобы сервис возвращал промежуточные результаты распознавания. Для этого в сообщении с настройками распознавания укажите config.specification.partial_results=true. В ответе для промежуточных результатов final=false, а для финальных final=true.

Ограничения сессии распознавания речи

После получения сообщения с настройками распознавания сервис начнет сессию распознавания. Для каждой сессии действуют следующие ограничения:

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

    Например, каждые 400 мс отправляйте на распознавание 400 мс аудио.

  • Максимальная длительность переданного аудио за всю сессию — 5 минут.

  • Максимальный размер переданных аудиоданных — 10 МБ.

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

API сервиса

Сервис располагается по адресу: stt.api.cloud.yandex.net:443

Сообщение с настройками распознавания

Параметр Описание
config object
Поле с настройками распознавания и идентификатором каталога.
config
.specification
object
Настройки распознавания.
config
.specification
.languageCode
string
Язык, для которого будет выполнено распознавание.
Допустимые значения:
  • ru-RU (по умолчанию) — русский язык,
  • en-US — английский язык.
  • tr-TR — турецкий язык.
config
.specification
.model
string
Языковая модель, которую следует использовать при распознавании.
Чем точнее выбрана модель, тем лучше результат распознавания. В одном запросе можно указать только одну модель.
Допустимые значения зависят от выбранного языка. Значение параметра по умолчанию: general.
config
.specification
.profanityFilter
boolean
Фильтр ненормативной лексики.
Допустимые значения:
  • true — исключать ненормативную лексику из результатов распознавания.
  • false (по умолчанию) — не исключать ненормативную лексику.
config
.specification
.partialResults
boolean
Фильтр промежуточных результатов.
Допустимые значения:
  • true — возвращать промежуточные результаты (часть распознанного высказывания). Для промежуточных результатов final равно false.
  • false (по умолчанию) — возвращать только финальные результаты (распознанное высказывание целиком).
config
.specification
.audioEncoding
string
Формат передаваемого аудио.
Допустимые значения:
config
.specification
.sampleRateHertz
integer (int64)
Частота дискретизации передаваемого аудио.
Этот параметр обязателен, если значение format равно LINEAR16_PCM. Допустимые значения:
  • 48000 (по умолчанию) — частота дискретизации 48 кГц;
  • 16000 — частота дискретизации 16 кГц;
  • 8000 — частота дискретизации 8 кГц.
folderId string

Идентификатор каталога, к которому у вас есть доступ. Требуется для авторизации с пользовательским аккаунтом (см. ресурс UserAccount ). Не используйте это поле, если вы делаете запрос от имени сервисного аккаунта.

Максимальная длина строки в символах — 50.

Сообщение с аудиофрагментом

Параметр Описание
audio_content Фрагмент аудио в виде массива байт. Аудио должно быть в формате, указанном в сообщении с настройками распознавания.

Структура ответа

При успешном распознавании фрагмента речи придет сообщение, содержащее список результатов распознавания chunks[]. Каждый результат содержит поля:

  • alternatives[] - список вариантов распознанного текста. Каждый вариант содержит поля:
    • text - распознанный текст.
    • confidence - достоверность определения. Сейчас сервис всегда возвращает значение 1, которое эквивалентно 100%.
  • final - равно true, если результат окончательный, и false, если промежуточный.

Коды ошибок, возвращаемые сервером

Соответствия gRPC-статусов с HTTP-кодами описаны в google.rpc.Code.

Список возможных gRPC-ошибок, возвращаемых сервисом:

Код Статус Описание
3 INVALID_ARGUMENT Клиент некорректно указал параметры запроса. Детальная информация представлена в поле details.
16 UNAUTHENTICATED Для выполнения операции необходима авторизация. Проверьте IAM-токен и идентификатор каталога, которые вы передали
13 INTERNAL Внутренняя ошибка сервера. Ошибка означает, что операция не может быть выполнена из-за технического состояния сервера. Например, из-за нехватки вычислительных ресурсов.

Примеры

Для того чтобы попробовать примеры в этом разделе:

  1. Склонируйте репозиторий Yandex.Cloud API:
    git clone https://github.com/yandex-cloud/cloudapi
    
  2. Узнайте идентификатор каталога, к которому у вашего аккаунта есть доступ.
  3. Для аутентификации в примерах используется IAM-токен (о других способах аутентификации). Получите IAM-токен:
  4. Скачайте пример аудиофайла для распознавания. Аудиофайл имеет формат LPCM с частотой дискретизации 8000.

После этого приступите к созданию клиентского приложения.

  1. Установите пакет grpcio-tools с помощью менеджера пакетов pip:

    $ pip install grpcio-tools
    
  2. Перейдите в директорию с репозиторием Yandex.Cloud API, создайте директорию output и сгенерируйте в ней код интерфейса клиента:

    $ cd cloudapi
    $ mkdir output
    $ python -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/operation/operation.proto yandex/cloud/ai/stt/v2/stt_service.proto
    

    В результате в директории output будут созданы файлы с интерфейсом клиента: stt_service_pb2.py, stt_service_pb2_grpc.py и файлы зависимостей.

  3. Создайте файл в корне директории output, например test.py, и добавьте в него следующий код:

    #coding=utf8
    import argparse
    
    import grpc
    
    import yandex.cloud.ai.stt.v2.stt_service_pb2 as stt_service_pb2
    import yandex.cloud.ai.stt.v2.stt_service_pb2_grpc as stt_service_pb2_grpc
    
    
    CHUNK_SIZE = 4000
    
    def gen(folder_id, audio_file_name):
        # Задать настройки распознавания.
        specification = stt_service_pb2.RecognitionSpec(
            language_code='ru-RU',
            profanity_filter=True,
            model='general',
            partial_results=True,
            audio_encoding='LINEAR16_PCM',
            sample_rate_hertz=8000
        )
        streaming_config = stt_service_pb2.RecognitionConfig(specification=specification, folder_id=folder_id)
    
        # Отправить сообщение с настройками распознавания.
        yield stt_service_pb2.StreamingRecognitionRequest(config=streaming_config)
    
        # Прочитать аудиофайл и отправить его содержимое порциями.
        with open(audio_file_name, 'rb') as f:
            data = f.read(CHUNK_SIZE)
            while data != b'':
                yield stt_service_pb2.StreamingRecognitionRequest(audio_content=data)
                data = f.read(CHUNK_SIZE)
    
    
    def run(folder_id, iam_token, audio_file_name):
        # Установить соединение с сервером.
        cred = grpc.ssl_channel_credentials()
        channel = grpc.secure_channel('stt.api.cloud.yandex.net:443', cred)
        stub = stt_service_pb2_grpc.SttServiceStub(channel)
    
        # Отправить данные для распознавания.
        it = stub.StreamingRecognize(gen(folder_id, audio_file_name), metadata=(('authorization', 'Bearer %s' % iam_token),))
    
        # Обработать ответы сервера и вывести результат в консоль.
        try:
            for r in it:
                try:
                    print('Start chunk: ')
                    for alternative in r.chunks[0].alternatives:
                        print('alternative: ', alternative.text)
                    print('Is final: ', r.chunks[0].final)
                    print('')
                except LookupError:
                    print('Not available chunks')
        except grpc._channel._Rendezvous as err:
            print('Error code %s, message: %s' % (err._state.code, err._state.details))
    
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser()
        parser.add_argument('--token', required=True, help='IAM token')
        parser.add_argument('--folder_id', required=True, help='folder ID')
        parser.add_argument('--path', required=True, help='audio file path')
        args = parser.parse_args()
    
        run(args.folder_id, args.token, args.path)
    
  4. Выполните созданный файл, передав в аргументах IAM-токен, идентификатор каталога и путь к аудиофайлу, который необходимо распознать:

    $ export FOLDER_ID=b1gvmob95yysaplct532
    $ export IAM_TOKEN=CggaATEVAgA...
    $ python test.py --token ${IAM_TOKEN} --folder_id ${FOLDER_ID} --path speech.pcm
    Start chunk:
    alternative: привет
    Is final: False
    
    Start chunk:
    alternative: привет мир
    Is final: True
    
  1. Перейдите в директорию с репозиторием Yandex.Cloud API, создайте директорию src и сгенерируйте в ней файл зависимостей package.json:

    $ cd cloudapi
    $ mkdir src
    $ cd src
    $ npm init
    
  2. Установите необходимые пакеты с помощью npm:

    $ npm install grpc @grpc/proto-loader google-proto-files --save
    
  3. Скачайте публичный сертификат gRPC из официального репозитория и сохраните его в корне директории src.

  4. Создайте файл в корне директории src, например index.js, и добавьте в него следующий код:

    const fs = require('fs');
    const grpc = require('grpc');
    const protoLoader = require('@grpc/proto-loader');
    const CHUNK_SIZE = 4000;
    
    // Получаем ID каталога и IAM-токен из переменных окружения.
    const folderId = process.env.FOLDER_ID;
    const iamToken = process.env.IAM_TOKEN;
    
    // Читаем файл, указанный в аргументах.
    const audio = fs.readFileSync(process.argv[2]);
    
    // Задать настройки распознавания.
    const request = {
        config: {
            specification: {
                languageCode: 'ru-RU',
                profanityFilter: true,
                model: 'general',
                partialResults: true,
                audioEncoding: 'LINEAR16_PCM',
                sampleRateHertz: '8000'
            },
            folderId: folderId
        }
    };
    
    // Частота отправки аудио в миллисекундах.
    // Для формата LPCM частоту можно рассчитать по формуле: CHUNK_SIZE * 1000 / ( 2 * sampleRateHertz);
    const FREQUENCY = 250;
    
    const serviceMetadata = new grpc.Metadata();
    serviceMetadata.add('authorization', `Bearer ${iamToken}`);
    
    const packageDefinition = protoLoader.loadSync('../yandex/cloud/ai/stt/v2/stt_service.proto', {
        includeDirs: ['node_modules/google-proto-files', '..']
    });
    const packageObject = grpc.loadPackageDefinition(packageDefinition);
    
    // Установить соединение с сервером.
    const serviceConstructor = packageObject.yandex.cloud.ai.stt.v2.SttService;
    const grpcCredentials = grpc.credentials.createSsl(fs.readFileSync('./roots.pem'));
    const service = new serviceConstructor('stt.api.cloud.yandex.net:443', grpcCredentials);
    const call = service['StreamingRecognize'](serviceMetadata);
    
    // Отправить сообщение с настройками распознавания.
    call.write(request);
    
    // Прочитать аудиофайл и отправить его содержимое порциями.
    let i = 1;
    const interval = setInterval(() => {
        if (i * CHUNK_SIZE <= audio.length) {
            const chunk = new Uint16Array(audio.slice((i - 1) * CHUNK_SIZE, i * CHUNK_SIZE));
            const chunkBuffer = Buffer.from(chunk);
            call.write({audioContent: chunkBuffer});
            i++;
        } else {
            call.end();
            clearInterval(interval);
        }
    }, FREQUENCY);
    
    // Обработать ответы сервера и вывести результат в консоль.
    call.on('data', (response) => {
        console.log('Start chunk: ');
        response.chunks[0].alternatives.forEach((alternative) => {
            console.log('alternative: ', alternative.text)
        };)
        console.log('Is final: ', Boolean(response.chunks[0].final));
        console.log('');
    })
    
    
  1. Задайте переменные FOLDER_ID и IAM_TOKEN, которые используются в скрипте, и выполните созданный файл. В аргументах укажите путь к аудиофайлу:

    $ export FOLDER_ID=b1gvmob95yysaplct532
    $ export IAM_TOKEN=CggaATEVAgA...
    $  node index.js speech.pcm
    
    Start chunk:
    alternative:  привет мир
    Is final:  true