Python/AI client
Python client нужен для AI-сценариев: speech-to-text, summaries, command agents, bots, semantic search по конференции, voice assistant. На первом этапе его лучше делать как receiver/publisher bot поверх WebSocket/WSS API, без native UDP.
Рекомендуемый первый scope
flowchart TB
Py[Python AI client]
Control[CommandLoop WS]
Media[WSMedia WSS mux]
STT[Speech-to-text]
LLM[AI logic]
Out[Optional response: text/audio/control]
Py --> Control
Py --> Media
Media --> STT
STT --> LLM
LLM --> Out
Out --> Control
Out --> Media
Первый MVP:
- логин по
CommandLoop; - вход в конференцию;
- прием remote microphone streams через
WSMedia; - Opus decode;
- передача PCM в STT/AI pipeline;
- отправка текстового результата в chat или внешний webhook.
Почему WSMedia, а не UDP
Для AI клиента WSS проще:
- один transport через firewall/NAT;
- одинаковая модель с browser media;
- меньше требований к системным правам и UDP routing;
- проще запускать в облаке и контейнерах.
UDP можно добавить позже для low-latency on-prem deployments.
Предлагаемая структура SDK
python-videograce/
videograce/
control.py # CommandLoop JSON WS
media_mux.py # WSMedia binary mux/demux
protocol.py # command dataclasses / serializers
rtp.py # RTP/RTCP helpers
opus.py # decode/encode integration
client.py # high-level state machine
examples/
record_audio.py
ai_observer.py
speaking_bot.py
High-level API
async with VideoGraceClient(server, login, password) as vg:
await vg.join_conference("default", receive=True, publish=False)
async for event in vg.events():
if isinstance(event, RemoteAudioFrame):
pcm = opus.decode(event.payload)
text = await stt.feed(pcm)
if text:
await vg.send_message(event.conference_tag, text)
Это псевдокод. Реальный SDK должен явно разделять control events и media frames.
Обязательные инварианты SDK
- Control reconnect и media reconnect независимы.
- Один
WSMediasocket на client/access token. - Demux только по
ssrc. device_idне использовать для media routing.- На reconnect заново отправлять RTP init для receiver streams.
- Для video receiver отправлять ForceKeyFrame после attach/reconnect.
- Не создавать локальные devices до
connect_to_conference_response OK.
Следующие решения
| Вопрос | Рекомендация |
|---|---|
| Какой async runtime | asyncio, без thread-heavy модели. |
| JSON protocol | dataclasses + explicit enum values из Engine/Proto. |
| Media transport | Сначала WSMedia mux only. |
| Audio decode | Opus через opuslib, pyogg или собственную thin binding. |
| Video | На первом этапе не декодировать, только audio. Видео добавить отдельным milestone. |
| Auth | Логин/пароль на control, token на media/blob. |