Серверная часть голосового ввода (слайд 11 «Записать → Проверить»). POST /api/v1/me/{token}/stt принимает WAV 16 кГц mono и возвращает распознанный текст. Ручка только расшифровывает: пациент проверяет текст и отправляет его обычным сообщением, поэтому safety, scrub() и шлюз LLM срабатывают как для набранного текста. Аудио не сохраняется и не логируется.
app/llm/stt.py: протокол SpeechToText, OpenRouterSTT (input_audio, google/gemini-2.5-flash, прокси и повторы по образцу vobot), MockSTT (офлайн).
STT_PROVIDER=auto|off|mock|openrouter (auto = OpenRouter при наличии ключа, иначе mock), STT_MODEL, лимит 60 с.
/patient/capabilities → voice_input.
Тексты промпта — в config/texts/stt.yaml; ADR-014: OpenRouter только на синтетике, для пилота SaluteSpeech (#121).
## Что меняется
Серверная часть голосового ввода (слайд 11 «Записать → Проверить»). `POST /api/v1/me/{token}/stt` принимает WAV 16 кГц mono и возвращает распознанный текст. Ручка **только расшифровывает**: пациент проверяет текст и отправляет его обычным сообщением, поэтому safety, `scrub()` и шлюз LLM срабатывают как для набранного текста. Аудио не сохраняется и не логируется.
- `app/llm/stt.py`: протокол `SpeechToText`, `OpenRouterSTT` (`input_audio`, `google/gemini-2.5-flash`, прокси и повторы по образцу vobot), `MockSTT` (офлайн).
- `STT_PROVIDER=auto|off|mock|openrouter` (`auto` = OpenRouter при наличии ключа, иначе mock), `STT_MODEL`, лимит 60 с.
- `/patient/capabilities` → `voice_input`.
- Тексты промпта — в `config/texts/stt.yaml`; ADR-014: OpenRouter только на синтетике, для пилота SaluteSpeech (#121).
Closes #116
## Зона
B (+ `app/config.py`, `.env.example` — контрактные, добавлены только новые поля)
## Как проверить
`uv run pytest tests/test_llm_stt.py tests/test_api_stt.py` (OpenRouter замокан через `httpx.MockTransport`). Вживую: `curl -H 'Content-Type: audio/wav' --data-binary @v.wav localhost:8000/api/v1/me/<token>/stt`.
## Чек-лист
- [x] rebase на origin/dev
- [x] make lint + make test зелёные (1078 passed)
- [x] лог в issue
- [x] нет ПДн в логах (длительность/провайдер/время/длина текста), нет секретов
- [ ] живой прогон с новым ключом OpenRouter — старый ключ в `.env` отвечает 401
🤖 Generated with [Claude Code](https://claude.com/claude-code)
POST /api/v1/me/{token}/stt takes a 16 kHz mono WAV and only transcribes:
the patient checks the text and sends it as an ordinary message, so safety,
scrub() and the LLM gateway still apply. Audio is neither stored nor logged.
OpenRouter STT is synthetic-data only (ADR-014); SaluteSpeech for the pilot is #121.
Refs #116
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Live check on synthetic speech (espeak) via OpenRouter gemini-2.5-flash:
3–5 s per clip, silence → no speech.
Refs #116
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Что меняется
Серверная часть голосового ввода (слайд 11 «Записать → Проверить»).
POST /api/v1/me/{token}/sttпринимает WAV 16 кГц mono и возвращает распознанный текст. Ручка только расшифровывает: пациент проверяет текст и отправляет его обычным сообщением, поэтому safety,scrub()и шлюз LLM срабатывают как для набранного текста. Аудио не сохраняется и не логируется.app/llm/stt.py: протоколSpeechToText,OpenRouterSTT(input_audio,google/gemini-2.5-flash, прокси и повторы по образцу vobot),MockSTT(офлайн).STT_PROVIDER=auto|off|mock|openrouter(auto= OpenRouter при наличии ключа, иначе mock),STT_MODEL, лимит 60 с./patient/capabilities→voice_input.config/texts/stt.yaml; ADR-014: OpenRouter только на синтетике, для пилота SaluteSpeech (#121).Closes #116
Зона
B (+
app/config.py,.env.example— контрактные, добавлены только новые поля)Как проверить
uv run pytest tests/test_llm_stt.py tests/test_api_stt.py(OpenRouter замокан черезhttpx.MockTransport). Вживую:curl -H 'Content-Type: audio/wav' --data-binary @v.wav localhost:8000/api/v1/me/<token>/stt.Чек-лист
.envотвечает 401🤖 Generated with Claude Code
POST /api/v1/me/{token}/stt takes a 16 kHz mono WAV and only transcribes: the patient checks the text and sends it as an ordinary message, so safety, scrub() and the LLM gateway still apply. Audio is neither stored nor logged. OpenRouter STT is synthetic-data only (ADR-014); SaluteSpeech for the pilot is #121. Refs #116 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>