Skip to main content

livekit-plugins-keyframe

Agent Framework plugin for Keyframe Labs avatars.

Installation

pip install livekit-plugins-keyframe

Usage

from livekit.agents import AgentSession
from livekit.plugins import keyframe

session = AgentSession(stt=..., llm=..., tts=...)

avatar = keyframe.AvatarSession(
    persona_slug="public:cosmo-2.0-live-preview",  # or persona_id="..."
    api_key="keyframe_sk_live_...",  # or set KEYFRAME_API_KEY env var
)

await avatar.start(session, room=ctx.room)
await session.start(room=ctx.room, agent=my_agent)

Authentication

Set the following environment variables:

  • KEYFRAME_API_KEY - Your Keyframe API key
  • LIVEKIT_URL - LiveKit server URL
  • LIVEKIT_API_KEY - LiveKit API key
  • LIVEKIT_API_SECRET - LiveKit API secret

Emotions

persona-2.0-live avatars support eleven expressions (keyframe.EMOTIONS): neutral, happy, sad, angry, surprised, concerned, confused, disgusted, excited, scared, skeptical. An expression holds until the next change.

Sync expressions to speech

Override tts_node with keyframe.emotion_tts_node on every agent in the session, and add keyframe.emotion_instructions() to the prompt. The LLM writes emotion markers into its reply, and the avatar changes expression on the marked word.

class MyAgent(Agent):
    def tts_node(self, text, model_settings):
        return keyframe.emotion_tts_node(self, text, model_settings)

Use the configuration that matches your TTS:

  • LiveKit Inference (expressive mode), where one <expr> marker steers both the voice and the face:

    session = AgentSession(
        tts=inference.TTS("cartesia/sonic-3.6", extra_kwargs={"add_timestamps": True}),
        expressive={"tts_instructions_append": keyframe.emotion_instructions()},
        ...
    )
    
  • ElevenLabs v3/v4 plugin, where one [happy] audio tag steers both the voice and the face. Pass style="brackets" to both functions, and set use_tts_aligned_transcript=True to keep tags out of transcripts:

    class MyAgent(Agent):
        def tts_node(self, text, model_settings):
            return keyframe.emotion_tts_node(self, text, model_settings, style="brackets")
    
    agent = MyAgent(
        instructions=f"{MY_INSTRUCTIONS}\n\n{keyframe.emotion_instructions(style='brackets')}",
    )
    session = AgentSession(
        tts=elevenlabs.TTS(model="eleven_v3"),
        use_tts_aligned_transcript=True,
        ...
    )
    
  • Any other TTS, where <expr> markers steer the face and are stripped before synthesis:

    agent = MyAgent(instructions=f"{MY_INSTRUCTIONS}\n\n{keyframe.emotion_instructions()}")
    

Set an expression directly

Use set_emotion for tool calls, vision events, or persona-1.5-live avatars (which support neutral, happy, sad, and angry):

await avatar.set_emotion("happy")

The avatar switches on the next video frame that it renders. During a reply, the avatar renders ahead of playback. When a change must land on a specific word, use markers instead.

TTS support and timing details

Timing accuracy depends on what the TTS reports:

TTS When the expression changes
Streaming TTS with word timings: Cartesia (add_timestamps=True, plugin default), Inworld (timestamp_type="WORD"), ElevenLabs v3/v4 (plugin), Rime (WebSocket), Speechify, Smallest.ai, Baseten (word_timestamps=True) On the marked word
Non-streaming TTS (Gemini, OpenAI, Hume) At the start of the sentence
Streaming TTS without word timings (Deepgram, xAI, or ElevenLabs, Fish Audio, and Gemini through Inference) Before the first word only (later markers are ignored)

Provider notes:

  • Inworld expressive mode accepts free-form labels: "warm, concerned" steers both the voice and the face, while "sympathetic" steers the voice only.
  • Cartesia expressive mode covers nine of the eleven expressions (concerned and skeptical change the face only).
  • SpaceXAI expressive mode has no expression labels, so markers change the face and are stripped before synthesis.
  • In style="brackets", only exact expression names ([happy]) change the face. Other audio tags ([whispers], [warmly]) steer the voice only. In the default "expr" style, square brackets are plain text.
Custom emotion sets and custom TTS nodes

Pass emotions= to emotion_tts_node and emotion_instructions to limit which expressions a marker can select.

A custom tts_node can attach keyframe.EmotionCue items directly to audio frames. offset is the time in seconds from the first sample of the frame and can be negative.

frame.userdata[keyframe.USERDATA_EMOTION_CUES] = [
    keyframe.EmotionCue("happy", offset=0.25),
]

Metadata

Release files for livekit-plugins-keyframe 1.8.10

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for livekit-plugins-keyframe 1.8.10
File Size Uploaded Provenance Actions
livekit_plugins_keyframe-1.8.10.tar.gz 20.0 kB With provenance Details for livekit_plugins_keyframe-1.8.10.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for livekit-plugins-keyframe 1.8.10
File Interpreter ABI Platform Actions
livekit_plugins_keyframe-1.8.10-py3-none-any.whl Python 3 none any Details for livekit_plugins_keyframe-1.8.10-py3-none-any.whl

Total release size: 43.5 kB

Release files / livekit_plugins_keyframe-1.8.10.tar.gz

Download URL livekit_plugins_keyframe-1.8.10.tar.gz
Size 20.0 kB
Tags Source
SHA-256 checksum
How to use checksums
b34a356dbfc1fdf1f91f2e7c2401aea0c12a711ed1f9d31715226d39dc4ae425
BLAKE2b-256 checksum
How to use checksums
9df4d9abc6ad76fa30be7c4f33a3f7f14abd59add96bf3586d0f4691f6127c3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / livekit_plugins_keyframe-1.8.10-py3-none-any.whl

Download URL livekit_plugins_keyframe-1.8.10-py3-none-any.whl
Size 23.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c4b8a033b67885572cab5b26ec2269d29644a58b750e31db716b82a40dbbf212
BLAKE2b-256 checksum
How to use checksums
32b95c1755f9282020e61d2276eea62aa8f6bbbf521bfb43b397150c0ec5ba7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Security for livekit-plugins-keyframe 1.8.10

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for livekit_plugins_keyframe-1.8.10.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.8.10 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page