Audio flow
Audio flow в VideoGrace состоит из двух независимых направлений:
- publish - локальный микрофон захватывается, кодируется в Opus и отправляется в media transport;
- receive - удаленный audio device подключается по событию
device_connect, RTP frames принимаются, декодируются и воспроизводятся.
Control channel управляет жизненным циклом устройств. Media channel переносит только RTP/RTCP frames и не должен создавать или удалять server-side devices сам по себе.
Local microphone publish
sequenceDiagram
participant UI
participant Client as VideograceClient
participant Control as Control channel
participant Mic as MicSession
participant Media as Media transport
participant Server
UI->>Client: toggleMic(true)
Client->>Mic: start capture
Mic-->>Client: capture ready(sample_rate, channels)
Client->>Control: device_params(device_type=mic, codec=opus)
Control->>Server: create audio device
Server-->>Control: device_connect(my=1, device_id, author_ssrc, port)
Control-->>Client: local audio device created
Client->>Mic: attach media(author_ssrc, port)
Mic->>Media: register author_ssrc
Mic->>Media: send RTP/Opus frames
Remote audio receive
sequenceDiagram
participant Control as Control channel
participant Client as VideograceClient
participant Audio as Remote AudioSession
participant Media as Media transport
participant Player as Audio playback
Control-->>Client: device_connect(my=0, device_type=mic, receiver_ssrc, port)
Client->>Audio: create session(device_id, client_id)
Audio->>Media: register receiver_ssrc
Audio->>Media: send RTP init
Media-->>Audio: RTP/Opus frames by receiver_ssrc
Audio->>Audio: decode Opus
Audio->>Player: enqueue PCM
Player->>Player: play with jitter buffer
Pipeline
flowchart LR
subgraph Publish[Local publish]
Capture[Microphone capture]
Preprocess[Resample / channel layout]
Encode[Opus encoder]
Packetize[RTP packetizer]
Send[Media transport send]
end
subgraph Receive[Remote receive]
Recv[Media transport receive]
Route[Demux by SSRC]
Decode[Opus decoder]
Buffer[Jitter/playback buffer]
Play[Audio output]
end
Capture --> Preprocess --> Encode --> Packetize --> Send
Recv --> Route --> Decode --> Buffer --> Play
Reconnect behavior
stateDiagram-v2
[*] --> Capturing
Capturing --> Publishing: device_connect my=1
Publishing --> TransportLost: media close/error
TransportLost --> Reattach: media reconnect
Reattach --> Publishing: register SSRC + continue frames
Publishing --> Stopping: toggleMic(false) / leave
Stopping --> [*]
Reconnect media transport не должен пересоздавать microphone device. После reconnect локальная MicSession заново attach/register к media transport и продолжает отправлять RTP frames с тем же published device lifecycle.
Invariants
device_paramsсоздает server-side microphone device; media transport его не создает.device_idживет в control lifecycle.author_ssrcиспользуется локальнойMicSessionдля отправки.receiver_ssrcиспользуется remote audio session для приема.- Повторный
device_connectдля того же remote audio device не должен создавать вторую playback session. toggleMic(false)должен остановить capture, encoder, media attach и отправитьdisconnect_device.- Reconnect media transport не должен менять
device_id.
Diagnostics
Для audio-инцидента в логах нужны:
device_id,client_id,device_type;author_ssrcилиreceiver_ssrc;- capture format: sample rate, channels;
- codec mode: Opus channels, bitrate;
- first RTP packet sent/received;
- decoder init/reinit;
- playback underrun/overrun;
- media transport close/reconnect reason.
Typical failures
- Локальный индикатор микрофона активен, но удаленный участник не слышит звук: проверить
device_params, localdevice_connect my=1, attach к media transport, first RTP sent, server routing. - RTP приходит, но звука нет: проверить Opus decoder, channel mode, playback buffer, audio route, mute state.
- После reconnect звук не возвращается: проверить re-register SSRC и повторную отправку media init, не создавая новый device.
- После выключения/включения микрофона появляется несколько audio sessions: проверить идемпотентность
device_connectи очистку старойMicSession.