Как писать клиентов
Новый клиент VideoGrace должен разделять control lifecycle и media lifecycle. Это главный способ избежать гонок и дублирования устройств.
flowchart TB
Start[Start process]
Login[CommandLoop login]
Token[Receive access_token]
Join[connect_to_conference_request]
Media[Open media path: UDP primary or WSMedia fallback]
Publish[Optional: create local devices]
Render[Optional: subscribe remote devices]
Events[Process events until shutdown]
Cleanup[device_disconnect + disconnect_from_conference + close transports]
Start --> Login --> Token --> Join --> Media
Media --> Publish
Media --> Render
Publish --> Events
Render --> Events
Events --> Cleanup
Минимальный state machine
stateDiagram-v2
[*] --> Disconnected
Disconnected --> Connecting: open CommandLoop
Connecting --> Ready: connect_response OK
Ready --> Conferencing: connect_to_conference_response OK
Conferencing --> Publishing: device_connect my=1
Conferencing --> Receiving: device_connect my=0
Publishing --> Conferencing: device_disconnect local
Receiving --> Conferencing: device_disconnect remote
Conferencing --> Ready: disconnect_from_conference
Ready --> Disconnected: disconnect/logout
Типы клиентов
| Тип | Что делает | Примеры |
|---|---|---|
| UI client | Управляет пользователем, публикует и принимает media, сообщения, звонки. | web-client, native Client. |
| Publisher bot | Подключается к конференции и публикует synthetic/file media. | Services/FilePlayer. |
| Receiver bot | Подключается к конференции и принимает/обрабатывает remote media. | Services/Recorder. |
| AI agent | Принимает audio/text/context, отправляет ответы или команды. | Планируемый Python client. |
Control client contract
Клиент обязан:
- открыть
CommandLoop; - отправить
connect_request; - сохранить
id,connection_id,access_token,secure_key,max_output_bitrate; - подключиться к конференции через
connect_to_conference_request; - обрабатывать
change_member_state,device_connect,device_disconnect,resolution_change,microphone_active; - корректно закрывать локальные устройства перед выходом.
Publisher contract
Publisher создает локальные capturer devices:
sequenceDiagram
participant Bot
participant Control
participant Server
participant Media
Bot->>Control: device_params(type, name, resolution)
Server-->>Bot: device_connect(my=1, device_id, author_ssrc, port, secure_key)
Bot->>Media: attach author_ssrc
Bot->>Media: send RTP packets to port
Server-->>Others: device_connect(my=0, receiver_ssrc, port)
Publisher не должен сам придумывать device_id. Его выдает сервер.
Receiver contract
Receiver создает renderer session на каждый remote device_connect:
sequenceDiagram
participant Server
participant Bot
participant Media
participant Decoder
Server-->>Bot: device_connect(my=0, receiver_ssrc, author_ssrc, port, codec, secure_key)
Bot->>Media: attach receiver_ssrc
Bot->>Media: send RTP init / RTCP ForceKeyFrame for video
Media-->>Bot: RTP frames by receiver_ssrc
Bot->>Decoder: decrypt/collect/decode/record/process
Receiver должен удалять renderer по device_disconnect.
Media transport выбор
| Runtime | Основной путь | Fallback |
|---|---|---|
| Native C++ | UDP RTP/RTCP | WSMedia WSS mux |
| Browser | WebRTC ICE/DTLS/SRTP | WSMedia WSS mux |
| Mobile Android/iOS | WebRTC ICE/DTLS/SRTP | По решению мобильного SDK |
| Python/AI | На первом этапе WSMedia WSS mux | UDP можно добавить позже при необходимости |
Практический чеклист нового клиента
- Реализовать CommandLoop WS.
- Реализовать parser/serializer нужных JSON-команд.
- Реализовать conference/device state machine.
- Реализовать media transport: UDP или WSMedia.
- Реализовать RTP/RTCP packetization или decoding.
- Реализовать cleanup: локальные devices, renderer sessions, conference, sockets.
- Добавить reconnect policy отдельно для control/media/blob.
- Зафиксировать ограничения клиента в этой документации.