Header Logo

How to Implement Avatar Presets and Theme Variants for a Streaming AI Avatar

How to Implement Avatar Presets and Theme Variants for a Streaming AI Avatar

Implement avatar presets and theme variants for streaming AI avatars with server-side session config, validation, and WebRTC-safe runtime mapping.

Introduction


When you add a streaming AI avatar to a product, “an avatar” usually turns into a family of avatars very quickly. Different customers want different faces, outfits, camera framing, or motion styles. Different product surfaces want different presentation: a support bot should look calm and readable, while a game NPC might lean more expressive. And if your avatar is driven by a realtime voice agent, those visual choices need to be selectable at session start without breaking lip sync, latency, or your deployment model.


This post covers a practical way to implement avatar presets and theme variants for a streaming AI avatar. By the end, you should be able to design a preset model, map it to runtime session configuration, keep backend and frontend boundaries clean, and avoid the common mistake of treating appearance as an afterthought. The examples use a realtime avatar platform like Protoface, but the implementation ideas apply broadly to WebRTC-backed avatars and voice agents.


Start by separating identity from presentation


The first design decision is to stop thinking of “avatar” as a single object. You usually want at least two layers:


  • Identity: who or what the avatar represents — for example, a support persona, a brand mascot, or a game character.

  • Presentation: how that identity is rendered — skin, clothing, background, framing, camera crop, lighting, motion aggressiveness, and perhaps voice pairing.


That split matters because identity tends to be stable, while presentation is often contextual. You may want the same support persona rendered in a “light” and “dark” theme, or the same character in “formal” and “casual” presets.


In practice, your preset model should be small and explicit. A good preset is just a named bundle of render parameters plus any session-time instructions the avatar runtime needs. For example:


{
}
{
}
{
}


Notice what is not in the preset: anything that belongs to the underlying model or session transport. Don’t couple UI theme variants to how you connect over WebRTC, and don’t tie visual presentation to your agent logic. You want to change the former without touching the latter.


Design presets as immutable templates, not free-form knobs


It is tempting to expose every render option directly in the UI and let callers compose them arbitrarily. That usually becomes hard to test and harder to support. A better pattern is to define a small set of curated presets that you can validate and version.


Think of the preset lifecycle like this:


  1. A developer or product manager defines a preset in your dashboard or config.

  2. The preset is validated against allowed assets, voice options, and instructions limits.

  3. At runtime, the application selects a preset by ID and creates a session with those settings.

  4. The avatar runtime loads the corresponding visual and behavioral configuration.


This gives you a few advantages:


  • Predictability: every preset is tested, so rendering and lip sync behave consistently.

  • Access control: you can prevent arbitrary asset URLs or unsupported settings.

  • Versioning: you can roll out new looks without breaking existing sessions.


If you need a lot of variants, create them from composition rather than ad hoc configuration. For example, a “brand” preset may define the avatar identity, and a “theme” overlay may adjust background and palette. Keep the number of dimensions small. A matrix of 5 avatars × 6 themes × 4 camera modes is already 120 combinations, which is manageable only if your config is clean and your validation is automated.


Model theme variants as data, then resolve them at session creation


A useful implementation pattern is to store variants as data that your backend resolves into a runtime session payload. The frontend should select a preset; the backend should turn that selection into the exact avatar/session parameters expected by your realtime service.


For example, the frontend might send only a preset key:


POST /api/start-avatar-session
}
POST /api/start-avatar-session
}
POST /api/start-avatar-session
}


The backend then maps that to the actual session configuration:


{
}
{
}
{
}


This indirection is important for two reasons. First, it lets you change internal asset IDs without forcing frontend changes. Second, it keeps sensitive or operational logic server-side. If you are using browser embeds, that boundary is especially important: the browser should receive only the minimum information needed to render or connect, never long-lived credentials.


Some practical rules:


  • Use stable preset IDs, not UI labels, as runtime keys.

  • Version presets when visual assets or instructions change materially.

  • Validate theme assets before saving the preset, not at call time.

  • Keep instruction text short and bounded; runtime prompts are configuration, not a content management system.


Implement session creation in Python, not in the browser


If you are building a backend that launches avatar sessions, use your server to resolve the chosen preset and create the session. A Python SDK is a good fit for this because it keeps API keys off the client and makes it straightforward to wire avatar selection into your app logic.


from protoface_sdk import ProtofaceClient  # illustrative import; see docs for exact package/API

print(session.id)
from protoface_sdk import ProtofaceClient  # illustrative import; see docs for exact package/API

print(session.id)
from protoface_sdk import ProtofaceClient  # illustrative import; see docs for exact package/API

print(session.id)


The exact method names and fields depend on the SDK version, so treat this as structural code, not copy-paste production code. The important part is the shape of the flow: resolve preset on the server, create the realtime session with the resolved config, then hand the client only the session-specific connection details it needs.


If your avatar is paired with a voice agent, keep the avatar session and the agent session synchronized by session ID or a shared conversation state. The avatar should reflect the same turn-taking state as the voice stack: listening, thinking, speaking, interrupting, or idle. Presets should influence presentation, not the synchronization logic itself.


How Protoface fits this pattern


Protoface is designed around this separation already. The REST API at api.protoface.com is the right surface for creating and managing avatars and realtime sessions from your backend, while the Python SDK is convenient when your app logic is already in Python. Use API keys server-side only; do not expose them in the browser.


A typical backend session creation call looks like this in curl form:


curl -X POST https://api.protoface.com/sessions \
}'
curl -X POST https://api.protoface.com/sessions \
}'
curl -X POST https://api.protoface.com/sessions \
}'


If you want a faster path for a voice agent, the LiveKit integration can drop a Protoface avatar into the agent so the agent gains a synchronized talking video face. That is often the cleanest place to implement presets because your agent session already exists, and the plugin can inherit the selected avatar configuration rather than inventing a second control plane. The relevant examples live in the plugin repo and quickstarts; the general pattern is to choose the preset in your app and pass the resulting config into the agent startup path.


For implementation details, validation rules, and exact request fields, use the documentation.


Watch the real gotchas: latency, asset loading, and drift


Avatar presets sound like a UI problem, but the failure modes are usually realtime problems.


1. Don’t let theme loading block session start. If your preset swaps backgrounds, clothing textures, or expression assets, preload or cache them. The user experience degrades quickly if the audio starts before the avatar is visually ready.


2. Keep the visual state machine small. A talking avatar only needs a few states to feel alive: idle, listening, speaking, and perhaps thinking. More granular animation states can be helpful, but too many states create synchronization bugs. Theme variants should not multiply the state machine.


3. Avoid prompt drift across presets. If “formal” and “casual” presets differ only visually, keep their behavioral instructions aligned. If they are supposed to differ in tone, define that explicitly. Otherwise support teams will spend time debugging what appears to be a visual issue but is actually a prompt issue.


4. Respect rate limits and session boundaries. If you offer customer-managed embeds, separate preset choice from session authorization. A preset can be public metadata; session creation should still be rate-limited and constrained by the allowed origin list and duration policies you enforce server-side.


5. Version changes intentionally. A new outfit asset, a different crop, or a stronger motion curve can change perceived personality. Treat those as versioned changes, not silent edits.


Use presets to make product decisions, not just visual ones


Once presets exist, they become a useful product abstraction. You can assign presets by plan tier, feature flag, customer segment, or conversation type. For example:


  • Sales demo: brighter theme, more expressive motion, short introduction script.

  • Support queue: neutral theme, stable framing, minimal motion, concise responses.

  • Interactive website assistant: brand-matched theme, lightweight background, tighter response policy.


That said, keep the taxonomy narrow. If users can select from 30 presets, the selection experience needs governance, analytics, and support. In many products, 3-8 well-tested presets are better than a sprawling gallery. Add variants only when they solve a concrete operational or branding need.


For developer-facing products, it also helps to expose presets in your dashboard so teams can preview, compare, and roll back changes without redeploying code. The browser playground is especially valuable here because it lets you check whether a visual change still feels right in a live conversation loop.


Conclusion


Implement avatar presets and theme variants as server-resolved templates, not as random client-side flags. Keep identity separate from presentation, version your presets, and make sure the session creation path is the only place where visual configuration turns into runtime configuration. That gives you predictable rendering, safer credential handling, and a much easier path to scaling from one avatar to many.


If you are wiring this into a realtime voice agent or a web embed, start with one preset and one fallback theme, then expand only after you have validated loading time, synchronization, and supportability. The docs at docs.protoface.com cover the API and integration surfaces in more detail, and the quickstarts in the GitHub examples are a good way to see the pieces working end to end.

Add a face to your AI.

No credit card needed.

Add a face to your AI.

No credit card needed.

Add a face to your AI.

No credit card needed.