Quickstart: Building a Realtime AI Avatar Kiosk with WebRTC, TTS, and STT

Build a realtime AI avatar kiosk with WebRTC, streaming STT/TTS, sync’d lip motion, and LiveKit/Protoface integration.
Introduction
If you want a kiosk that can greet people, answer questions, and feel present rather than robotic, you need three things working together: low-latency audio capture, streaming speech recognition, and a video face that stays synchronized with the generated speech. That means dealing with WebRTC-style realtime transport, audio turn-taking, and a rendering path that can keep lip motion aligned with the TTS stream.
This post shows the core architecture for a realtime AI avatar kiosk and the integration points you actually need to think about: how audio flows in, how text and speech flow out, where latency comes from, and how to wire an avatar into a voice agent without turning your kiosk into a pile of glue code. By the end, you should be able to build a browser-based kiosk or embedded web experience that feels responsive, not batchy.
The realtime kiosk loop: capture, transcribe, reason, speak, render
A kiosk is basically a tight loop with a hard UX constraint: the user should hear and see the system respond quickly enough that it feels like a conversation, not a form submission. The data path is usually:
User speaks into a microphone.
Audio is streamed to STT, not buffered into a full file.
The agent decides whether to respond, ask a follow-up, or hand off.
TTS generates speech incrementally.
The avatar renders a talking face that stays synchronized with that speech.
The important point is that these are not independent steps. Latency compounds across them, and the user notices the total, not each stage in isolation. If your STT waits for long endpointing, or your TTS only starts after the whole response is ready, or your avatar is fed audio late, the whole kiosk feels sluggish.
Transport choice: why WebRTC is the right baseline
For a kiosk, WebRTC is usually the right transport because it is designed for realtime media with jitter buffering, congestion control, and low end-to-end latency. In practical terms, it gives you a path for microphone input and speaker output that can keep up with conversational turn-taking. It also lets the browser handle device access and audio playback in a way that’s robust across desktop and kiosk deployments.
There are a few implementation details worth getting right:
Prefer streaming audio packets over request/response uploads. You want partial STT results as the user is still talking.
Use endpointing carefully. Too aggressive and you cut users off; too lax and the response starts too late.
Keep TTS streaming. The earlier the avatar can start mouth motion, the better the perceived responsiveness.
Handle barge-in. If the user interrupts, you should stop or de-emphasize the current speech cleanly.
For kiosk UX, it is often better to get a slightly imperfect first response fast than a perfect response late. That trade-off is not unique to avatars; the avatar just makes it more visible.
Voice pipeline architecture: STT, orchestration, and TTS
The cleanest architecture is to treat the avatar as a terminal rendering surface, not as the thing doing the thinking. The agent layer owns conversation state, policy, and tool calls. STT converts user audio into text. TTS converts the agent’s final text into an audio stream. The avatar consumes that audio and renders synchronized lip motion and facial animation.
This separation matters because it keeps your orchestration logic independent from the visual layer. If you later change models, swap STT providers, or adjust voice prompts, the avatar integration should not need to change. In a kiosk, that makes iteration much easier.
A few technical gotchas show up repeatedly:
Audio sample rate mismatches can create drift or resampling artifacts. Keep the pipeline consistent end-to-end.
Turn detection affects conversational feel more than model choice in many setups.
Backpressure matters if the TTS or video renderer cannot consume audio as fast as it is produced.
Interruption policy should be explicit: do you finish the current sentence, or stop on user speech?
For a kiosk, a simple policy is often best: start the response quickly, allow interruption, and keep answers short unless the user asks for detail. That improves both perceived quality and throughput under load.
Short Python example: creating and managing sessions
If you want to manage avatars or realtime sessions from your backend, the REST API and Python SDK are the natural entry points. The exact request/response fields are documented in the API docs, so treat the snippet below as shape rather than copy-paste.
If you prefer raw HTTP for debugging or automation, the API is straightforward to inspect with curl:
Use the dashboard at docs.protoface.com as the source of truth for the exact schema, rate limits, and session lifecycle.
Embedding the avatar into a voice agent
For teams already building on LiveKit, the cleanest path is the LiveKit Agents plugin: protoface-quickstart-openai-realtime is one of the quickest ways to see the pattern end to end, and the LiveKit integration keeps the avatar synchronized with the agent’s spoken output. The important architectural point is that the plugin doesn’t replace your agent; it adds a realtime video face to it.
In practice, your voice agent still handles conversation state and tool use. The plugin subscribes to the spoken output, turns it into a video avatar stream, and keeps the lip sync aligned with the TTS timeline. That avoids the common anti-pattern where the avatar is driven by a separate timing loop and ends up visibly lagging behind the audio.
A minimal integration usually looks like this conceptually:
If you are using Pipecat instead of LiveKit directly, the same design applies: your pipeline owns conversation flow, and the avatar service is a video sink for the TTS stream. The difference is mostly where the orchestration glue lives.
Operational details for kiosks: reliability, security, and rate limits
A kiosk is not just a demo in a browser tab. It has to survive network hiccups, locked-down machines, and people speaking over one another in a public space. A few practical considerations matter more than fancy prompts:
Session isolation: each kiosk interaction should have a bounded session lifecycle so stale audio does not leak across users.
Retry strategy: reconnecting media should be graceful, but failed upstream model calls should not leave the UI hanging.
Prompt hardening: kiosks often need tight instructions and limited tool access to avoid weird user-driven edge cases.
Access control: never expose long-lived API keys in the browser if you can avoid it.
This is also where customer-managed iframe embeds are useful. If your use case is “put an interactive avatar on a website with minimal backend,” the iframe approach keeps the API key off the client, allows parent-origin allowlisting, and gives you per-embed controls such as voice selection, custom instructions, and rate limits. That is a better fit than wiring a public browser client directly to your backend.
Where Protoface fits in this stack
Protoface sits at the avatar layer: it gives you the realtime talking face that subscribes to your voice agent’s output and keeps video aligned with speech. If you are building a kiosk on top of LiveKit, the plugin route is the most direct integration path. If you are orchestrating sessions from your own backend, the REST API and Python SDK give you programmatic control over avatars and sessions. And if you want a browser-native embed without exposing keys, the iframe flow is the safest option.
That division is useful because it lets you pick the integration surface that matches your architecture instead of forcing a single SDK shape across every app. The one thing you should keep constant is the media model: the agent speaks in realtime, and the avatar follows the speech stream, not the other way around.
Conclusion
A good realtime AI avatar kiosk is mostly an exercise in latency management and clean separation of responsibilities. Keep audio streaming, keep STT incremental, keep the response path short, and make the avatar a synchronized rendering target rather than a separate subsystem. That architecture scales from a single kiosk to a web embed or a full voice-agent product without changing the core conversation loop.
If you want to implement this quickly, start with the docs at docs.protoface.com, then pick the integration surface that matches your stack: LiveKit plugin for voice agents, Python SDK or REST API for backend control, or iframe embed for a zero-key browser deployment. Once the media path is working, spend your time on prompts, interruption behavior, and kiosk UX — that is where most of the quality difference shows up.
