Docs / Concepts /Models

Expression 2

Official guide to expression-2 — bitHuman's second-generation expression engine: per-identity training from one photo, GPU/CPU/Apple Neural Engine serving tiers, real-footage idle, latency expectations, and pricing.

Note — Generally available. expression-2 (“Expression 2”) is the second-generation expression engine and the model for stylized and universal characters — cartoons, animals, creatures, robots, and people. Available now — see Essence 2 & Expression 2 for the family overview.

What it is

expression-2 is bitHuman’s second-generation expression engine: an audio-driven, real-time talking avatar whose motion is fully generated live from the audio — expressions, mouth, and head movement are synthesized each session, not replayed from a pre-rendered base.

It is also fully generative across the whole scene: the engine animates the entire 416×720 portrait frame, not a detected face region. That is what makes it the model for any character morphology — cartoons, animals, creatures, robots, objects with a “face”, and people alike. There is no face detector, cropping, or landmark step anywhere in the pipeline, so a winged creature or a talking appliance animates just as naturally as a headshot.

What makes it different from every other bitHuman model is per-identity training. At creation time the platform builds a small model of your specific identity from a single photo. The full rendering model never ships anywhere; only the compact per-identity model serves your sessions — a small, fast build tuned to render a sharp, well-defined mouth and teeth. That per-identity step is why Expression 2’s motion tracks the audio so closely — and why creation takes longer than the other models (see creation below).

At serve time the engine generates the full 416×720 scene at 20 frames per second and streams it over WebRTC like every other bitHuman session — the platform contract (push audio in, drain lip-synced video out) is unchanged.

When to choose it

  • You want the most lifelike generated motion in the lineup. Expression 2 synthesizes expression and movement from the audio itself rather than patching a base video.
  • Your character isn’t a photorealistic human. The whole scene animates — stylized, cartoon, animal, creature, robot, and object characters are exactly what this engine is for (and where model: "auto" routes them).
  • You only have a photo. One image is enough — creation is image-only for every model, and Expression 2 trains straight from the photo.
  • You want the same identity on cloud GPU, CPU, or Apple Neural Engine — Expression 2 serves on all three tiers (see serving).

If you need the absolute highest image fidelity for close-up content, compare with Essence 2 Max. If cost at scale or on-device deployment is the priority, compare with Essence 2. For the family-level decision, start at Essence 2 & Expression 2.

How creation works

Create the agent once with POST /v1/agent/generate and model: "expression-2". Creation is asynchronous and costs 2000 credits (one-time, per agent). Expression 2 handles any subject — photorealistic or stylized — and it is the family that works best for cartoonish, stylized, animal, creature, and robot characters, which is why model: "auto" routes those inputs here, and why the Essence 2 subject gate points rejected creations at this model. You can also add expression-2 to an existing agent (2000 credits — the same per-identity training runs; it uses the agent’s stored image).

Note The Python examples below use requests, which is not in the standard library — pip install requests first, or use curl / urllib instead.

import requests

import os

resp = requests.post(
    "https://api.bithuman.ai/v1/agent/generate",
    headers={
        "Content-Type": "application/json",
        "api-secret": os.environ["BITHUMAN_API_SECRET"],
    },
    json={
        "prompt": "You are a friendly product specialist.",
        "image": "https://example.com/face.jpg",
        "model": "expression-2",
    },
)
print(resp.json())
# {"success": true, "message": "Agent generation started",
#  "agent_id": "A66GYD8664", "status": "processing"}

Note — image must be publicly fetchable, and this is not checked at submit time. The https://example.com/… URLs above are placeholders. Posting one verbatim returns HTTP 200 with {"success": true, "status": "processing"}, and the job only fails seconds later with Image processing failed: Failed to download after 3 attempts: 404. The credits are charged at submit and automatically refunded on that failure (verified 2026-07-28: -500 then +500 within 4 s), so nothing is lost — but a 200 here is not confirmation that your image was accepted. Poll GET /v1/agent/status/{agent_id} before assuming the creation started.

Inputs. Creation is image-only: an image (URL or upload) is the identity source, and Expression 2 trains straight from the photo. If you omit it, the platform generates a portrait from your prompt first. bitHuman also generates the agent’s 10-second idle clip internally as part of creation, authored to loop seamlessly. Video input is not part of the creation contract and is being removed platform-wide: do not send video — as the rollout completes, a request carrying it is rejected with 400 VIDEO_INPUT_NOT_SUPPORTED before anything is billed. A voice is always prepared as part of creation — supply audio to clone one, or one is generated for you.

What happens. Poll GET /v1/agent/status/{agent_id}: the run moves through the standard steps (paymentpersonavoice_image), then enters the model-training step (reported as current_step: "lip_sync", ~70% progress) where the per-identity model is trained and packaged on a training GPU. When the status reaches ready, the agent is servable on every tier.

How long. The per-identity training step runs on a dedicated training GPU and is the dominant cost of creation — plan for about 1 to 1.5 hours (roughly 60–100 minutes). The training recipe is adaptive: it starts from a short, efficient schedule, and every agent must pass the same quality checks before it ships — an identity that needs more work automatically climbs to more training, never a lower bar. That is why harder identities take longer. A recent cold-start run measured about 1 hour 40 minutes end to end; runs trend toward the lower end of the range as the shared training pool stays warm.

curl https://api.bithuman.ai/v1/agent/status/A66GYD8664 \
  -H "api-secret: $BITHUMAN_API_SECRET"

Creation failures are terminal and reported on the same status endpoint (status: "failed" plus error_message); a failed creation is not silently retried into a different model. See failure modes.

Serving tiers

A ready expression-2 agent serves through every delivery surface — the embed widget, the viewer/share URL, the REST API, and the LiveKit plugin. By default the platform routes each session down the model’s serving chain — GPU → Apple Neural Engine → CPU — starting at an always-warm GPU first line and overflowing to the next tier on capacity.

For benchmarking or placement testing you can force one runtime tier with the ?model= override on the session URL (a forced tier never overflows and fails loudly if unavailable):

?model= slugRuntimeNotes
expression-2The full chain (default)GPU → Neural Engine → CPU with automatic overflow.
expression-2-gpuGPUThe production GPU line with elastic cloud GPU overflow.
expression-2-cpuCPUForce the native quantized (int8) build on CPU servers — no GPU in the path.
expression-2-aneApple Neural EngineForce the Apple Silicon Neural Engine tier; limited real-time slots.
https://bithuman.ai/embed/A66GYD8664?model=expression-2-ane

Tier slugs are an advanced, operational surface — an unrecognized value falls back to the agent’s default routing. For production, omit ?model= and let the platform choose. See tier pinning on the embed widget.

Real-time streaming is carried by the GPU and Apple Neural Engine tiers. The CPU tier is offline-batch-grade — sized for offline talking-video generation and used as capacity overflow / fallback, not as the primary real-time line — so pin expression-2-cpu for batch and self-hosted-server work rather than low-latency live sessions.

Self-hosted. Expression 2 also renders on your own hardware via the CLI’s local renderer — macOS (Apple Silicon) and Linux x86_64 — at the self-hosted rate; batch / server-grade CPU work wants modern (AVX-512-class) CPUs. (The Python SDK has no Expression-2-loadable artifact — local rendering is a CLI surface.) See the device matrix.

On-device. The same compact per-identity model also runs fully on-device on Apple Silicon via the Swift SDK rail (preview maturity) — no server in the path. Download the runnable <code>.imx build (legacy .avatar zip) with GET /v1/agent/{code}/model/download or bithuman pull <code>. In the browser: append ?render=local to a session URL to render Expression 2 locally (LiteRT.js / WebGPU, WASM fallback), so the video never leaves the machine — rolling out per identity as web bundles publish. See Browser rendering.

Idle and speaking behavior

As of 2026-07-02, Expression 2 agents use real-footage idle: during silences the avatar plays the 10-second idle clip generated internally at creation from the identity itself. The clip is authored to loop seamlessly and forward-only (it wraps from its last frame back to its first and never plays in reverse), so idle looks like a person waiting, not a video scrubbing back and forth. Every new creation bakes its idle clip automatically.

When speech starts, the engine hands off from the idle clip to generated frames on the first rendered frame, and a per-identity color match keeps the two visually continuous. When speech ends, idle resumes only after sustained silence — brief pauses inside a sentence never flip the avatar back to idle.

Speech onset. The Expression 2 engine renders in fixed audio chunks, so the first talking frame appears roughly 1.6 seconds after speech audio begins (less when the platform bursts audio faster than real time). The lively real-footage idle masks this window — the avatar keeps moving naturally until the generated frames take over. See session behavior & troubleshooting.

Pricing

SurfaceRate
Cloud serving4 credits/min
Self-hosted serving2 credits/min
Agent creation2000 credits (one-time)
Talking-video renders4 credits per minute of output (rounded up)

Per-minute serving is metered for the whole time a session is live and the engine is rendering — idle/silent animation included. Only stopped, paused, or disconnected sessions stop accruing. Full schedule: Pricing & credits.

Limits and expectations

  • Output: the full 416×720 portrait scene, generated at 20 fps; video streams over WebRTC with adaptive bitrate.
  • Creation time: plan for about 1 to 1.5 hours — roughly 60–100 minutes (see above; a cold run measured ~1h40m, trending faster as the pool warms) — and poll status rather than assuming the few-minute wall-clock of essence-1.
  • Identity input: a clear, frontal, well-lit face photo gives the best result. The identity is fixed at creation — to change the face, create a new agent.
  • First session on a fresh agent can take longer to connect while the per-identity model is provisioned onto serving capacity; subsequent sessions reuse it. See troubleshooting.
  • Before training completes, launch surfaces that request this model reject it with 409 MODEL_NOT_GENERATED (agent A66GYD8664's expression-2 model hasn't been generated yet). Once the agent is ready, its supported_models (on status / get / list and the embed-token response) includes expression-2.

Next steps