Skip to content

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, local device_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.