# STT: дополнительные провайдеры и переход на асинхронную схему > Статус: беклог / план развития. Контекст — фича «голосовая диктовка» (STT, > speech-to-text): кнопка-микрофон в чате агента и в редакторе, аудио > распознаётся на сервере через AI-провайдер воркспейса. Документ фиксирует > (1) какие ещё форматы STT-API имеет смысл поддержать и как, и (2) как в > будущем перейти с текущей синхронной схемы (push-to-talk) на асинхронную. ## 1. Где мы сейчас Распознавание построено как **синхронный запрос-ответ**: - Клиент пишет звук (`MediaRecorder`), POST-ит blob → сервер распознаёт → возвращает `{ text }`, который вставляется в ввод. Никакого состояния задачи нет. - Клиентская часть: `apps/client/src/features/dictation/` (`hooks/use-dictation.ts`, `components/mic-button.tsx`, `services/dictation-service.ts`). - Эндпоинт: `POST /ai-chat/transcribe` (`apps/server/src/core/ai-chat/ai-chat.controller.ts`) — фича-гейт `settings.ai.dictation`, throttle, лимит 25 МБ, whitelist mime, вывод реальной ошибки провайдера (`describeProviderError`), формат контейнера выводится из mime. - Тонкая обёртка: `apps/server/src/core/ai-chat/ai-transcription.service.ts` → делегирует в `AiService.transcribe(workspaceId, audio, format)`. - Выбор кодировки запроса — **явное** поле `sttApiStyle` (`apps/server/src/integrations/ai/ai.types.ts`, `SttApiStyle`, `STT_API_STYLES`): - `multipart` — OpenAI-совместимый `POST /v1/audio/transcriptions` (form-data) через AI SDK (`createOpenAI(...).transcription()` + `experimental_transcribe`); - `json` — OpenRouter-стиль: `POST {baseURL}/audio/transcriptions`, `Content-Type: application/json`, тело `{ model, input_audio: { data:, format } }`, ответ `{ text }` (`AiService.transcribeJsonBase64`). - Поле прокладывается как любой не-секрет: `resolve()` / `getMasked()` / whitelist в `AiSettingsService.update` (`apps/server/src/integrations/ai/ai-settings.service.ts`) **и** массив `ALLOWED` в `WorkspaceRepo.updateAiProviderSettings` (`apps/server/src/database/repos/workspace/workspace.repo.ts`). - UI: селектор «Request format» на карточке Voice / STT (`apps/client/.../settings/components/ai-provider-settings.tsx`) + кнопка «Test endpoint» (бэкенд-проба — тихий WAV через тот же `transcribe`). **Важно:** `multipart` уже покрывает почти всю экосистему — её реализуют OpenAI, Azure OpenAI (Whisper), Groq, Together, Fireworks, DeepInfra, vLLM, LM Studio, whisper.cpp/llama.cpp server, `speaches`, `faster-whisper-server`, WhisperX. Для них **новый формат не нужен**, достаточно base URL + модель + ключ. `json` покрывает OpenRouter. Ось `sttApiStyle` — это абстракция над *контрактом запроса/ответа*: каждый реально иной контракт = одно значение enum + одна ветка-энкодер. ### Точки расширения для нового СИНХРОННОГО формата (чек-лист) 1. `ai.types.ts` — добавить значение в `SttApiStyle` и `STT_API_STYLES`. 2. `dto/update-ai-settings.dto.ts` — `@IsIn(STT_API_STYLES)` подхватит автоматически. 3. `ai.service.ts` — ветка в `transcribe()` + приватный энкодер (по образцу `transcribeJsonBase64`): сборка запроса, заголовок авторизации, `!res.ok` → бросок со статусом+телом (без утечки ключа), парс ответа в `text`. 4. Клиент: `ai-settings-service.ts` (тип `SttApiStyle`), опция в `