Docs index: /llms.txt · every page as Markdown: add .md

‹ Platforms

Python

Render Essence 2 and Expression 2 avatars from your own Python code.

Your computer or serverNo GPU neededAPI secretPython 2.12.12

A file in and frames out, or a live stream of audio in and frames out, on your own machine.

Before you start

To run an avatar without code, use the CLI.

Note: On Linux and Windows, Python renders both models on the CPU alone, no GPU. On macOS it renders on Apple silicon. Windows has its own page: Windows. See CPU only (no GPU).

DetailExpression 2Essence 2
Rendersany character from one portraita photoreal person from one portrait
Installpip install "bithuman[expression-2]"pip install "bithuman[essence-2]"
FramesRGB numpy arrays, (height, width, 3) uint8the same
You needCheck
Python 3.10–3.14python3 --version
macOS 14+ on Apple silicon, Linux x86_64 or Linux arm64, or Windows 11 x86_64python3 -c "import platform; print(platform.system(), platform.machine())"
An API secretYour API secret
A paid plan (Creator or higher): billing: How billing worksPricing
About 1 GB of disk (570 MB package, about 120–200 MB per avatar)df -h .

Install

python3 -m venv .venv
source .venv/bin/activate

Then install the extra for your model. The first run below uses Expression 2:

Expression 2

pip install "bithuman[expression-2]"

Essence 2

pip install "bithuman[essence-2]"

The version pip installs depends on your system: PyPI serves 2.12.12 for macOS on Apple silicon and Linux x86_64; on Linux arm64, pip installs 2.12.10, and on Windows 11 x86_64, 2.12.9 (Downloads).

Install into a virtual environment: Debian and Ubuntu refuse a system-wide pip install (externally-managed-environment). If venv is missing, run sudo apt install -y python3-venv first. The package installs no bithuman command; python -m bithuman runs the same renders from a terminal (Your own agent).

Authenticate

Set BITHUMAN_API_SECRET in the shell that runs Python (bithuman.open reads it), or pass api_secret= to AsyncBithuman.create(). Rendering needs it. python -m bithuman pull needs it for an agent code, a sample’s code included; a sample’s name (wise-pup, sofia-ramirez) downloads with no secret.

Run your first avatar

export BITHUMAN_API_SECRET="<your API secret>"
export AVATAR=$(python -m bithuman pull A23WJF0199)    # prints the avatar's local path
curl -fsSLo speech.wav https://docs.bithuman.ai/samples/speech.wav
import bithuman, os
bithuman.open(os.environ["AVATAR"]).render("speech.wav", out_mp4="out.mp4")
# → out.mp4: wise-pup speaking the sample, 416×720, 15 s

Open out.mp4 to watch it talk. out_mp4= needs no ffmpeg, and render returns the number of frames written. It takes a path to an audio file (WAV, MP3 and the other common formats, at any sample rate: the SDK decodes and resamples a file for you, so the 24 kHz sample works as is), or already-decoded audio, which must already be 16 kHz mono (int16 or float32 arrays, or raw 16-bit bytes).

The same call opens Essence 2 and Essence 1 avatars: for a photoreal person, get the sofia-ramirez Essence 2 sample with python -m bithuman pull A52DHS2219 and render it the same way (1080×1920). If it stops and names bithuman[essence-2], install that extra. The output size follows the agent’s source video, so an agent of your own can come out portrait or landscape.

Your own agent

To render an agent you created, download it with your API secret. pull gets whatever the agent’s model is made of (one .imx, or the package an Essence 2 agent on the current engine has) and prints its local path; add --model expression-2 or --model essence-2 to pick one of the agent’s models:

export AVATAR=$(python -m bithuman pull "$AGENT_CODE")    # AGENT_CODE = your agent's code

Then render it with the same bithuman.open(os.environ["AVATAR"]).render(...) call as above. From a terminal, one command downloads the model by code and renders it:

BITHUMAN_API_SECRET=<your API secret> python -m bithuman render <AGENT_CODE> speech.wav     # writes <AGENT_CODE>.mp4

An agent code that is not yours and not a sample avatar answers 404 (Troubleshooting).

What downloads on the first run

The first Essence 2 render downloads a shared audio encoder (about 66 MB) to ~/.bithuman/deps, once. python -m bithuman render also keeps the agent’s model (about 143 MB for an Essence 2 agent) in ~/.cache/bithuman. Behind a firewall, allow these downloads, or run the first render on a connected machine. The disk figure above includes them.

To process the frames yourself, iterate over render without out_mp4=. The blocks below open the AVATAR path from Run your first avatar:

import bithuman, os

with bithuman.open(os.environ["AVATAR"]) as avatar:
    frames = [image for image in avatar.render("speech.wav")]
print(len(frames), "frames of", frames[0].shape)
# → 300 frames of (720, 416, 3)

The loop on its own, as it reads in your app. show is your app’s own: it draws one RGB frame.

pip install "bithuman[expression-2]"
import bithuman, os

with bithuman.open(os.environ["AVATAR"]) as avatar:
    for image in avatar.render("speech.wav"):
        show(image)

Frames are RGB; OpenCV expects BGR, so write one with cv2.imwrite("frame.png", image[:, :, ::-1]).

No display (server/CI)

render(..., out_mp4="out.mp4") needs no window, no GPU and no ffmpeg, so it is the path for a server, a container or CI. The window in Build a Python app needs a desktop session.

Talk to it

The avatar draws the face and the lips; it does not listen or think. For “a character I can talk to” you add a language model and a voice. No path installs in a few minutes with no key at all: the CLI’s local conversation brain builds llama-cpp-python from source and downloads about 860 MB. The shortest path is your own OpenAI key, which does the thinking and the speaking, and the avatar renders on your machine:

pip install openai                       # about 30 MB, in the same virtual environment
export OPENAI_API_KEY="<your OpenAI key>"
import bithuman, os
from openai import OpenAI

ai = OpenAI()                                       # reads OPENAI_API_KEY
question = "Tell me one fun fact about dogs."       # text in
reply = ai.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "system", "content": "You are a friendly pup. Answer in two short sentences."},
              {"role": "user", "content": question}],
).choices[0].message.content
with ai.audio.speech.with_streaming_response.create(
    model="gpt-4o-mini-tts", voice="alloy", input=reply, response_format="wav"
) as speech:
    speech.stream_to_file("reply.wav")              # 24 kHz: a file path is resampled for you
bithuman.open(os.environ["AVATAR"]).render("reply.wav", out_mp4="reply.mp4")
# → reply.mp4: wise-pup speaking the answer

To start from speech instead of text, transcribe it first: question = ai.audio.transcriptions.create(model="whisper-1", file=open("question.wav", "rb")).text.

  • Cost: OpenAI bills the reply and the voice on your key, a fraction of a cent for a short answer. bitHuman credits for the avatar (How billing works).
  • Live, with your microphone: conversation.py in the examples repository runs the same idea as a conversation in a window (OpenAI Realtime, OPENAI_API_KEY); see Companion app.
  • No OpenAI key: install the separate CLI, which this package does not include, and sign in. bithuman run <avatar> then talks in your browser with the voice on your bitHuman account.
Measured with Python SDK 2.11.6
Capture detailsCaptured on an Apple M4 Mac (macOS) · Python SDK 2.11.6 · sofia-ramirez (Essence 2) · 2026-09-23.

Performance

ConfigurationEssence 2Expression 2
Intel Core i7-13700F (x86_64) Linux · Python CPU only (no GPU)
1.2× real timeIntel Core i7-13700F (x86_64), CPU only (no GPU) · bithuman 2.12.1 · measured 2026-10-08
2.4× real timeIntel Core i7-13700F (x86_64), CPU only (no GPU) · bithuman 2.12.1 · measured 2026-10-08
Apple M4 macOS · Python
6.9× real timeApple M4 · bithuman 2.11.12 · measured 2026-09-25
8.4× real timeApple M4 · bithuman 2.11.12 · measured 2026-09-25

Times real time: seconds of avatar video rendered per second. At 1.0× or more, an avatar holds a live conversation. Select a figure for its release and date. All configurations and how we measure.

Each rate is measured on the machine named in its row. Speed depends on the CPU, its free cores and what else is running: expect real time or faster on a modern multi-core CPU, and slower on a small or busy one. The log line below shows what your own machine does.

A finished render logs its own rate on the bithuman logger at INFO. Nothing prints until you configure logging:

import logging
logging.basicConfig(level=logging.INFO)   # then call render as above

This section moved: docs.bithuman.ai/platforms/python#run-your-first-avatar

This section moved: docs.bithuman.ai/platforms/python/app#integrate-into-your-app

This section moved: docs.bithuman.ai/build/voice-agent/python#a-voice-agent-on-your-own-livekit-server

This section moved: docs.bithuman.ai/platforms/python/app#complete-example

This section moved: docs.bithuman.ai/platforms/python/app#requirements

This section moved: docs.bithuman.ai/platforms/python/app#run-it

This section moved: docs.bithuman.ai/platforms/python/app#expected-output

This section moved: docs.bithuman.ai/platforms/python/app#make-it-your-own

This section moved: docs.bithuman.ai/platforms/python/app#platform-notes

This section moved: docs.bithuman.ai/platforms/python/reference

This section moved: docs.bithuman.ai/platforms/python/troubleshooting