Zeli AvatarDeveloper docs
v0.1.0

Guides / Connecting

Connecting

Configure a ZeliClient, open a session, and manage its lifecycle — either as an async context manager or by hand.

Creating a client

A ZeliClient holds your configuration and event handlers. Point it at your server with ClientOptions and describe the avatar with AvatarConfig.

from zeli import ZeliClient, AvatarConfig, ClientOptions
 
client = ZeliClient(
    avatar_config=AvatarConfig(
        avatar_id="presenter-male-1080",
        voice_id="your-voice-id",
        emotion_responsive=True,
    ),
    options=ClientOptions(
        server_url="http://your-server:8080",
        connect_timeout=30.0,
    ),
)

You can also pass just an avatar id as a shorthand:

client = ZeliClient(
    avatar_id="presenter-male-1080",
    options=ClientOptions(server_url="http://your-server:8080"),
)

Pass either avatar_id or avatar_config, not both — doing both raises ConfigurationError. server_url is required.

Opening a session

connect() works two ways. As an async context manager (recommended), the session is closed for you:

async with client.connect() as session:
    print(session.session_id, session.avatar)
    await session.wait_until_closed()

Or awaited directly, when you want to manage the lifetime yourself:

session = await client.connect()
try:
    ...
finally:
    await session.close()

Session options

from zeli import SessionOptions
 
options = SessionOptions(
    video_quality="high",  # or "auto" to adapt to bandwidth
    receive_video=True,
    receive_audio=True,
)
 
async with client.connect(options) as session:
    ...

Lifecycle

  • session.session_id — the server-issued id for the session.
  • session.avatar — the concrete avatar the server resolved.
  • session.is_activeFalse once closed.
  • await session.wait_until_closed() — blocks until the server closes the session, the media connection drops, or you call close().

When the connection ends, the client emits CONNECTION_CLOSED.

What happens under the hood

  1. The SDK negotiates a WebRTC connection via the server's POST /connect endpoint (audio + video, receive-only).
  2. It opens the control channel (a WebSocket) for commands and events.
  3. If the server predates the control gateway, the SDK falls back to plain HTTP for send_message; talk / talk streams then require an upgraded server. Check session.has_control_channel to detect this.
Zeli Avatar · real-time avatars over WebRTC · self-hostable · AU data residency · source