Header Logo

Adding a Streaming Voice and Video Avatar to a SvelteKit E-Commerce App

Adding a Streaming Voice and Video Avatar to a SvelteKit E-Commerce App

Add a streaming voice/video avatar to a SvelteKit e-commerce app with secure backend sessions, WebRTC, and LiveKit integration.

Introduction


If you are building a SvelteKit e-commerce app, adding a voice-and-video avatar can make the experience feel immediately more interactive: product Q&A, guided shopping, post-purchase support, or a concierge for high-intent visitors. The hard part is not rendering a face; it is keeping speech, lip motion, and conversation state synchronized over a realtime transport without leaking credentials into the browser.


This post walks through the architecture you actually need: how a streaming avatar fits into a web app, how to keep the backend boundary clean, and where the integration points are when your agent is already voice-first. By the end, you should be able to choose between a browser embed, a backend-managed session, or a LiveKit-based voice agent with a synced video face.


What “streaming avatar” means in practice


A realtime avatar is usually a low-latency media session, not a prerecorded video. The backend or agent produces audio, the avatar service synthesizes or maps that audio onto a face stream, and the client subscribes to the resulting video track over WebRTC or a similar streaming channel. The important bit is synchronization: the mouth movement has to track the audio timeline closely enough that the illusion holds, while the application keeps end-to-end latency low enough for natural turn-taking.


For an e-commerce app, that means you need to think about three separate flows:


  • Conversation control: who is speaking, what the current turn is, and whether the agent is waiting for user input.

  • Media transport: audio and video tracks, often delivered via a realtime session instead of ordinary HTTP responses.

  • Application state: product context, cart state, inventory lookups, and whatever custom instructions shape the agent’s behavior.


Those concerns should stay separate. Don’t let your SvelteKit page become the orchestrator for media timing. Keep it as the UI layer, and push session creation and secret handling to the server side.


Architecture for a SvelteKit app


The cleanest shape is:


  1. The browser asks your SvelteKit backend to create or join a realtime session.

  2. Your backend calls the avatar service with private credentials.

  3. The client receives only the short-lived session or embed details it needs to connect.

  4. The avatar stream is rendered in a dedicated UI region, not mixed into the rest of the page layout.


In SvelteKit, the practical rule is simple: anything involving an API key, session creation policy, or customer-specific instructions belongs in a server route or form action. The browser should never see your long-lived credentials. If you must pass configuration to the client, keep it limited to the minimum session-specific data required to start playback.


Server-side session creation with the REST API


If you are managing sessions yourself, the REST API is the straightforward boundary. Your server can create an avatar, start a realtime session, and hand the client the session metadata it needs. Exact request fields depend on the endpoint, but the shape will be familiar if you have used any session-oriented API before.


Here is an illustrative server-side request using an API key. Keep this in a SvelteKit server route or another backend service, not in the browser.


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


The response will include the session data your client needs to establish the media connection. Treat this as ephemeral. In practice, you want your SvelteKit backend to issue a short-lived session per visitor or per support interaction, then expire it as soon as the experience ends.


In SvelteKit, that usually means a +server.ts endpoint that proxies only the setup step:


export async function POST({ request, fetch }) {

}
export async function POST({ request, fetch }) {

}
export async function POST({ request, fetch }) {

}


That proxy pattern gives you a place to validate inputs, attach tenant-specific metadata, and enforce whatever business rules you need before a session exists.


Rendering the avatar without fighting SvelteKit


On the client, the biggest mistake is trying to treat the avatar like a regular image or video asset. It is not static media. It is a live participant in a session. Your UI should therefore manage connection lifecycle explicitly:


  • connect on user intent, not immediately on page load

  • show a clear connecting state while the session is negotiated

  • handle disconnects and retries without duplicating tracks

  • clean up streams when the component unmounts or the route changes


In SvelteKit, that often means putting the client-side connection logic in a component that only mounts when the user clicks “Talk to an assistant” or opens the support drawer. If you are embedding the avatar in a product detail page, keep the rest of the page responsive while media initializes; do not block rendering on the avatar.


For layout, reserve space for the video element before playback starts. Reflow during connection looks sloppy and can make the media feel slower than it is. If the avatar is a floating concierge, use a fixed container with a stable aspect ratio so the session can attach cleanly once the stream is ready.


Voice-agent integration: when the avatar should follow an existing agent


If you already have a voice agent, the avatar should attach to that agent rather than become a separate conversational system. That is where the LiveKit plugin surface is useful. In a LiveKit-based agent, the plugin drops a synchronized talking face into the agent pipeline so the same conversational turn can produce audio and video without you writing media sync logic yourself.


The integration point is intentionally narrow: your agent keeps deciding what to say, and the plugin handles the avatar side of the output. That is a better model than “agent speaks to avatar through another API,” because it keeps turn state and timing in one place.


A minimal Python-side setup looks roughly like this:


from livekit.agents import JobContext

await avatar.connect(ctx)
from livekit.agents import JobContext

await avatar.connect(ctx)
from livekit.agents import JobContext

await avatar.connect(ctx)


The exact constructor fields and wiring vary by your agent setup, so treat that as a structural example rather than copy-paste code. The relevant point is that the plugin lives on the backend, alongside your LiveKit agent, not in the browser. If you are using Pipecat instead of LiveKit, the integration pattern is similar; the plugin layer sits inside the agent runtime, and the web client only receives the resulting media.


If you are looking for code examples or the current API shape, the most useful references are the OpenAI Realtime quickstart and the documentation. For the plugin itself, the relevant package is published on PyPI as pipecat-protoface, and the repo contains the integration examples.


Practical gotchas for an e-commerce implementation


A few implementation details matter more than they first appear:


1. Keep auth out of the browser. API keys stay on the server. If you expose them in client code, you will eventually create a support incident. Use your SvelteKit backend to create sessions and hand out only short-lived session data.


2. Make session boundaries explicit. A shopping concierge should not be an immortal websocket connection. Tie sessions to a user action, a timeout, or a route-level lifecycle. That keeps billing predictable and simplifies cleanup.


3. Separate identity from state. The avatar can be the same across sessions while the instructions, voice, and business context change per visitor. Do not bake catalog data into the avatar definition if it changes frequently; fetch live product context at session start.


4. Plan for degraded modes. Network jitter, denied autoplay, and transient media failures happen. Have a text fallback, even if it is just “continue in chat” or “retry audio.” For commerce, reliability matters more than novelty.


5. Match the UI to the latency budget. If the avatar is your front door to support, keep turn-taking crisp. If response times are higher because you are querying inventory or order history, surface that as an obvious “thinking” state instead of letting the avatar appear frozen.


Where Protoface fits


Protoface is useful here because it gives you the avatar layer without forcing you to invent the media pipeline yourself. In a SvelteKit app, that usually means you keep your frontend focused on layout and session initiation, while your backend talks to the REST API and your agent runtime can use the LiveKit plugin when the assistant already lives there.


For teams that want to avoid exposing any backend at all for the embed case, the customer-managed iframe flow is also worth considering. It keeps API keys out of the browser and lets you configure per-embed behavior, rate limits, and access control without stitching together your own media proxy. For the app architecture in this post, though, the key takeaway is simpler: choose the surface that matches where your conversation logic already lives, then keep the browser dumb.


Conclusion


Adding a streaming avatar to a SvelteKit e-commerce app is mostly a systems-integration problem. You need a secure backend boundary, a client that treats the avatar as live media, and an agent pipeline that keeps voice and video synchronized. Once those pieces are separated correctly, the UI work is pretty ordinary: connect, render, handle disconnects, and preserve state across turns.


If you are implementing this now, start by deciding whether your avatar should be managed from your backend, attached to an existing voice agent, or delivered as an embed. Then wire up one minimal end-to-end session and validate latency, cleanup, and fallback behavior before you add commerce-specific logic. The docs at docs.protoface.com are the right place to check the current API shapes and quickstarts.

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.