<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: FaceMode</title>
    <description>The latest articles on DEV Community by FaceMode (facemode).</description>
    <link>https://dev.to/facemode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F15206%2Fcc455e31-acc5-47f5-b9fc-538271fb836e.png</url>
      <title>DEV Community: FaceMode</title>
      <link>https://dev.to/facemode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/facemode"/>
    <language>en</language>
    <item>
      <title>Interactive Avatar APIs Compared: 10 Options (2026)</title>
      <dc:creator>prajwaldkadam</dc:creator>
      <pubDate>Sun, 18 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/facemode/interactive-avatar-apis-compared-10-options-2026-3901</link>
      <guid>https://dev.to/facemode/interactive-avatar-apis-compared-10-options-2026-3901</guid>
      <description>&lt;p&gt;Ten APIs now sell the same promise: send speech, get a live talking face. They differ on who owns the media room, which stacks they attach to, what "latency" each vendor actually measures, and what a streamed minute really costs. This page compares all ten on those four axes.&lt;/p&gt;

&lt;p&gt;Every vendor in this market has published a comparison, and every one of those comparisons ranks its publisher first: &lt;a href="https://www.heygen.com/blog/best-real-time-ai-avatar-platforms" rel="noopener noreferrer"&gt;HeyGen's seven-platform scoring&lt;/a&gt; puts HeyGen #1, &lt;a href="https://www.beyondpresence.ai/" rel="noopener noreferrer"&gt;Beyond Presence's benchmark&lt;/a&gt; puts Genesis #1, &lt;a href="https://www.d-id.com/v4-expressive-visual-avatars-tech-specs/" rel="noopener noreferrer"&gt;D-ID's SyncNet table&lt;/a&gt; puts D-ID #1 on lip-sync, and &lt;a href="https://anam.ai/tools/latency-benchmark" rel="noopener noreferrer"&gt;Anam's latency benchmark&lt;/a&gt; puts Anam fastest. This post takes a different approach. It is documentation-based, every cell links to the vendor's own current page, and it is written by FaceMode - one of the products in the table, disclosed rather than hidden.&lt;/p&gt;

&lt;p&gt;Sources were checked on October 18, 2026. Pricing and access rules change often in this category; confirm in your account before budgeting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three ways to put a face on a voice agent
&lt;/h2&gt;

&lt;p&gt;"Interactive avatar API" covers three different products, and most bad purchases come from comparing across the boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avatar layer on your own transport.&lt;/strong&gt; You create and own the LiveKit or Daily room; the vendor joins as a participant and publishes video. Your STT, LLM, TTS, and turn detection stay untouched. FaceMode and Synthesia's Interactive Avatar API both document this model, and &lt;a href="https://www.beyondpresence.ai/blog/what-is-a-real-time-ai-avatar-the-definitive-2026-buyers-guide" rel="noopener noreferrer"&gt;Beyond Presence's speech-to-video&lt;/a&gt; describes the same division.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avatar layer on the vendor's transport.&lt;/strong&gt; You still bring the conversation logic, but the session runs on vendor infrastructure - their WebRTC, their participant, their metering. Simli (built on Daily), LemonSlice (widget, hosted, or self-managed pipelines), and Runway Characters (WebRTC sessions) fit here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;End-to-end conversational platform.&lt;/strong&gt; The vendor supplies the whole call: speech recognition, LLM wiring, voice, turn-taking, and the face. Tavus's Conversational Video Interface, HeyGen LiveAvatar's FULL mode, and D-ID Agents are built this way. Several of them also expose a render-only path for your own stack - HeyGen's LITE mode, Tavus's LiveKit plugin, Anam's LiveKit/Pipecat integrations - so the boundary is a dial, not a wall.&lt;/p&gt;

&lt;p&gt;The first question to answer is which of the three you are actually shopping for. A full platform is the fastest demo and the deepest lock-in; a render-only layer is the least code on day one only if your agent already exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interactive avatar APIs: the comparison table
&lt;/h2&gt;

&lt;p&gt;Cells link to the vendor's own documentation or pricing where we verified it. "Not published" means we did not find a public figure in reviewed sources - it is not a zero or a criticism.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vendor&lt;/th&gt;
&lt;th&gt;Architecture&lt;/th&gt;
&lt;th&gt;Integration surface&lt;/th&gt;
&lt;th&gt;Published latency (boundary)&lt;/th&gt;
&lt;th&gt;Pricing model&lt;/th&gt;
&lt;th&gt;Free tier&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://anam.ai/pricing" rel="noopener noreferrer"&gt;Anam&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Avatar layer + hosted pipeline&lt;/td&gt;
&lt;td&gt;LiveKit + Pipecat plugins, JS SDK, embed widget&lt;/td&gt;
&lt;td&gt;180ms median server-side; sub-1s end-to-end claim (&lt;a href="https://anam.ai/interactive-avatars" rel="noopener noreferrer"&gt;interactive avatars&lt;/a&gt;); own public TTFF benchmark: 1.55s median&lt;/td&gt;
&lt;td&gt;Subscription $12-$999/mo with minute pools + $0.11-0.16/min overage; enterprise floor $0.04/min&lt;/td&gt;
&lt;td&gt;30 min/mo (watermark, 3-min sessions)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.beyondpresence.ai/" rel="noopener noreferrer"&gt;Beyond Presence&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Avatar layer + managed agents&lt;/td&gt;
&lt;td&gt;LiveKit + Pipecat, n8n webhooks&lt;/td&gt;
&lt;td&gt;Sub-100ms model inference; sub-250ms global (vendor claims on homepage)&lt;/td&gt;
&lt;td&gt;Headline: "rates fall to EUR 0.03/min at scale"; full schedule not published in reviewed pages&lt;/td&gt;
&lt;td&gt;Not published in reviewed pages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.d-id.com/" rel="noopener noreferrer"&gt;D-ID&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;End-to-end agents + video API&lt;/td&gt;
&lt;td&gt;LiveKit plugin, client SDK&lt;/td&gt;
&lt;td&gt;Sub-500ms conversational, sub-120ms model (&lt;a href="https://www.d-id.com/v4-expressive-visual-avatars-tech-specs/" rel="noopener noreferrer"&gt;V4 tech specs&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Subscription minutes shared across studio and API&lt;/td&gt;
&lt;td&gt;Trial with watermark&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FaceMode&lt;/td&gt;
&lt;td&gt;Avatar layer on your LiveKit or Daily room&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.facemode.io/integrations/overview" rel="noopener noreferrer"&gt;LiveKit Python + TypeScript plugins, Pipecat plugin, REST + WebSocket&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;~960ms audio-to-rendered-frame target (&lt;a href="https://facemode.io/llms-full.txt" rel="noopener noreferrer"&gt;product summary&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Credits: 1 credit = 1s of streamed video; paid top-ups open at GA&lt;/td&gt;
&lt;td&gt;60 minutes in beta, no card&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://help.heygen.com/en/articles/12758516-introducing-liveavatar" rel="noopener noreferrer"&gt;HeyGen LiveAvatar&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;FULL hosted pipeline + LITE bring-your-own&lt;/td&gt;
&lt;td&gt;LiveKit, Pipecat, Agora, VisionAgent; &lt;code&gt;openai_agent&lt;/code&gt; BYO-key mode&lt;/td&gt;
&lt;td&gt;Not published&lt;/td&gt;
&lt;td&gt;Credits: Essential $99/mo for 1,100 credits; 1 credit = 30s FULL / 60s LITE (about $0.16-0.18/min FULL); overage $0.10/credit&lt;/td&gt;
&lt;td&gt;10 credits/mo (1 session, 2-min sessions, watermark)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://lemonslice.com/pricing" rel="noopener noreferrer"&gt;LemonSlice&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Avatar layer: widget / hosted / self-managed&lt;/td&gt;
&lt;td&gt;LiveKit plugin, REST, WebSocket, Agora; Python/Node/Pipecat examples&lt;/td&gt;
&lt;td&gt;471ms p99 (homepage claim; response latency during a call, not startup)&lt;/td&gt;
&lt;td&gt;Subscription $8-$960/mo with minute pools + $0.22/min overage (Starter); CWM-1 Lite "as low as $0.048/min" on Ultra+; hosted pipeline +$0.09/min&lt;/td&gt;
&lt;td&gt;Free on-site avatar chat; API needs a paid plan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.dev.runwayml.com/characters/" rel="noopener noreferrer"&gt;Runway&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Characters API (GWM-1), hosted sessions&lt;/td&gt;
&lt;td&gt;WebRTC API, LiveKit plugin, React SDK, ElevenLabs Agents&lt;/td&gt;
&lt;td&gt;No comparable figure on current docs&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;gwm1_avatars&lt;/code&gt;: 2 credits upfront + 2 credits per 6s = $0.20/min at $0.01/credit (&lt;a href="https://docs.dev.runwayml.com/guides/pricing/" rel="noopener noreferrer"&gt;dev pricing&lt;/a&gt;); 5-min max sessions&lt;/td&gt;
&lt;td&gt;125 one-time developer credits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.simli.com/" rel="noopener noreferrer"&gt;Simli&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Avatar layer on Daily infra&lt;/td&gt;
&lt;td&gt;LiveKit + Pipecat plugins, WebRTC&lt;/td&gt;
&lt;td&gt;Sub-300ms speech-to-video (homepage claim)&lt;/td&gt;
&lt;td&gt;$10 credit on signup + 50 min/mo top-up; paid plans with volume discounts&lt;/td&gt;
&lt;td&gt;Yes, as described&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.synthesia.io/reference/interactive-avatars" rel="noopener noreferrer"&gt;Synthesia&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;BYO-stack avatar layer on LiveKit&lt;/td&gt;
&lt;td&gt;Python &lt;code&gt;livekit-plugins-synthesia&lt;/code&gt;, REST; Pipecat marked coming soon&lt;/td&gt;
&lt;td&gt;No comparable audio-to-frame figure&lt;/td&gt;
&lt;td&gt;Product page $0.12/min; operational docs $0.10/min - public conflict&lt;/td&gt;
&lt;td&gt;500 free minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.tavus.io/pricing" rel="noopener noreferrer"&gt;Tavus&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;End-to-end CVI platform&lt;/td&gt;
&lt;td&gt;LiveKit plugin (Python + Node)&lt;/td&gt;
&lt;td&gt;No comparable round-trip figure&lt;/td&gt;
&lt;td&gt;Free 25 min/mo; $59/$397 subscriptions + $0.37/$0.32 per-min overage; 30s minimum charge&lt;/td&gt;
&lt;td&gt;25 min/mo, 1 concurrent stream&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the table as a map, not a ranking. The columns are deliberately different units - transport, latency boundary, billing shape - because those are the dimensions where a wrong assumption costs you a rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the latency numbers
&lt;/h2&gt;

&lt;p&gt;Every vendor publishes a number, and almost none of them measure the same interval.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model inference&lt;/strong&gt; isolates the avatar model's compute time. Beyond Presence's sub-100ms and D-ID's sub-120ms are measured here - before network, before transport, before your room.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-side / speech-to-video&lt;/strong&gt; measures one stage of the pipeline. Anam's 180ms median and Simli's sub-300ms are this type: from received audio to generated response inside the vendor's system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversational or turn latency&lt;/strong&gt; covers the wider gap between the user finishing a sentence and the avatar's reply starting. D-ID's sub-500ms and Anam's sub-1s end-to-end claim live here, and both still exclude parts of your own stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audio-to-rendered-frame&lt;/strong&gt; is the boundary FaceMode publishes: approximately 960ms from audio input to a rendered frame. It counts the avatar layer's work, not your STT, LLM, TTS, or the user's perceived end-to-end wait.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time to first frame (TTFF)&lt;/strong&gt; is startup, not response speed. Anam runs the category's only public cross-vendor benchmark: 80 raters, 1,280 live conversations, measured July 31, 2026, with a published caveat that products change continuously. It measured Anam at 1.55s median TTFF, HeyGen at 4.7s, Tavus at 5.7s, and LemonSlice at 9.4s - and that is connection setup time, unrelated to LemonSlice's separate 471ms p99 mid-call claim. Both can be accurate; they describe different intervals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical consequence: an "under 100ms" badge and a "960ms" target can coexist on honest pages because they time different things. When you evaluate, instrument at least three points - session startup, response onset, and interruption recovery - under the same region, voice model, and utterance. Our &lt;a href="https://facemode.io/blog/synthesia-interactive-avatar-vs-facemode" rel="noopener noreferrer"&gt;Synthesia comparison&lt;/a&gt; walks through that measurement checklist in more detail.&lt;/p&gt;

&lt;p&gt;If you run on LiveKit, there is now a standardized hook: the &lt;a href="https://docs.livekit.io/agents/models/avatar/" rel="noopener noreferrer"&gt;virtual avatar docs&lt;/a&gt; describe &lt;code&gt;AvatarMetrics&lt;/code&gt; emitted by every avatar plugin through the session's &lt;code&gt;metrics_collected&lt;/code&gt; event, reporting &lt;strong&gt;join latency&lt;/strong&gt; (session start to the avatar participant publishing video) and &lt;strong&gt;playback latency&lt;/strong&gt; (first audio frame forwarded to playback starting on the avatar). That gives you a comparable number across LiveKit plugins without trusting any vendor's marketing page.&lt;/p&gt;

&lt;p&gt;Your frontend also has to tell the agent apart from the avatar worker. LiveKit's docs mark the worker as a participant of kind &lt;code&gt;agent&lt;/code&gt; carrying an &lt;code&gt;lk.publish_on_behalf&lt;/code&gt; attribute; in React, &lt;code&gt;useVoiceAssistant&lt;/code&gt; resolves the correct tracks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// The agent participant&lt;/span&gt;
  &lt;span class="nx"&gt;audioTrack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// the worker's audio track&lt;/span&gt;
  &lt;span class="nx"&gt;videoTrack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// the worker's video track&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useVoiceAssistant&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What a minute of avatar actually costs
&lt;/h2&gt;

&lt;p&gt;Headline prices in this category span an order of magnitude - roughly $0.03-0.05/min at volume commitments to $0.20/min pay-as-you-go and $0.37/min on overage - but the number only means something next to its billing shape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subscription plus minute pool.&lt;/strong&gt; Anam ($12-$999/mo + $0.11-0.16/min overage), LemonSlice ($8-$960/mo + $0.22/min overage on Starter), HeyGen ($99-$475/mo credit packs), and Tavus ($59-$397/mo + $0.32-0.37/min overage) all work this way. The effective per-minute rate depends on how much of the pool you consume; unused minutes mostly do not roll over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metered credits or per-minute.&lt;/strong&gt; Synthesia publishes $0.10-0.12/min (two public pages disagree, which we flagged in our &lt;a href="https://facemode.io/blog/synthesia-interactive-avatar-vs-facemode" rel="noopener noreferrer"&gt;Synthesia vs FaceMode post&lt;/a&gt;). Runway bills &lt;code&gt;gwm1_avatars&lt;/code&gt; at 2 credits per 6 seconds - $0.20/min at its $0.01 credit. FaceMode bills 1 credit per second of streamed video; during beta, 3,600 credits (60 minutes) are free and paid top-ups are not yet open, so there is no published paid rate to compare.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gotchas that change the bill:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency caps.&lt;/strong&gt; Anam ranges 1-10 sessions by tier, LemonSlice 3-100+, Tavus 1-10, Synthesia 1 on free vs 100 on paid; HeyGen advertises unlimited on paid plans. A 24/7 kiosk and a 50-user support line price very differently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session duration limits.&lt;/strong&gt; Runway caps sessions at 5 minutes per current docs, Anam at 3 minutes to 2 hours by tier, LemonSlice at 30 minutes to 24 hours by tier, HeyGen at 20-60 minutes, FaceMode's beta at 10 minutes. Long sessions are a paid-tier feature almost everywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimum charges and burst pricing.&lt;/strong&gt; Tavus bills a 30-second minimum per conversation; LemonSlice prices calls above the concurrency limit at a 2x burst multiplier; D-ID rounds video minutes up to 15-second intervals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free tiers are evaluation budgets.&lt;/strong&gt; Synthesia's 500 minutes, FaceMode's 60-minute beta, Anam's 30 min/mo, Tavus's 25 min/mo, HeyGen's ~10-20 minute monthly equivalent, and Simli's $10-plus-50-minutes let you test startup, interruption, and idle behavior. They are not production capacity, and most carry watermarks or session caps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The ten APIs, briefly
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Anam
&lt;/h3&gt;

&lt;p&gt;The most productized avatar-layer competitor: Cara-4 model with Director Notes for mid-call emotion control, 1152x768 landscape or 768x1152 portrait output, 70+ languages, SOC 2 Type II with HIPAA-aligned controls, and the only public cross-vendor latency benchmark in the category. Strengths to weigh honestly: transparent tiered pricing, both LiveKit and Pipecat plugins, and the strongest public measurement posture. Its enterprise floor of $0.04/min is the lowest published rate we found, gated behind enterprise terms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond Presence
&lt;/h3&gt;

&lt;p&gt;The enterprise-compliance play: Genesis 2.0 renders 1080p with claimed sub-100ms model inference and sub-250ms global latency, backed by SOC 2, GDPR, and EU data residency. October 2026 additions include bringing your own ElevenLabs agent, pushing agents into Zoom/Meet/Teams/Webex calls, and 24-hour speech-to-video sessions. Its homepage benchmark claims #1 across measured dimensions - treat it like every other vendor-run ranking in this post.&lt;/p&gt;

&lt;h3&gt;
  
  
  D-ID
&lt;/h3&gt;

&lt;p&gt;The established enterprise vendor: V4 Expressive avatars with sentiment control, up to 4K output, generative UI inside conversations, and a SyncNet lip-sync table ranking itself above Anam, HeyGen, and Tavus. Agents are a full hosted pipeline (LLM, knowledge, voice in one API object), and the October launch of Presentation Mode extends the stack into slide-led sessions. Heavier than a bare avatar layer, but the broadest packaged feature set.&lt;/p&gt;

&lt;h3&gt;
  
  
  FaceMode
&lt;/h3&gt;

&lt;p&gt;This site's product, so read this cell accordingly. FaceMode is the audio-in, face-out layer: stream your agent's audio over WebSocket and it publishes lip-synced video into a LiveKit or Daily room you own, as an ordinary participant you subscribe to with the SDK you already have. Plugins exist for &lt;a href="https://docs.facemode.io/integrations/overview" rel="noopener noreferrer"&gt;LiveKit Agents in Python and TypeScript&lt;/a&gt; and for Pipecat; anything else uses the REST + WebSocket path directly. Five art styles plus a one-portrait custom avatar, idle crossfades instead of freeze frames, credits pricing. Published target: ~960ms audio-to-frame. Honest limits: private beta, 10-minute sessions, one concurrent session per account, and - unlike the nine competitors above - FaceMode's plugin is not yet listed in &lt;a href="https://docs.livekit.io/agents/models/avatar/" rel="noopener noreferrer"&gt;LiveKit's official avatar directory&lt;/a&gt;, which currently covers 16 providers.&lt;/p&gt;

&lt;h3&gt;
  
  
  HeyGen LiveAvatar
&lt;/h3&gt;

&lt;p&gt;The biggest brand in the space, now with a genuine developer path. FULL mode is a hosted conversational pipeline; LITE mode renders the avatar for your own stack at half the credits. LiveKit, Pipecat, Agora, and VisionAgent integrations are documented, an &lt;code&gt;openai_agent&lt;/code&gt; mode runs your own OpenAI key, and paid plans carry unlimited concurrency - the strongest concurrency posture in the table. The credit math (1 credit = 30s FULL / 60s LITE) puts effective FULL pricing around $0.16-0.18/min on self-serve plans. Their October comparison post ranks LiveAvatar #1 of 7; apply the same skepticism as to any self-ranked table.&lt;/p&gt;

&lt;h3&gt;
  
  
  LemonSlice
&lt;/h3&gt;

&lt;p&gt;The most aggressive shipper this month. In the first half of October alone it launched the Cartoon Model (hyper-expressive cartoon/anime/3D mascot avatars from one image), CWM-1 Lite at "as low as $0.048/min", smoother rendering, and GDPR compliance - on top of CWM-1's action and emotion control, non-human characters, and mid-call image updates. Integration surface is the widest on the list: LiveKit plugin, REST, WebSocket aimed at Vapi/Retell/Bland-style agents, Agora, and a two-line widget. Caveats: the interesting models and the $0.048/min floor sit behind the $800/mo Ultra tier or enterprise, API access requires a paid plan, and its 471ms p99 is a mid-call response figure that says nothing about session startup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Runway
&lt;/h3&gt;

&lt;p&gt;The world-model entrant: Characters builds persistent avatars from a single image on GWM-1, accepts webcam and screen vision input, and now also lives inside OpenAI's Dots. Developer experience is genuinely good - React SDK, LiveKit plugin, embedded widget, MCP support. Constraints are real: sessions cap at 5 minutes per current docs, and at $0.20/min it is the most expensive pay-as-you-go cell in the table. Best fit for short, high-production-value interactions rather than long support calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simli
&lt;/h3&gt;

&lt;p&gt;"The face layer for AI agents" - the closest positioning match to FaceMode - built on Daily's WebRTC infra with LiveKit and Pipecat plugins. Its wedge is price: the Trinity-1 launch claimed under $0.01/min through Gaussian-splatting efficiency, and the site currently offers a $10 signup credit plus a 50-minute monthly top-up. The sub-300ms speech-to-video figure is a pipeline-stage claim like Anam's 180ms, not end-to-end latency. Watch the pricing page rather than launch-era numbers, which we could not reconfirm as a current rate card this cycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Synthesia
&lt;/h3&gt;

&lt;p&gt;The enterprise video giant's real-time entry: a bring-your-own-stack Interactive Avatar API that joins your LiveKit room, with optional hosted TTS. Python &lt;code&gt;livekit-plugins-synthesia&lt;/code&gt; and REST endpoints are documented, Pipecat is marked coming soon, and a Claude Code/Cursor skill now wires the integration for you. 500 free minutes is the most generous evaluation budget in the table. Public pricing pages conflict ($0.12 vs $0.10/min), transport is LiveKit-only, and plugin support is Python-only today - our full &lt;a href="https://facemode.io/blog/synthesia-interactive-avatar-vs-facemode" rel="noopener noreferrer"&gt;Synthesia vs FaceMode comparison&lt;/a&gt; covers the detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tavus
&lt;/h3&gt;

&lt;p&gt;The most complete hosted pipeline: CVI bundles STT, LLM, TTS, turn-taking (Sparrow), vision (Raven-1), and Phoenix rendering into one API object, with a LiveKit plugin for teams that only want the face. Replicas train from a headshot or two minutes of video, the object model was recently renamed to PAL/Face/Voice, and a Griffin model in preview claims Turing-test-level realism. The trade-off is price and shape: $0.32-0.37/min overage and a 30-second minimum make it the heaviest metering here, and its strength is an opinionated full stack you adopt wholesale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which interactive avatar API fits your situation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You already run LiveKit Agents.&lt;/strong&gt; All nine competitors have official plugins in the &lt;a href="https://docs.livekit.io/agents/models/avatar/" rel="noopener noreferrer"&gt;LiveKit avatar directory&lt;/a&gt;, and FaceMode ships a public Python and TypeScript plugin outside it. Shortlist on transport ownership (your room vs vendor session) and avatar style, then instrument with &lt;code&gt;AvatarMetrics&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You run Pipecat.&lt;/strong&gt; FaceMode (&lt;code&gt;pipecat-facemode&lt;/code&gt;), Anam, Simli, LemonSlice, HeyGen LiveAvatar, and Beyond Presence all document Pipecat paths; Synthesia marks it coming soon. Our &lt;a href="https://facemode.io/blog/livekit-voice-agent-avatar" rel="noopener noreferrer"&gt;LiveKit avatar tutorial&lt;/a&gt; shows the attachment pattern that carries over.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You are on Vapi, Retell, or a custom stack.&lt;/strong&gt; You need a raw audio-in or WebSocket path: FaceMode's direct API, LemonSlice's WebSocket GA (built for exactly these agents), Simli's WebRTC, Anam's SDK, or Runway's session API. Skip anything that only ships as a plugin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want zero orchestration work.&lt;/strong&gt; Tavus CVI, HeyGen FULL, or D-ID Agents supply the whole call including turn-taking. You trade away stack control and pay for the full pipeline whether you need it or not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance gates the deal.&lt;/strong&gt; Beyond Presence (SOC 2, GDPR, EU residency), Anam (SOC 2, HIPAA-aligned, enterprise ZDR and data residency), D-ID, Synthesia, and now LemonSlice (GDPR, with ZDR and residency on Enterprise) all publish postures worth a procurement review. FaceMode is in private beta - evaluate it after compliance needs are met, not before.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your character is not a photoreal human.&lt;/strong&gt; LemonSlice's Cartoon model and CWM-1 animate mascots, anime, and non-humans; Runway accepts any visual style; Tavus accepts cartoon/anime/Pixar faces; FaceMode's library covers realism through flat vector. Compare listening and idle behavior, not just the talking demo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform agents are not this comparison.&lt;/strong&gt; Meta Muse, OpenAI Dots, and Gemini Live Avatar put a face inside a consumer assistant, not an API you attach to your agent - the &lt;a href="https://facemode.io/blog/muse-dots-gemini-avatar-vs-facemode" rel="noopener noreferrer"&gt;Muse/Dots/Gemini post&lt;/a&gt; separates those categories.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Which interactive avatar API is the cheapest?
&lt;/h3&gt;

&lt;p&gt;At published floors, Beyond Presence advertises EUR 0.03/min at scale, Anam $0.04/min on enterprise, and LemonSlice $0.048/min on CWM-1 Lite - all volume-gated. Pay-as-you-go spans $0.10-0.20/min, and subscription-plus-pool plans vary with utilization. The honest answer: model your minutes, concurrency, and session lengths against the table above rather than trusting any headline figure, including ours.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which interactive avatar API is the fastest?
&lt;/h3&gt;

&lt;p&gt;There is no fair public answer. The only cross-vendor measurement published - &lt;a href="https://anam.ai/tools/latency-benchmark" rel="noopener noreferrer"&gt;Anam's TTFF benchmark&lt;/a&gt; - covers four vendors, measures startup time, and is run by one of the products it ranks first. Everything else is single-vendor claims with different boundaries, which is why this post lists each figure's measurement type instead of picking a winner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is there a free interactive avatar API?
&lt;/h3&gt;

&lt;p&gt;For evaluation, yes: Synthesia offers 500 free minutes, FaceMode's beta includes 60 minutes, Anam 30 min/mo, Tavus 25 min/mo, Simli $10 plus a 50-minute monthly top-up, HeyGen about 10-20 minutes monthly, Runway 125 developer credits, and LemonSlice offers free on-site chats. None of these is a production tier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does HeyGen have an interactive avatar API?
&lt;/h3&gt;

&lt;p&gt;Yes - LiveAvatar. LITE mode renders the face for your own stack over LiveKit, Pipecat, or Agora; FULL mode hosts the whole conversational pipeline. It bills in its own credit system, separate from HeyGen's video-generation subscriptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is FaceMode the right choice here?
&lt;/h3&gt;

&lt;p&gt;If your requirements are a LiveKit or Daily room you own, audio from any stack, Python or TypeScript LiveKit plugins or Pipecat, and per-second credit pricing, FaceMode was built for exactly that shape. If you need GA availability, enterprise compliance attestations, or concurrency beyond the beta's one-session limit today, several rows above fit better right now. The point of this post is that you can check that claim against primary sources, not our word for it.&lt;/p&gt;

&lt;p&gt;If you want to test FaceMode, &lt;a href="https://console.facemode.io/waitlist" rel="noopener noreferrer"&gt;request beta access&lt;/a&gt; or read the &lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt; and &lt;a href="https://docs.facemode.io/integrations/overview" rel="noopener noreferrer"&gt;integration guides&lt;/a&gt;. If this comparison helped, the &lt;a href="https://facemode.io/blog/livekit-voice-agent-avatar" rel="noopener noreferrer"&gt;LiveKit avatar plugin walkthrough&lt;/a&gt; is the fastest way to see one of these rows running.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>livekit</category>
      <category>saas</category>
    </item>
    <item>
      <title>LiveKit Avatar Plugin: Add a Face to Your Voice Agent</title>
      <dc:creator>prajwaldkadam</dc:creator>
      <pubDate>Fri, 02 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/facemode/livekit-avatar-plugin-add-a-face-to-your-voice-agent-4pni</link>
      <guid>https://dev.to/facemode/livekit-avatar-plugin-add-a-face-to-your-voice-agent-4pni</guid>
      <description>&lt;p&gt;Use the FaceMode &lt;strong&gt;LiveKit avatar plugin&lt;/strong&gt; to turn your existing voice agent's speech into lip-synced video in the room you already run. This guide covers the Python and TypeScript attachment paths, then shows how a browser subscribes to the avatar's media.&lt;/p&gt;

&lt;p&gt;Your STT, LLM, TTS, and conversation logic stay in your agent. The avatar layer receives its audio and publishes synchronized audio/video as another room participant, following the model described in &lt;a href="https://docs.livekit.io/agents/models/avatar/" rel="noopener noreferrer"&gt;LiveKit's virtual avatar overview&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The examples below are integration excerpts validated against FaceMode's plugin READMEs and &lt;a href="https://docs.facemode.io/integrations/overview" rel="noopener noreferrer"&gt;integration docs&lt;/a&gt;. They assume you already have a working LiveKit agent; they are not standalone worker applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;p&gt;Four things, all server-side:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A FaceMode account.&lt;/strong&gt; Sign-up is waitlist-gated during the private beta at &lt;a href="https://console.facemode.io/signup" rel="noopener noreferrer"&gt;console.facemode.io/signup&lt;/a&gt;. Approved testers get 3,600 free credits - 60 minutes of avatar video, no card required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A FaceMode API key&lt;/strong&gt; (&lt;code&gt;fm_...&lt;/code&gt;) from the dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An avatar ID&lt;/strong&gt; for the face that should speak. Pick from the library across five art styles, or upload one front-facing portrait and make it your own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A LiveKit room you own, plus a publisher token.&lt;/strong&gt; The token must grant the FaceMode worker &lt;code&gt;room_join&lt;/code&gt;, &lt;code&gt;can_publish&lt;/code&gt;, and &lt;code&gt;can_subscribe&lt;/code&gt; on your room.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The access and beta limits come from the &lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;FaceMode quickstart&lt;/a&gt;. Use a separate participant identity for the avatar worker and for each viewer. Reusing a token identity for multiple connections is not a way to give every participant the same permissions.&lt;/p&gt;

&lt;p&gt;Set the credentials as environment variables on your backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FACEMODE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fm_your_key_here"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FACEMODE_AVATAR_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your_avatar_id"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LIVEKIT_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"wss://your-project.livekit.cloud"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LIVEKIT_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;publisher-token&amp;gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Keep every token in this guide on the server. The browser only ever receives the room URL and its own subscribe-only viewer token - never the API key, never the publisher token.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The 30-second mental model
&lt;/h2&gt;

&lt;p&gt;FaceMode is not another agent framework. It is one job done well: turn the audio your agent already produces into a lip-synced avatar, published into the room you already run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your agent (STT -&amp;gt; LLM -&amp;gt; TTS)
        |
        v (the TTS audio you already have)
    FaceMode -- lip-synced video frames, ~960ms audio-to-frame target
        |
        v
  Your LiveKit room -- the avatar joins as an ordinary participant
        |
        v
  Your frontend -- subscribes with the livekit-client SDK you already ship

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing sits between your app and your room. FaceMode joins as a participant, publishes its video track, and leaves when the session ends. If you removed FaceMode tomorrow, your agent would keep working exactly as before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1A: Python LiveKit avatar integration
&lt;/h2&gt;

&lt;p&gt;If your agent runs on LiveKit Agents for Python, install the plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;livekit-plugins-facemode

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://docs.facemode.io/integrations/livekit-agents-python" rel="noopener noreferrer"&gt;FaceMode Python integration guide&lt;/a&gt; requires Python 3.13+ and LiveKit Agents 1.7+. In your existing asynchronous worker entrypoint, &lt;code&gt;ctx&lt;/code&gt; is its job context and &lt;code&gt;agent_session&lt;/code&gt; is the &lt;code&gt;AgentSession&lt;/code&gt; you have already configured with speech and model providers. The attachment excerpt is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;livekit.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AgentSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room_io&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;livekit_plugins_facemode&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AvatarSession&lt;/span&gt;

&lt;span class="n"&gt;avatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AvatarSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACEMODE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;avatar_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACEMODE_AVATAR_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agent_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;livekit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LIVEKIT_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LIVEKIT_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent_session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;room_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;room_io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RoomOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three details worth noticing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;audio_output=False&lt;/code&gt;.&lt;/strong&gt; The avatar publishes synchronized audio and video. Disabling the agent's separate audio path avoids duplicate playback; it is not a guarantee against every possible synchronization issue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;room&lt;/code&gt; object.&lt;/strong&gt; You hand the plugin the same LiveKit URL and publisher token you already manage. FaceMode never creates or replaces your room.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;wait_for_join()&lt;/code&gt;.&lt;/strong&gt; A one-line confirmation that the avatar participant is actually in the room before you consider the session live.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Success means &lt;code&gt;wait_for_join()&lt;/code&gt; resolves and the avatar's video track is available in the room, not merely that the REST request succeeded. The &lt;a href="https://docs.facemode.io/integrations/livekit-agents-python" rel="noopener noreferrer"&gt;Python integration docs&lt;/a&gt; distinguish session creation, WebSocket negotiation, and media readiness.&lt;/p&gt;

&lt;p&gt;Under the hood, &lt;code&gt;avatar.start()&lt;/code&gt; creates a FaceMode session over REST, opens the worker WebSocket, negotiates the audio format, and forwards TTS frames as PCM. After a started session loses its transport, the plugin attempts up to two reconnects with fresh one-time tokens. Exhaustion surfaces an error; reconnect is not a guarantee that every outage is invisible.&lt;/p&gt;

&lt;p&gt;Optionally, pin the upstream input provider so the backend knows which TTS is driving the audio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;avatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AvatarSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACEMODE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;avatar_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACEMODE_AVATAR_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;input_provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;elevenlabs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# deepgram, gemini, gnani, elevenlabs, openai, cartesia, sarvam, custom
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any TTS works. If it can stream audio, it can drive a face.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1B: TypeScript LiveKit avatar integration
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;@facemode/agents-plugin-facemode&lt;/code&gt; with Node 20+ and &lt;code&gt;@livekit/agents&lt;/code&gt; 1.x, as specified in the &lt;a href="https://docs.facemode.io/integrations/livekit-agents-js" rel="noopener noreferrer"&gt;TypeScript integration guide&lt;/a&gt;. This is an alternative to the Python route, not a second worker you need to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @facemode/agents-plugin-facemode

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this inside your worker entrypoint with an already-configured &lt;code&gt;agentSession&lt;/code&gt;. The session-start portion is adapted from the TypeScript docs so the excerpt includes the audio-output setting as well as the avatar attachment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;voice&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@livekit/agents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AvatarSession&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@facemode/agents-plugin-facemode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;avatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AvatarSession&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FACEMODE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;avatarId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FACEMODE_AVATAR_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deepgram&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agentSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;room&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;livekit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LIVEKIT_URL&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LIVEKIT_TOKEN&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;agentSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;voice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a helpful voice assistant.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;room&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;outputOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;audioEnabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForJoin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plugin replaces the agent session's audio tail: TTS frames flow to FaceMode as binary &lt;code&gt;pcm_s16le&lt;/code&gt;, interruptions send a &lt;code&gt;cancel_utterance&lt;/code&gt; control, and reconnects are handled for you. Sample rates from 8kHz to 48kHz are accepted, with 8, 11.025, 12, 16, 22.05, 24, 32, 44.1, and 48kHz as the preferred set covering common TTS outputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: render the LiveKit avatar in the browser
&lt;/h2&gt;

&lt;p&gt;This is the part developers expect to be hard and is actually the easiest. The avatar is just a participant in your room, so your existing LiveKit client code subscribes to it like any other video track.&lt;/p&gt;

&lt;p&gt;Mint a &lt;strong&gt;separate, subscribe-only viewer token&lt;/strong&gt; for a read-only viewer and pass it down with the room URL. In the browser, register the subscription listener before connecting and insert the elements returned by &lt;code&gt;track.attach()&lt;/code&gt; into the DOM. This excerpt is adapted from &lt;a href="https://docs.livekit.io/home/client/tracks/subscribe" rel="noopener noreferrer"&gt;LiveKit's track subscription guide&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RoomEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;livekit-client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;room&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Room&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;media&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;media&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;room&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RoomEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TrackSubscribed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;audio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;media&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// render the avatar&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;room&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roomUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewerToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// your own viewer token&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success is visible video plus audible speech, not just a connected room. In a multi-participant app, filter tracks by the avatar participant identity instead of rendering every subscribed participant. Your real app should also detach media on unsubscribe and disconnect the room when its viewer component unmounts.&lt;/p&gt;

&lt;p&gt;This is a read-only viewer example. A user who talks to the agent needs microphone publication in your existing voice UI and appropriate grants on their own token. Do not give them the worker's publisher token. Browser autoplay policies can require a user gesture to enable audio; use LiveKit's playback controls in that interaction rather than interpreting silent playback as an avatar failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interruptions, silence, and the in-between moments
&lt;/h2&gt;

&lt;p&gt;Real conversations are messy, and the avatar behaves accordingly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Barge-in.&lt;/strong&gt; The &lt;a href="https://docs.facemode.io/integrations/livekit-agents-python" rel="noopener noreferrer"&gt;plugin docs&lt;/a&gt; say an agent interruption sends &lt;code&gt;cancel_utterance&lt;/code&gt;. That control is not evidence of zero-delay playback cancellation; test the visible and audible result in your actual client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Silence between utterances.&lt;/strong&gt; The &lt;a href="https://facemode.io/llms-full.txt" rel="noopener noreferrer"&gt;FaceMode product summary&lt;/a&gt; describes crossfading into an idle loop between utterances. Check that this remains visible when your voice agent is waiting on a long-running tool call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Startup budgets.&lt;/strong&gt; The Python docs allow up to 240 seconds for readiness polling and WebSocket opening, but use a separate 15-second protocol acknowledgement budget and a 30-second default media-join timeout. Those are timeout settings, not a measured cold-start duration or a guaranteed successful startup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A short pitfalls checklist
&lt;/h2&gt;

&lt;p&gt;Before your first session, check the five things that bite most often:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Token grants.&lt;/strong&gt; The publisher token must allow join, publish, and subscribe. If it pins a fixed participant identity, make the room policy allow that identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets stay server-side.&lt;/strong&gt; API key and publisher token never reach the browser. Only the room URL and a subscribe-only viewer token do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;audio_output=False&lt;/code&gt;&lt;/strong&gt; on the agent session, or you will hear double.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declared sample rate must match the actual PCM.&lt;/strong&gt; The plugin locks the format at negotiation and rejects a mismatch mid-stream.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beta limits.&lt;/strong&gt; Sessions auto-end after 10 minutes, one concurrent session per account, and a session needs at least 60 credits of remaining balance to start.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: validate media, failure recovery, and shutdown
&lt;/h2&gt;

&lt;p&gt;A LiveKit avatar integration crosses several boundaries: your voice agent, the FaceMode API, its ingestion WebSocket, the avatar participant, and browser playback. Diagnose the boundary that failed rather than treating all five as one connection.&lt;/p&gt;

&lt;p&gt;Start with a short utterance whose beginning and end are easy to recognize. Confirm that only one audio path is audible and that the visible avatar is the participant you intended to subscribe to. Then interrupt a longer sentence. Observe whether the agent stops generating speech, whether cancellation reaches the avatar, and whether already-buffered client media continues playing. This separates agent behavior from transport and playback behavior.&lt;/p&gt;

&lt;p&gt;Next, test a pause with no speech. Idle animation should not be mistaken for proof that the agent is ready to answer, and a connected room should not be mistaken for proof that the ingestion socket is healthy. Keep the voice agent's own state indicator alongside the video so users can distinguish listening from waiting.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.facemode.io/integrations/livekit-agents-python" rel="noopener noreferrer"&gt;Python lifecycle guide&lt;/a&gt; documents &lt;code&gt;await avatar.stop()&lt;/code&gt; or &lt;code&gt;aclose()&lt;/code&gt; for shutdown. The TypeScript guide documents the equivalent methods. Wire these into your existing call cleanup path, including failures; an abandoned browser tab should not be your only cleanup mechanism. The canonical &lt;code&gt;ended&lt;/code&gt; acknowledgement confirms the protocol message, not that every backend cleanup action has finished.&lt;/p&gt;

&lt;p&gt;If you test reconnect behavior, do it with disposable development sessions. The plugin only attempts recovery after negotiation has completed; intentional shutdown and fatal protocol errors do not trigger the same recovery path. Do not write code that retries a consumed one-time WebSocket token or replays previously sent audio.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the latency target does and does not mean
&lt;/h2&gt;

&lt;p&gt;FaceMode publishes an approximately 960ms audio-to-rendered-frame target. Your total voice-agent response time also includes turn detection, transcription, LLM generation, TTS, transport, and client playback. A sub-second target for the avatar layer does not imply the whole conversation responds within one second.&lt;/p&gt;

&lt;p&gt;When comparing providers, measure the same utterance from the same boundary. Keep session startup separate from steady-state response latency. Also keep interruption recovery separate: a pipeline can begin speaking quickly and still feel poor if it cannot stop naturally when the user cuts in.&lt;/p&gt;

&lt;p&gt;Record observations from a real room rather than using a console-only voice test. Console mode can validate conversation logic without exercising the video subscription and browser playback paths. These are suggested acceptance checks, not benchmarks we ran for this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing a plugin or the direct talking avatar API
&lt;/h2&gt;

&lt;p&gt;Use the plugin when LiveKit Agents already owns your speech pipeline. It captures the framework's audio frames and lifecycle events, so you do not have to reproduce its WebSocket protocol handling. Use the direct talking avatar API when your application produces audio outside that framework and you can manage session creation, PCM negotiation, and shutdown yourself.&lt;/p&gt;

&lt;p&gt;That choice does not automatically prove compatibility with every hosted voice-agent platform. A provider that cannot expose its generated audio, or whose calls are phone-only, may need an additional transport or product integration. FaceMode's documented room output is LiveKit or Daily, not a claim of native support for every conferencing system.&lt;/p&gt;

&lt;p&gt;For a comparison with another bring-your-own-stack provider, see &lt;a href="https://facemode.io/blog/synthesia-interactive-avatar-vs-facemode" rel="noopener noreferrer"&gt;Synthesia Interactive Avatar vs FaceMode&lt;/a&gt;. Both preserve existing conversation models; their documented runtimes, transport paths, and access limits are the useful differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  LiveKit avatar plugin: short version
&lt;/h2&gt;

&lt;p&gt;Inside your existing asynchronous Python worker, connect the room, attach the configured avatar, start the configured agent session with direct audio disabled, and wait for video. This recap uses the &lt;code&gt;room&lt;/code&gt; binding and objects configured in Step 1A; it is not a standalone script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent_session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;room_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;room_io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RoomOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;room&lt;/code&gt; is the server-side dictionary containing &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;, and the worker &lt;code&gt;token&lt;/code&gt; from the earlier example. Stop the avatar through your call's cleanup path once the conversation ends.&lt;/p&gt;

&lt;h2&gt;
  
  
  From zero to a talking face
&lt;/h2&gt;

&lt;p&gt;The whole flow is: install the plugin, hand it your room, keep your agent code. If you want the raw HTTP and WebSocket protocol instead - any language that can hold a socket open works - the &lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;direct API quickstart&lt;/a&gt; walks it end to end.&lt;/p&gt;

&lt;p&gt;For the broader category distinction, read &lt;a href="https://facemode.io/blog/muse-dots-gemini-avatar-vs-facemode" rel="noopener noreferrer"&gt;Muse Avatar, OpenAI Dots, Gemini Live Avatar vs FaceMode&lt;/a&gt;. It separates platform agent experiences from avatar components you integrate into a product.&lt;/p&gt;

&lt;p&gt;Ready to see your agent talk? &lt;a href="https://console.facemode.io/waitlist" rel="noopener noreferrer"&gt;Join the beta&lt;/a&gt; - 60 free minutes, no card - or skim the &lt;a href="https://docs.facemode.io" rel="noopener noreferrer"&gt;docs&lt;/a&gt; first.&lt;/p&gt;

</description>
      <category>livekit</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>webrtc</category>
    </item>
    <item>
      <title>Synthesia Interactive Avatar vs FaceMode</title>
      <dc:creator>prajwaldkadam</dc:creator>
      <pubDate>Fri, 02 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/facemode/synthesia-interactive-avatar-vs-facemode-33g2</link>
      <guid>https://dev.to/facemode/synthesia-interactive-avatar-vs-facemode-33g2</guid>
      <description>&lt;p&gt;Synthesia Interactive Avatar and FaceMode both turn voice-agent speech into live, lip-synced video. If your agent already works, the useful comparison is which avatar API fits its transport, runtime, avatar requirements, and deployment constraints.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.synthesia.io/reference/interactive-avatars" rel="noopener noreferrer"&gt;Synthesia's Interactive Avatar API&lt;/a&gt; supports a bring-your-own conversation stack connected to LiveKit. &lt;a href="https://facemode.io" rel="noopener noreferrer"&gt;FaceMode&lt;/a&gt; accepts your existing audio and publishes avatar media into a LiveKit or Daily room you own. Neither requires replacing your LLM simply to add a face.&lt;/p&gt;

&lt;p&gt;This is a documentation-based comparison by FaceMode, not an independent performance benchmark. Sources were checked on October 2, 2026. Prices, access rules, and plugin support can change; conflicting vendor documentation is called out rather than resolved by guesswork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synthesia Interactive Avatar vs FaceMode: the short version
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criterion&lt;/th&gt;
&lt;th&gt;Synthesia Interactive Avatar&lt;/th&gt;
&lt;th&gt;FaceMode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Conversation stack&lt;/td&gt;
&lt;td&gt;Bring your own STT, LLM, and TTS; optional hosted TTS (&lt;a href="https://docs.synthesia.io/reference/interactive-avatars" rel="noopener noreferrer"&gt;docs&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Keep your voice stack; supply its audio (&lt;a href="https://facemode.io/llms-full.txt" rel="noopener noreferrer"&gt;product summary&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Media transport&lt;/td&gt;
&lt;td&gt;LiveKit-only in current operational docs (&lt;a href="https://docs.synthesia.io/reference/ia-operational-trust" rel="noopener noreferrer"&gt;limitations&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Customer-owned LiveKit or Daily room (&lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integration paths&lt;/td&gt;
&lt;td&gt;Documented Python LiveKit plugin and direct REST endpoints; Pipecat marked coming soon (&lt;a href="https://www.synthesia.io/features/avatars/interactive-avatars" rel="noopener noreferrer"&gt;product page&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;LiveKit Python/TypeScript plugins, Python Pipecat plugin, direct REST + WebSocket (&lt;a href="https://docs.facemode.io/integrations/overview" rel="noopener noreferrer"&gt;integrations&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avatars&lt;/td&gt;
&lt;td&gt;Synthetic and personal avatars; operational docs exclude stock actor avatars (&lt;a href="https://docs.synthesia.io/reference/ia-operational-trust" rel="noopener noreferrer"&gt;limitations&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Front-facing portrait uploads and five library styles (&lt;a href="https://facemode.io/llms-full.txt" rel="noopener noreferrer"&gt;product summary&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comparable latency figure&lt;/td&gt;
&lt;td&gt;No numeric audio-to-rendered-frame figure in the sources reviewed&lt;/td&gt;
&lt;td&gt;Approximately 960ms audio-to-rendered-frame target, not a measured result from this comparison&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing and trial&lt;/td&gt;
&lt;td&gt;Product page: $0.12/min and 500 free minutes; operational docs: $0.10/min (&lt;a href="https://www.synthesia.io/features/avatars/interactive-avatars" rel="noopener noreferrer"&gt;pricing sources&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Private beta: 3,600 credits / 60 minutes; paid top-ups not open yet (&lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;beta terms&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The shared capabilities matter as much as the differences. Bring-your-own models and room ownership are not FaceMode-exclusive features. A useful evaluation starts with those similarities, then tests the details that actually change your implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: both can keep your voice stack
&lt;/h2&gt;

&lt;p&gt;Synthesia's &lt;a href="https://www.synthesia.io/post/interactive-avatar-api-real-time-avatars" rel="noopener noreferrer"&gt;announcement&lt;/a&gt; describes an open architecture: customers supply their STT, LLM, and optionally TTS, while Synthesia provides real-time avatar rendering. Its &lt;a href="https://docs.synthesia.io/reference/ia-livekit-plugin-reference" rel="noopener noreferrer"&gt;plugin reference&lt;/a&gt; says the plugin replaces &lt;code&gt;session.output.audio&lt;/code&gt;, so it can lip-sync the speech your agent already produces.&lt;/p&gt;

&lt;p&gt;FaceMode follows a similar division of responsibility. Your agent handles conversation logic and produces speech. FaceMode takes that audio, generates synchronized avatar media, and publishes it as a participant in your room. Your frontend subscribes through the room SDK it already uses, as described in the &lt;a href="https://facemode.io/llms-full.txt" rel="noopener noreferrer"&gt;FaceMode product summary&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Consequently, switching LLMs is not the main reason to choose one over the other. If your application mixes one company's transcription with another company's language model and a third company's TTS, both document a path for preserving that composition.&lt;/p&gt;

&lt;p&gt;The transport boundary is a clearer difference. Synthesia's current operational documentation explicitly lists LiveKit-only transport. FaceMode's direct API accepts a room binding for LiveKit or Daily. That makes FaceMode relevant to a Daily-based application without implying that every third-party voice platform already has a tested, native FaceMode integration.&lt;/p&gt;

&lt;p&gt;Be specific about what “keep your stack” means. You still need to route audio correctly, handle session lifecycle, and build a frontend that plays media. An avatar layer does not remove those responsibilities or make an existing voice agent production-ready by itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration paths: LiveKit, TypeScript, and Pipecat
&lt;/h2&gt;

&lt;p&gt;For a Python LiveKit application, Synthesia documents &lt;code&gt;livekit-plugins-synthesia&lt;/code&gt; and the &lt;code&gt;livekit.plugins.synthesia&lt;/code&gt; import namespace. The &lt;a href="https://docs.synthesia.io/reference/ia-livekit-plugin-reference" rel="noopener noreferrer"&gt;plugin requirements&lt;/a&gt; specify Python 3.10 or later and LiveKit Agents 1.8.2 or later. Its marketing page uses a different installation name, so follow the plugin reference and quickstart for exact package instructions.&lt;/p&gt;

&lt;p&gt;The following is the integration excerpt from that reference, without its inline annotation. It belongs in an existing worker with &lt;code&gt;session&lt;/code&gt;, &lt;code&gt;ctx&lt;/code&gt;, environment credentials, and a workspace-accessible avatar ID already configured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;livekit.plugins&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;synthesia&lt;/span&gt;

&lt;span class="n"&gt;avatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;synthesia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AvatarSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;synthesia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AvatarConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avatar_ids&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;avatar-id&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reference says the room must already be connected and &lt;code&gt;avatar.start()&lt;/code&gt; must run before &lt;code&gt;AgentSession.start()&lt;/code&gt;. It returns after the avatar joins and publishes video. This is an attachment excerpt, not a standalone script; use Synthesia's &lt;a href="https://docs.synthesia.io/reference/interactive-avatar-minimal-quickstart" rel="noopener noreferrer"&gt;minimal quickstart&lt;/a&gt; for the complete worker and browser app.&lt;/p&gt;

&lt;p&gt;FaceMode's Python package is &lt;code&gt;livekit-plugins-facemode&lt;/code&gt;, imported as &lt;code&gt;livekit_plugins_facemode&lt;/code&gt;. Its &lt;a href="https://docs.facemode.io/integrations/livekit-agents-python" rel="noopener noreferrer"&gt;Python guide&lt;/a&gt; requires Python 3.13 or later and LiveKit Agents 1.7 or later. The same attachment boundary looks like this, adapted from FaceMode's integration README with required environment values made explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;livekit_plugins_facemode&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AvatarSession&lt;/span&gt;

&lt;span class="n"&gt;avatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AvatarSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACEMODE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;avatar_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACEMODE_AVATAR_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agent_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;livekit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LIVEKIT_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LIVEKIT_WORKER_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here too, the room and agent session already exist. Start the Python agent with audio output disabled, wait for avatar media using the documented helper, and shut the avatar session down when the call ends. The &lt;a href="https://facemode.io/blog/livekit-voice-agent-avatar" rel="noopener noreferrer"&gt;LiveKit avatar tutorial&lt;/a&gt; covers those surrounding steps.&lt;/p&gt;

&lt;p&gt;FaceMode also ships &lt;code&gt;@facemode/agents-plugin-facemode&lt;/code&gt; for TypeScript and &lt;code&gt;pipecat-facemode&lt;/code&gt; for Python pipelines. A Pipecat avatar integration is not just an interchangeable LiveKit snippet: FaceMode's service taps TTS frames and handles returned media, with transport output configuration depending on how the pipeline is connected. Follow the &lt;a href="https://docs.facemode.io/integrations/overview" rel="noopener noreferrer"&gt;integration overview&lt;/a&gt; rather than assuming all transports use identical setup.&lt;/p&gt;

&lt;p&gt;Synthesia's product page mentions Python and Node in one section, but its FAQ says the plugin currently supports Python LiveKit Agents only; the reviewed reference is Python-specific. The same page marks Pipecat as coming soon. Treat those as availability questions to confirm before choosing a runtime, not proof that undocumented paths cannot exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avatar styles and custom creation
&lt;/h2&gt;

&lt;p&gt;Synthesia's announcement describes photorealistic avatars and branded Style Avatars powered by Express-3. However, its &lt;a href="https://docs.synthesia.io/reference/ia-operational-trust" rel="noopener noreferrer"&gt;operational limitations&lt;/a&gt; say Interactive Avatar currently uses synthetic and personal avatars, not stock actor avatars. Its minimal quickstart repeats that restriction and explains how to obtain an Interactive ID from an eligible workspace avatar.&lt;/p&gt;

&lt;p&gt;That distinction prevents a common purchasing mistake: a large catalog on a video-generation website does not mean every avatar in it can be used in a real-time session. Validate the specific appearance you want through the interactive product, using the actual account and API access you plan to deploy.&lt;/p&gt;

&lt;p&gt;FaceMode documents five styles: realism, semi-realism, 3D animation, anime, and flat vector. It also accepts a front-facing portrait for a custom avatar. Those are documented product capabilities, not evidence that its visual quality is better than Synthesia's.&lt;/p&gt;

&lt;p&gt;For a branded tutor, compare readability and character consistency during a full lesson. For a support agent, inspect listening behavior and lip sync across several utterances. Use the same script and reference style wherever the products permit it, rather than comparing each vendor's most favorable demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Latency: compare the same measurement
&lt;/h2&gt;

&lt;p&gt;FaceMode's published target is approximately &lt;strong&gt;960ms from audio to rendered frame&lt;/strong&gt;. It is not a promise of 960ms from the user's last word to a response, and it is not a result measured for this article. Transcription, turn detection, LLM generation, TTS, networking, and playback all affect the experience a user sees.&lt;/p&gt;

&lt;p&gt;The Synthesia pages reviewed describe real-time operation but do not provide a directly comparable audio-to-rendered-frame latency figure. Its quickstart discusses a preflight optimization for the voice pipeline; that is not an avatar rendering benchmark. “Not published in the reviewed sources” is different from “slow.”&lt;/p&gt;

&lt;p&gt;Measure at least three separate timings in your evaluation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Session startup:&lt;/strong&gt; request creation to the first playable video track.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response onset:&lt;/strong&gt; end of the user's turn to audible speech and visible response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interruption recovery:&lt;/strong&gt; user interruption to stopped playback and return to listening.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use the same region, voice model, utterance, and client conditions. Record both typical and slower responses, including cold starts. A target for one stage cannot establish which complete system is faster, and neither successful socket negotiation nor a room join proves that media is already playing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing, free access, and production limits
&lt;/h2&gt;

&lt;p&gt;Synthesia's &lt;a href="https://www.synthesia.io/features/avatars/interactive-avatars" rel="noopener noreferrer"&gt;Interactive Avatar product page&lt;/a&gt; advertises &lt;strong&gt;500 free Interactive Avatar minutes&lt;/strong&gt; and pay-as-you-go at &lt;strong&gt;$0.12/minute&lt;/strong&gt; , with no commitment or minimum. Its &lt;a href="https://docs.synthesia.io/reference/ia-operational-trust" rel="noopener noreferrer"&gt;operational documentation&lt;/a&gt; instead says 10 credits per minute, or &lt;strong&gt;$0.10/minute&lt;/strong&gt;. These public sources disagree. Confirm the account-specific rate before estimating a production bill.&lt;/p&gt;

&lt;p&gt;At the advertised $0.12 rate, 1,000 avatar minutes would cost $120 for that layer alone. That is arithmetic based on the product page, not a quote: your voice models, media infrastructure, and other services remain separate costs. Do not use prices for Synthesia's scripted-video plans as a substitute for Interactive Avatar pricing.&lt;/p&gt;

&lt;p&gt;FaceMode's &lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;beta terms&lt;/a&gt; provide &lt;strong&gt;3,600 credits, equivalent to 60 minutes&lt;/strong&gt; , with one credit metering one second of streamed video. Credit purchases are disabled during beta and top-ups open at general availability. There is no published paid rate in the reviewed FaceMode product summary, so this comparison cannot establish which service is cheaper in production.&lt;/p&gt;

&lt;p&gt;FaceMode's beta also has ten-minute sessions, one concurrent session per account, and a minimum remaining balance of 60 credits to start. Synthesia's operational docs list one concurrent session for Freemium and 100 for paid plans. Check current terms for both products before building load-test or rollout plans.&lt;/p&gt;

&lt;p&gt;Free allowances are evaluation budgets, not substitutes for availability, quotas, or production support. Count the minutes needed for testing startup, interruptions, multiple voices, and failure recovery, not just one polished demonstration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each product is a stronger fit
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Synthesia is a stronger candidate when your immediate path is documented Python LiveKit integration and you need a publicly offered paid service.&lt;/strong&gt; Its Python baseline is lower than FaceMode's, its current product page describes general availability, and it publishes an initial usage rate. Its announcement also describes enterprise security certifications and workspace controls; validate their scope for your procurement requirements rather than assuming they apply identically to every deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FaceMode is a useful Synthesia alternative when your requirements include its documented TypeScript LiveKit plugin, Python Pipecat integration, or Daily room output through the direct API.&lt;/strong&gt; Its portrait-upload workflow and five library styles may also match your design requirements. Those benefits come with explicit private-beta access and limits.&lt;/p&gt;

&lt;p&gt;Neither choice should be justified by claiming the other forces a different LLM, owns your room, or lacks all stylized avatars. The public sources do not support those claims. The real decision is which documented integration and operating model fits the application you are shipping.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to choose an interactive avatar API
&lt;/h2&gt;

&lt;p&gt;Before committing to either product, run the same acceptance checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confirm your runtime, framework version, and media transport have a documented path.&lt;/li&gt;
&lt;li&gt;Verify your intended avatar is available for interactive use, not only rendered video.&lt;/li&gt;
&lt;li&gt;Check startup, speech, interruptions, and idle behavior in an actual room.&lt;/li&gt;
&lt;li&gt;Keep API credentials and worker tokens server-side; give the browser its own room token.&lt;/li&gt;
&lt;li&gt;Confirm pricing, concurrency, session duration, and access in your account.&lt;/li&gt;
&lt;li&gt;Inspect reconnect and shutdown behavior, including what happens after a failed session.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Does Synthesia have interactive avatars?
&lt;/h3&gt;

&lt;p&gt;Yes. The &lt;a href="https://www.synthesia.io/features/avatars/interactive-avatars" rel="noopener noreferrer"&gt;current Interactive Avatar page&lt;/a&gt; describes a generally available API that renders real-time conversations, not just scripted video. This question also appears in the autocomplete suggestions reviewed for this post. The important next check is whether your particular workspace avatar and integration path are supported.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is FaceMode a Synthesia alternative?
&lt;/h3&gt;

&lt;p&gt;For adding real-time visual output to existing voice-agent audio, it is an alternative worth testing. It is not a replacement for every Synthesia product, such as its broader scripted-video creation workflow. Compare the interactive APIs on their documented transports, runtimes, limits, and actual media behavior, while accounting for FaceMode's private-beta access.&lt;/p&gt;

&lt;p&gt;If your goal is to understand how these avatar APIs differ from platform-level launches, read the &lt;a href="https://facemode.io/blog/muse-dots-gemini-avatar-vs-facemode" rel="noopener noreferrer"&gt;Muse Avatar, OpenAI Dots, and Gemini Live Avatar comparison&lt;/a&gt;. If you already have a LiveKit agent and want to try the FaceMode path, use the &lt;a href="https://facemode.io/blog/livekit-voice-agent-avatar" rel="noopener noreferrer"&gt;LiveKit avatar plugin walkthrough&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For a FaceMode proof of concept, &lt;a href="https://console.facemode.io/waitlist" rel="noopener noreferrer"&gt;request beta access&lt;/a&gt; or start with the &lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;direct API quickstart&lt;/a&gt;. Choose on documented fit and a tested workflow, not on a comparison table that hides the constraints.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>livekit</category>
      <category>saas</category>
    </item>
    <item>
      <title>Muse Avatar, OpenAI Dots, Gemini Live Avatar vs FaceMode</title>
      <dc:creator>prajwaldkadam</dc:creator>
      <pubDate>Fri, 02 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/facemode/muse-avatar-openai-dots-gemini-live-avatar-vs-facemode-3j63</link>
      <guid>https://dev.to/facemode/muse-avatar-openai-dots-gemini-live-avatar-vs-facemode-3j63</guid>
      <description>&lt;p&gt;Muse Avatar, OpenAI Dots, and Gemini Live Avatar put different kinds of visual presence around AI agents. For a developer, the first question is not which looks best: it is whether the product supplies an agent experience or a talking avatar API you can attach to the voice agent you already run.&lt;/p&gt;

&lt;p&gt;Meta's &lt;a href="https://research.meta.ai/blog/bringing-your-muse-to-life" rel="noopener noreferrer"&gt;Muse Realtime Avatar research announcement&lt;/a&gt; appeared on September 23, 2026. Google's &lt;a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-8-live-with-live-avatar/" rel="noopener noreferrer"&gt;Gemini 3.8 Live with Live Avatar announcement&lt;/a&gt; followed on September 24, and OpenAI &lt;a href="https://openai.com/index/introducing-dots/" rel="noopener noreferrer"&gt;introduced Dots&lt;/a&gt; on September 29. They are related developments, but they are not interchangeable integration options.&lt;/p&gt;

&lt;p&gt;This is FaceMode's documentation-based category comparison, checked on October 2, 2026. We have not run an independent visual-quality or latency benchmark across these products. The differences below describe documented product boundaries, not a claim that one provider wins every workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;What the reviewed sources describe&lt;/th&gt;
&lt;th&gt;Developer integration question&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://research.meta.ai/blog/bringing-your-muse-to-life" rel="noopener noreferrer"&gt;Meta Muse Avatar&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Avatar rendering coupled to Muse Realtime Voice; images can drive expressive characters&lt;/td&gt;
&lt;td&gt;The research post does not document an external PCM-to-avatar API for your room&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://openai.com/index/introducing-dots/" rel="noopener noreferrer"&gt;OpenAI Dots&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Persistent assistants with cloud computers, connected apps, messaging, and voice calls&lt;/td&gt;
&lt;td&gt;An assistant product, not a documented lip-synced video output API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-8-live-with-live-avatar/" rel="noopener noreferrer"&gt;Gemini Live Avatar&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Avatar capability natively paired with Gemini 3.8 Live, available in Gemini Enterprise&lt;/td&gt;
&lt;td&gt;Evaluate as part of the Gemini Live conversation stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://facemode.io/llms-full.txt" rel="noopener noreferrer"&gt;FaceMode&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Audio-driven avatar API and plugins, publishing into your LiveKit or Daily room&lt;/td&gt;
&lt;td&gt;Evaluate as an added visual layer for your existing audio pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table separates categories before comparing features. A hosted assistant may be the right product for an employee who wants work delegated. A video-generation layer may be the right component for a team building a customer-facing voice application. Both needs are real; they do not share the same acceptance criteria.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meta Muse Realtime Avatar: shared speech tokens and video
&lt;/h2&gt;

&lt;p&gt;Meta's research post describes Muse Realtime Voice and Muse Realtime Avatar as a single streaming system. The voice model produces speech tokens carrying both content and delivery. An audio decoder turns those tokens into speech, while the avatar model consumes the same stream to generate the visual performance.&lt;/p&gt;

&lt;p&gt;The avatar model is an audio-driven Diffusion Transformer conditioned on the speech-token stream, reference media, and recent video context. It produces video in short causal chunks and carries recent generated context into the next chunk. That is the technical mechanism Meta describes for maintaining continuity during a live conversation.&lt;/p&gt;

&lt;p&gt;Meta reports &lt;strong&gt;448×768 portrait video at 25fps&lt;/strong&gt; and approximately &lt;strong&gt;870ms from the end of a user's turn to the first byte of a synchronized voice-and-video response&lt;/strong&gt;. This is a vendor-reported end-of-turn response metric, not the time taken to render an isolated audio frame and not a measured browser playback delay from our own test.&lt;/p&gt;

&lt;p&gt;The post also describes company-run live-call preference tests against Runway Characters and HeyGen LiveAvatar. Raters preferred Muse overall, while the mannerism comparison with Runway was not statistically distinguishable from parity. That result should be attributed to Meta's evaluation and its tested conditions, not turned into a universal ranking of every avatar API.&lt;/p&gt;

&lt;p&gt;For integration planning, the important limit is what the post actually documents. It explains Muse's coupled voice-and-avatar system and notes that its examples do not all reflect avatars available in the Muse app. It does not provide a public recipe for sending your own PCM audio to Muse Avatar or publishing its output into your LiveKit room. That is a limit of the reviewed documentation, not proof that Meta will never offer such a product.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI Dots: an assistant with a visual identity
&lt;/h2&gt;

&lt;p&gt;OpenAI's &lt;a href="https://openai.com/index/introducing-dots/" rel="noopener noreferrer"&gt;Dots announcement&lt;/a&gt; describes always-on agents powered by GPT-6 Astra. They have cloud computers, can use a browser, connect to more than 4,000 apps through plugins, and work on goals over time. Users can message or call them through ChatGPT, with Slack and Teams also described as communication channels.&lt;/p&gt;

&lt;p&gt;This is a persistent-assistant architecture. Its value is task continuity: a user gives the agent context and goals, then reviews work or decisions rather than supplying every next instruction. The announcement includes examples such as investigating software feedback, updating research analysis, and preparing content for approval.&lt;/p&gt;

&lt;p&gt;The cartoon-like identity shown around Dots is not equivalent to a streaming avatar renderer. The launch article does not document an endpoint that accepts a developer's audio stream and returns a lip-synced video participant. Calling it an “avatar” in news coverage does not make it a substitute for a real-time avatar API.&lt;/p&gt;

&lt;p&gt;OpenAI says rollout begins across &lt;strong&gt;Pro, Business Premium, and Enterprise&lt;/strong&gt; plans in eligible markets. Those access details matter if you want a personal or organizational assistant. They do not answer whether your product can stream its own TTS into a custom face; that is a different capability and is not documented in the reviewed announcement.&lt;/p&gt;

&lt;p&gt;Choose Dots for the assistant workflow it actually offers. Do not evaluate it as though its cloud computer, connected apps, and background tasks were features that a narrowly scoped audio-to-video renderer ought to provide. FaceMode does not replace that agent harness or perform those tasks on your behalf.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gemini Live Avatar: a native conversational video capability
&lt;/h2&gt;

&lt;p&gt;Google's &lt;a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-8-live-with-live-avatar/" rel="noopener noreferrer"&gt;announcement&lt;/a&gt; presents Gemini 3.8 Live with Live Avatar as near-real-time visual presence natively coupled to Gemini's live dialogue model. It includes lip sync, expressions, multimodal conversation, and asynchronous tool execution while dialogue continues.&lt;/p&gt;

&lt;p&gt;Google says the feature can transition across &lt;strong&gt;97 languages&lt;/strong&gt; , adapting speech-to-speech synchronization and expressions. It also describes a preset avatar library and custom avatars created from reference images, with custom creation available through enterprise allowlisting. These are Google's published capabilities, not independently tested quality claims from this article.&lt;/p&gt;

&lt;p&gt;The announcement says Live Avatar is available in &lt;strong&gt;Gemini Enterprise&lt;/strong&gt; and links developers to API documentation. It also describes SynthID watermarking for audio and video output. For organizations already evaluating Gemini's live conversational stack, those capabilities belong in the procurement and technical review.&lt;/p&gt;

&lt;p&gt;What the announcement does not establish is a drop-in renderer for an arbitrary external TTS stream. Its architecture is described as paired with Gemini 3.8 Live. That is narrower than saying “all your infrastructure must be Google,” which the launch post alone does not prove. Review the actual enterprise API and deployment terms before drawing conclusions about external clients, networking, or room integration.&lt;/p&gt;

&lt;p&gt;A team adopting Gemini for conversation generation is making a different decision from a team that already has a working STT/LLM/TTS pipeline and wants only video output. The distinction is about the integration boundary, not whether either architecture is inherently better.&lt;/p&gt;

&lt;h2&gt;
  
  
  FaceMode: a talking avatar API for existing voice agents
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://facemode.io/llms-full.txt" rel="noopener noreferrer"&gt;FaceMode's product summary&lt;/a&gt; describes a focused audio-to-video layer. Your agent retains its speech recognition, language model, voice synthesis, and turn detection. FaceMode receives the audio it produces, renders a lip-synced avatar, and publishes media as a participant in a LiveKit or Daily room you own.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.facemode.io/integrations/overview" rel="noopener noreferrer"&gt;integration overview&lt;/a&gt; covers LiveKit Agents plugins for Python and TypeScript, a Python Pipecat integration, and the direct REST/WebSocket path. The direct API is useful when your application produces audio outside those frameworks, provided you can implement the documented session lifecycle and PCM negotiation.&lt;/p&gt;

&lt;p&gt;That does not mean every hosted voice service or conferencing application is already supported natively. Verify that your platform exposes the audio you need and that your intended output can use the documented room transport. “Can stream audio” is an input capability, not proof of an end-to-end integration with every product bearing an API label.&lt;/p&gt;

&lt;p&gt;FaceMode documents a front-facing portrait upload workflow and five library styles: realism, semi-realism, 3D animation, anime, and flat vector. Its published latency target is approximately &lt;strong&gt;960ms from audio to rendered frame&lt;/strong&gt;. That target is not a guarantee of total conversational response time or instantaneous interruption cutoff.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt; describes private-beta access, 3,600 free credits equivalent to 60 minutes, one credit per second of streamed video, ten-minute sessions, and one concurrent session per account. Paid top-ups are not open during beta. Those operating limits should be part of the decision, especially if your next step is production deployment rather than a proof of concept.&lt;/p&gt;

&lt;h2&gt;
  
  
  Latency claims are not directly comparable
&lt;/h2&gt;

&lt;p&gt;Meta's approximately 870ms number begins at the end of the user's turn and ends at the first byte of synchronized response. FaceMode's approximately 960ms target begins with supplied audio and concerns its rendering path. Comparing the two numbers as a speed ranking would combine different timing boundaries and a reported result with a product target.&lt;/p&gt;

&lt;p&gt;The reviewed Dots announcement is not an avatar-rendering benchmark. Google's Live Avatar announcement does not publish a directly comparable numeric latency figure. Missing numbers should remain missing, rather than being inferred from words such as “real-time” or “near-real-time.”&lt;/p&gt;

&lt;p&gt;For an application test, record session startup, end-of-turn response onset, media synchronization, and interruption recovery separately. Use the same voice settings, client region, network conditions, and utterances where the architectures permit it. Keep cold-start observations separate from ongoing turns.&lt;/p&gt;

&lt;p&gt;This also makes failures easier to diagnose. A delayed LLM response, slow avatar startup, and browser audio playback restriction can all look like “the avatar is slow” while requiring different fixes. A comparison article should not flatten those into one unexplained millisecond figure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each product is a useful fit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Muse Avatar:&lt;/strong&gt; investigate it when you care about Meta's integrated consumer-facing embodiment research, shared speech-token architecture, or expressive character generation. Its research demos provide technical context, but the reviewed post is not an external integration guide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI Dots:&lt;/strong&gt; evaluate it when you want a persistent assistant working across connected applications with review and permission controls. It addresses delegated work, not just a visual response to supplied speech.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini Live Avatar:&lt;/strong&gt; evaluate it when Gemini's live dialogue stack and enterprise access fit your application. The announced multilingual synchronization, tools, and custom-avatar pathway are genuine reasons to include it in that review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FaceMode:&lt;/strong&gt; test it when your voice agent already exists and its audio needs a visual layer in a documented LiveKit or Daily room. Account for private-beta limits and test media readiness, not only API responses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FaceMode is not the only provider in the last category. Other vendors also offer bring-your-own-stack real-time avatar components. For a more direct comparison, read &lt;a href="https://facemode.io/blog/synthesia-interactive-avatar-vs-facemode" rel="noopener noreferrer"&gt;Synthesia Interactive Avatar vs FaceMode&lt;/a&gt;, which examines shared architecture as well as differences in runtimes, transport, pricing, and access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a face to an existing LiveKit voice agent
&lt;/h2&gt;

&lt;p&gt;If you choose the component route, attach an avatar session inside the worker you already run. This FaceMode excerpt is adapted from the Python integration README. It assumes &lt;code&gt;agent_session&lt;/code&gt; and a connected &lt;code&gt;ctx.room&lt;/code&gt; already exist, and that environment credentials are configured on the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;livekit_plugins_facemode&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AvatarSession&lt;/span&gt;

&lt;span class="n"&gt;avatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AvatarSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACEMODE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;avatar_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACEMODE_AVATAR_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;livekit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LIVEKIT_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LIVEKIT_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete flow also starts the agent with direct audio output disabled, waits for avatar media, and handles shutdown. The &lt;a href="https://facemode.io/blog/livekit-voice-agent-avatar" rel="noopener noreferrer"&gt;LiveKit avatar plugin tutorial&lt;/a&gt; covers those steps and the browser subscription path. Use the &lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;direct API quickstart&lt;/a&gt; if you are not using a framework plugin.&lt;/p&gt;

&lt;p&gt;Keep credentials separate: the avatar worker receives a server-side publisher token, while the browser gets its own room token. A read-only viewer and a user publishing a microphone have different permissions. An API key or worker token should never be the shortcut used to make a browser demo connect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions to answer before choosing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do you need an assistant or a renderer?&lt;/strong&gt; If the requirement is autonomous work across apps, compare agent products and their controls. If it is visual output for existing speech, compare real-time avatar APIs and transports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can you keep the voice pipeline you already have?&lt;/strong&gt; FaceMode documents that path explicitly. Google's launch describes native pairing with Gemini Live. Meta's research describes shared voice tokens. Dots is a packaged assistant. Check documentation for the specific integration boundary rather than assuming the marketing term “avatar” implies the same contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What will you actually test?&lt;/strong&gt; Start with a short real conversation: join, speak, interrupt, pause, resume, and end. Inspect video, audio, and session cleanup. Then check pricing and concurrency with the account you will deploy, not only the public demo.&lt;/p&gt;

&lt;p&gt;The goal is to choose the right layer for your application. If FaceMode's component model fits, &lt;a href="https://console.facemode.io/waitlist" rel="noopener noreferrer"&gt;request beta access&lt;/a&gt; or read the &lt;a href="https://docs.facemode.io" rel="noopener noreferrer"&gt;FaceMode docs&lt;/a&gt; before wiring it into your agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Primary sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://research.meta.ai/blog/bringing-your-muse-to-life" rel="noopener noreferrer"&gt;Meta: Bringing Your Muse to Life&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/introducing-dots/" rel="noopener noreferrer"&gt;OpenAI: Introducing Dots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-8-live-with-live-avatar/" rel="noopener noreferrer"&gt;Google: Introducing Gemini 3.8 Live with Live Avatar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://facemode.io/llms-full.txt" rel="noopener noreferrer"&gt;FaceMode product summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.facemode.io/quickstart" rel="noopener noreferrer"&gt;FaceMode direct API quickstart&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>news</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
