yandex-cloud/cloudapi

Проксирование запросов с Фронтенда в Yandex Speechkit в Django при помощи Websocket

Banzaika opened this issue · 0 comments

Здравствуйте, я плохо знаком с данным пакетом, поэтому прошу помощи у вас. Мне нужно написать бэкенд приложение на Джанго, который будет использоваться React'ом как прокси запросов к Yandex SpeechKit, используя WebSocket протокол. В документации приведен пример кода, демонстрирующий потоковое распазнование речи с микрофона, но я слишком глуп, чтобы реконструировать его под мой случай. В Read.me указана документация ко всему YandexCloud, но я не нашел там документацию именно к этому репо. Для каждого вебсокет соединения создается объект питон WebsocketConsumer, у него есть методы connect, receive, disconnect. В методе receive принимается порция аудиоданных в виде bytes, конвертируется при помощи Speechkit и возвращается обратно клиенту. Можете ли привести пример кода, который будет конвертировать аудио в текст при помощи cloudapi при проксировании? Пример WebsocketConsumer, который я успел написать(он неправильный):

from channels.generic.websocket import WebsocketConsumer
import grpc
import cloudapi.output.yandex.cloud.ai.stt.v3.stt_pb2 as stt_pb2
import cloudapi.output.yandex.cloud.ai.stt.v3.stt_service_pb2_grpc as stt_service_pb2_grpc

class MyConsumer(WebsocketConsumer):
    secret = 'some-token'
    rate = 8000
    chunk = 4000
    def get_settings_recognition(self):
        '''Генератор возвращяющий настройки распознавания.'''
        # Задать настройки распознавания.
        recognize_options = stt_pb2.StreamingOptions(
          recognition_model=stt_pb2.RecognitionModelOptions(
             audio_format=stt_pb2.AudioFormatOptions(
                raw_audio=stt_pb2.RawAudio(
                   audio_encoding=stt_pb2.RawAudio.LINEAR16_PCM,
                   sample_rate_hertz=8000,
                   audio_channel_count=1
                )
             ),
             text_normalization=stt_pb2.TextNormalizationOptions(
                text_normalization=stt_pb2.TextNormalizationOptions.TEXT_NORMALIZATION_ENABLED,
                profanity_filter=True,
                literature_text=False
             ),
             language_restriction=stt_pb2.LanguageRestrictionOptions(
                restriction_type=stt_pb2.LanguageRestrictionOptions.WHITELIST,
                language_code=['ru-RU']
             ),
             audio_processing_type=stt_pb2.RecognitionModelOptions.REAL_TIME
          )
        )


        yield stt_pb2.StreamingRequest(session_options=recognize_options)

    def connect(self):

        # Установить соединение с сервером.
        cred = grpc.ssl_channel_credentials()
        channel = grpc.secure_channel('stt.api.cloud.yandex.net:443', cred)
        self.stub = stt_service_pb2_grpc.RecognizerStub(channel)

        # Отправить данные для распознавания.
        self.stub.RecognizeStreaming(self.get_settings_recognition(), metadata=(
          ('authorization', f'Api-Key {self.secret}'),
        ))
        self.accept()

    def disconnect(self, close_code):
        pass

    def gen_chunk(self, audio_data: bytes):
        yield stt_pb2.StreamingRequest(chunk=stt_pb2.AudioChunk(data=audio_data))

    def receive(self, bytes_data):
        audio_data = bytes_data
        audio_data = stt_pb2.StreamingRequest(chunk=stt_pb2.AudioChunk(data=audio_data))
        resp = self.stub.RecognizeStreaming(self.gen_chunk(audio_data), metadata=(
            ('authorization', f'Api-Key {self.secret}'),
        ))
        try:
            event_type, alternatives = resp.WhichOneof('Event'), None
            if event_type == 'partial' and len(resp.partial.alternatives) > 0:
                alternatives = [a.text for a in resp.partial.alternatives]
            if event_type == 'final':
                alternatives = [a.text for a in resp.final.alternatives]
            if event_type == 'final_refinement':
                alternatives = [a.text for a in resp.final_refinement.normalized_text.alternative]
        except grpc._channel._Rendezvous as err:
            print(f'Error code {err._state.code}, message: {err._state.details}')
            raise err
        if not alternatives:
            alternatives = ''
        self.send(text_data=alternatives)