macOS
More ▾
Render Essence 2 and Expression 2 on a Mac with Apple silicon, in a Mac app or from a terminal, with the same package as iPhone and iPad.
The same Swift package that runs on iPhone and iPad renders the avatar on a Mac with Apple silicon: in a Mac app, or in a command-line tool with swift run. No device, provisioning profile or entitlement is needed to try it from a terminal.
Before you start
| You need | Expression 2 | Essence 2 |
|---|---|---|
| A Mac | Apple silicon, macOS 13 or newer | Apple silicon M3 or newer, macOS 26 or newer |
| Toolchain | Xcode 26 or newer (to build) | the same |
| Credential | an API secret (Creator plan or higher) | the same |
| Disk | about 800 MB for the example: downloads plus the folder the engine unpacks them into | about 250 MB of downloads |
Install
In Xcode choose File → Add Package Dependencies… and paste https://github.com/bithuman-product/homebrew-bithuman.git. In a Package.swift:
.package(url: "https://github.com/bithuman-product/homebrew-bithuman.git", from: "2.19.0")
// then attach the product your target uses:
// .product(name: "Expression2", package: "homebrew-bithuman")
// .product(name: "Essence2Kit", package: "homebrew-bithuman")
// .product(name: "Essence2", package: "homebrew-bithuman")
The products:
| Product | Import | What it is | Deployment target |
|---|---|---|---|
Expression2 | import Expression2 | the Expression 2 engine with a Swift API | iOS 16 · macOS 13 |
Essence2Kit | import Essence2Kit | the Essence 2 engine with a Swift API; it includes Essence2 | iOS 26 · macOS 26 |
Essence2 | import Essence2 | the Essence 2 engine as a C library, for C, C++ and plugins | iOS 26 · macOS 26 |
Every product ships ios-arm64, ios-arm64-simulator (arm64 only) and macos-arm64. bitHumanKit 2.4.0 is legacy and frozen; new apps use Expression2 or Essence2Kit.
Authenticate
The engines check an API secret when a session starts. Set BITHUMAN_API_SECRET in the scheme's environment, or pass it in code before you create an engine: Expression2Credential.set(secret) or Essence2Credential.set(secret) (Your API secret).
The scheme's environment is for local builds. Every copy of a shipped app carries its secret, so treat it as exposed: fetch it from your backend at startup, keep it in the Keychain, give each app its own secret, and rotate it if usage looks wrong (What a shipped app holds).
Credits pay for active session time, talking or idle, billed to the second (pricing).
A Mac app built from Xcode’s App template turns on App Sandbox. Under Signing & Capabilities → App Sandbox, tick Outgoing Connections (Client), or the engines cannot check your secret.
First frame
The macOS Expression 2 example is one Swift file. Clone it, fetch the sample avatar, and run it:
git clone https://github.com/bithuman-product/bithuman-examples.git
cd bithuman-examples/swift/macos-expression2
./setup.sh # the wise-pup avatar, the shared engine and a speech clip
export BITHUMAN_API_SECRET="<your API secret>"
swift run -c release MacOSExpression2
Expected result
engine ready: 416x720, isReady=true
audio: 325451 samples, 20.34 s
generated 407 frames in … s -> out/first-frame.png
407 frames for 20.34 seconds of audio: one frame per 50 ms of speech. The first run prepares the engine for your Mac; keep Model/staged/ and later runs start faster.
The core of Sources/main.swift:
// excerpt: swift/macos-expression2/Sources/main.swift
let engine = try Expression2Engine.create(
avatarContainer: model.appendingPathComponent("agent.imx"),
sharedEngineContainer: model.appendingPathComponent("shared-engine.imx"),
stagingDir: model.appendingPathComponent("staged"))
// …
let started = Date()
engine.feed(samples)
engine.flushTail()
// …
var frames = 0, idleTicks = 0
while idleTicks < 100 {
var got = false
while let (frame, _) = engine.pull() {
if frames == 0 {
writePNG(frame, width: engine.width, height: engine.height,
to: out.appendingPathComponent("first-frame.png"))
}
frames += 1
got = true
}
if got { idleTicks = 0 } else { idleTicks += 1; usleep(50_000) }
}
Complete example
macOS Expression 2 walks through the tool above: requirements, your own avatar and audio, and troubleshooting. For a window with a microphone button, the iOS Expression 2 example is the same engine in a SwiftUI app.
Integrate into your app
The Swift API is the same on the Mac as on iPhone and iPad: feed 16 kHz mono audio, take frames on your player’s clock, end and interrupt replies. The whole table is on iOS & iPadOS; every entry point is on the Swift reference.
On a Mac:
- Files: add the
.imxfiles and engine resources to the app bundle. A sandboxed app reads only its bundle and container. - Quitting: call
Essence2Engine.quiesceAll()fromapplicationWillTerminate.
Platform notes
- Also on a Mac: the CLI renders an avatar or runs a live conversation with no code, and Python renders frames from your own scripts. Both run on Apple silicon.
- Intel Macs are not supported.
Performance
| Configuration | Essence 2 | Expression 2 |
|---|---|---|
| Apple M4 macOS · Swift package | 4.8× real timeApple M4 · Swift package 2.15.0 · measured 2026-09-24 | 8.8× real timeApple M4 · Swift package 2.15.0 · measured 2026-09-24 |
| Apple M4 macOS · CLI | 4.2× real timeApple M4 · CLI 2.8.1 · measured 2026-09-27 | 8.4× real timeApple M4 · CLI 2.8.1 · measured 2026-09-27 |
| 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.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
refusing to serve: no API secret was found | no secret in this shell or scheme | export BITHUMAN_API_SECRET=…, or set it in the scheme |
| cannot reach bitHuman to verify your credential in a Mac app | App Sandbox blocks outgoing connections | tick Outgoing Connections (Client) under App Sandbox |
create throws before engine ready | the model files are missing | run ./setup.sh from the example folder, so Model/ holds the three files |
The link step prints about ten unable to open object file warnings naming a folder on another machine | debug paths recorded in the published binary | harmless; the tool runs |
| The first run is slow | the engine is prepared for this Mac once | keep Model/staged/ between runs |
Reference
- Swift reference: every Swift and C entry point.
- macOS Expression 2 example and its source on GitHub.
- Changelog and Downloads & versions.
