bithuman-cli 2.3.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bithuman_cli-2.3.5/PKG-INFO +73 -0
- bithuman_cli-2.3.5/README.md +40 -0
- bithuman_cli-2.3.5/pyproject.toml +113 -0
- bithuman_cli-2.3.5/scripts/build-cli-wheel-in-container.sh +240 -0
- bithuman_cli-2.3.5/src/bithuman_cli/__init__.py +22 -0
- bithuman_cli-2.3.5/src/bithuman_cli/__main__.py +12 -0
- bithuman_cli-2.3.5/src/bithuman_cli/_avatar_bridge.py +250 -0
- bithuman_cli-2.3.5/src/bithuman_cli/_entry.py +141 -0
- bithuman_cli-2.3.5/src/bithuman_cli/agent.py +463 -0
- bithuman_cli-2.3.5/src/bithuman_cli/local_plugins/__init__.py +35 -0
- bithuman_cli-2.3.5/src/bithuman_cli/local_plugins/_resample.py +17 -0
- bithuman_cli-2.3.5/src/bithuman_cli/local_plugins/_trace.py +86 -0
- bithuman_cli-2.3.5/src/bithuman_cli/local_plugins/llm.py +192 -0
- bithuman_cli-2.3.5/src/bithuman_cli/local_plugins/stt.py +140 -0
- bithuman_cli-2.3.5/src/bithuman_cli/local_plugins/tts.py +152 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: bithuman-cli
|
|
3
|
+
Version: 2.3.5
|
|
4
|
+
Summary: bitHuman CLI — `bithuman run model.imx` (live avatar) / `bithuman render` / `bithuman info` / `bithuman doctor`. Bundles the Rust CLI binary, the conversation brain, and the on-device plugins. Depends on the `bithuman` Python SDK.
|
|
5
|
+
Keywords: bithuman,avatar,essence,lipsync,cli,livekit
|
|
6
|
+
Author-Email: bitHuman <hello@bithuman.ai>
|
|
7
|
+
License: Commercial — see LICENSE file
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Operating System :: MacOS
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Multimedia
|
|
20
|
+
Project-URL: Homepage, https://bithuman.ai
|
|
21
|
+
Project-URL: Documentation, https://docs.bithuman.ai
|
|
22
|
+
Project-URL: Source, https://github.com/bithuman-product/bithuman-sdk
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: bithuman<2.4,>=2.3.2
|
|
25
|
+
Requires-Dist: livekit-agents[openai]==1.5.12
|
|
26
|
+
Provides-Extra: local
|
|
27
|
+
Requires-Dist: livekit-agents[silero]~=1.5; extra == "local"
|
|
28
|
+
Requires-Dist: supertonic>=1.3; extra == "local"
|
|
29
|
+
Requires-Dist: pywhispercpp>=1.3; extra == "local"
|
|
30
|
+
Requires-Dist: llama-cpp-python>=0.3; extra == "local"
|
|
31
|
+
Requires-Dist: soxr>=0.5; extra == "local"
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# bithuman-cli
|
|
35
|
+
|
|
36
|
+
The bitHuman CLI tool — `bithuman run`, `bithuman render`,
|
|
37
|
+
`bithuman doctor`, `bithuman info`, `bithuman list`, `bithuman pull`.
|
|
38
|
+
|
|
39
|
+
Bundles:
|
|
40
|
+
|
|
41
|
+
- The cross-platform Rust CLI binary (`bithuman_cli/_bin/bithuman`)
|
|
42
|
+
- The conversation brain (`agent.py`) spawned by `bithuman run`
|
|
43
|
+
- On-device brain plugins (whisper.cpp + llama.cpp + Supertonic) under
|
|
44
|
+
the `[local]` extra
|
|
45
|
+
- The `livekit-server` Go SFU child that the CLI spawns to host the
|
|
46
|
+
in-browser talk loop
|
|
47
|
+
|
|
48
|
+
Depends on the [`bithuman`](https://pypi.org/project/bithuman/) Python
|
|
49
|
+
SDK for the in-process avatar runtime.
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
pip install bithuman-cli # cloud brain (OpenAI Realtime)
|
|
55
|
+
pip install 'bithuman-cli[local]' # also bundles on-device brain
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
For non-Python install paths (the same Rust binary, no Python needed):
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
brew install bithuman # macOS
|
|
62
|
+
curl -fsSL https://install.bithuman.ai | sh # macOS / Linux
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
bithuman run model.imx # live avatar via LiveKit, browser-to-talk
|
|
69
|
+
bithuman render model.imx -a in.wav -o out.mp4 # offline mp4
|
|
70
|
+
bithuman doctor # check install + env + brain config
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
See [docs.bithuman.ai](https://docs.bithuman.ai) for the full reference.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# bithuman-cli
|
|
2
|
+
|
|
3
|
+
The bitHuman CLI tool — `bithuman run`, `bithuman render`,
|
|
4
|
+
`bithuman doctor`, `bithuman info`, `bithuman list`, `bithuman pull`.
|
|
5
|
+
|
|
6
|
+
Bundles:
|
|
7
|
+
|
|
8
|
+
- The cross-platform Rust CLI binary (`bithuman_cli/_bin/bithuman`)
|
|
9
|
+
- The conversation brain (`agent.py`) spawned by `bithuman run`
|
|
10
|
+
- On-device brain plugins (whisper.cpp + llama.cpp + Supertonic) under
|
|
11
|
+
the `[local]` extra
|
|
12
|
+
- The `livekit-server` Go SFU child that the CLI spawns to host the
|
|
13
|
+
in-browser talk loop
|
|
14
|
+
|
|
15
|
+
Depends on the [`bithuman`](https://pypi.org/project/bithuman/) Python
|
|
16
|
+
SDK for the in-process avatar runtime.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
pip install bithuman-cli # cloud brain (OpenAI Realtime)
|
|
22
|
+
pip install 'bithuman-cli[local]' # also bundles on-device brain
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
For non-Python install paths (the same Rust binary, no Python needed):
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
brew install bithuman # macOS
|
|
29
|
+
curl -fsSL https://install.bithuman.ai | sh # macOS / Linux
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
bithuman run model.imx # live avatar via LiveKit, browser-to-talk
|
|
36
|
+
bithuman render model.imx -a in.wav -o out.mp4 # offline mp4
|
|
37
|
+
bithuman doctor # check install + env + brain config
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
See [docs.bithuman.ai](https://docs.bithuman.ai) for the full reference.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# bithuman-cli — the bitHuman CLI wheel.
|
|
2
|
+
#
|
|
3
|
+
# Phase B split (2026-05-28): the CLI surface (`bithuman run / render /
|
|
4
|
+
# doctor`) was extracted from the unified `bithuman` PyPI package into
|
|
5
|
+
# this dedicated wheel. The `bithuman` console script now lives here;
|
|
6
|
+
# the `bithuman` PyPI package is the slim Python SDK
|
|
7
|
+
# (`from bithuman import AsyncBithuman`) that this wheel depends on.
|
|
8
|
+
#
|
|
9
|
+
# What this wheel ships:
|
|
10
|
+
# bithuman_cli/_bin/bithuman — Rust CLI binary (per-platform)
|
|
11
|
+
# bithuman_cli/_bin/lib/*.dylib|so — vendored native deps
|
|
12
|
+
# bithuman_cli/_bin/livekit-server — Go SFU child the CLI spawns
|
|
13
|
+
# bithuman_cli/_entry.py — Python shim, exec's _bin/bithuman
|
|
14
|
+
# bithuman_cli/agent.py — conversation brain (livekit-agents)
|
|
15
|
+
# bithuman_cli/local_plugins/ — on-device STT/LLM/TTS (under [local])
|
|
16
|
+
#
|
|
17
|
+
# pure-Python wheel — no C extension. The Rust binary is staged into
|
|
18
|
+
# bithuman_cli/_bin/ at wheel-build time by the CI workflow; scikit-build-
|
|
19
|
+
# core copies it (and any tree-under-src content) into the wheel
|
|
20
|
+
# automatically via the `wheel.packages` config below.
|
|
21
|
+
|
|
22
|
+
[build-system]
|
|
23
|
+
requires = ["scikit-build-core>=0.10"]
|
|
24
|
+
build-backend = "scikit_build_core.build"
|
|
25
|
+
|
|
26
|
+
[project]
|
|
27
|
+
name = "bithuman-cli"
|
|
28
|
+
version = "2.3.5"
|
|
29
|
+
description = "bitHuman CLI — `bithuman run model.imx` (live avatar) / `bithuman render` / `bithuman info` / `bithuman doctor`. Bundles the Rust CLI binary, the conversation brain, and the on-device plugins. Depends on the `bithuman` Python SDK."
|
|
30
|
+
readme = "README.md"
|
|
31
|
+
requires-python = ">=3.10"
|
|
32
|
+
authors = [{ name = "bitHuman", email = "hello@bithuman.ai" }]
|
|
33
|
+
license = { text = "Commercial — see LICENSE file" }
|
|
34
|
+
keywords = ["bithuman", "avatar", "essence", "lipsync", "cli", "livekit"]
|
|
35
|
+
classifiers = [
|
|
36
|
+
"Development Status :: 4 - Beta",
|
|
37
|
+
"Intended Audience :: Developers",
|
|
38
|
+
"Operating System :: MacOS",
|
|
39
|
+
"Operating System :: POSIX :: Linux",
|
|
40
|
+
"Programming Language :: Python",
|
|
41
|
+
"Programming Language :: Python :: 3",
|
|
42
|
+
"Programming Language :: Python :: 3.10",
|
|
43
|
+
"Programming Language :: Python :: 3.11",
|
|
44
|
+
"Programming Language :: Python :: 3.12",
|
|
45
|
+
"Programming Language :: Python :: 3.13",
|
|
46
|
+
"Programming Language :: Python :: 3.14",
|
|
47
|
+
"Topic :: Multimedia",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
# Phase B split: the CLI depends on the slim `bithuman` SDK wheel for the
|
|
51
|
+
# in-process avatar runtime. The slim SDK is on its own (decoupled)
|
|
52
|
+
# semver track — it does NOT move in lockstep with the CLI version — so
|
|
53
|
+
# pin to a compatible RANGE (>= the version this CLI was built against,
|
|
54
|
+
# < the next minor), not an exact match that goes stale the moment the
|
|
55
|
+
# SDK ships a patch. (It did: the CLI was 2.3.0 but the slim SDK is now
|
|
56
|
+
# 2.3.2, so `==2.3.0` pulled a stale SDK.)
|
|
57
|
+
#
|
|
58
|
+
# `livekit-plugins-bithuman` is intentionally NOT a runtime dep. Its
|
|
59
|
+
# `bithuman<1.12` pin would block our 2.x SDK install. The cloud-mode
|
|
60
|
+
# `AvatarSession` we use is reimplemented inline in
|
|
61
|
+
# `bithuman_cli/_avatar_bridge.py` on top of livekit-agents primitives
|
|
62
|
+
# (`AvatarSession` base + `DataStreamAudioOutput` + `ATTRIBUTE_PUBLISH_ON_BEHALF`).
|
|
63
|
+
# Users who want the in-process `BITHUMAN_LOCAL_AVATAR=1` path can
|
|
64
|
+
# `pip install livekit-plugins-bithuman` themselves — the import is
|
|
65
|
+
# lazy in `agent.py`. Sunset: drop `_avatar_bridge.py` and re-add the
|
|
66
|
+
# dep once upstream relaxes `bithuman<1.12`.
|
|
67
|
+
dependencies = [
|
|
68
|
+
"bithuman>=2.3.2,<2.4",
|
|
69
|
+
"livekit-agents[openai]==1.5.12",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
# Fully on-device brain for `BITHUMAN_LOCAL=1 bithuman run` — no API
|
|
73
|
+
# keys. whisper.cpp STT, llama.cpp LLM, Supertonic TTS, all in-process
|
|
74
|
+
# and mobile-portable (same C++ cores run on iOS/Android). Models
|
|
75
|
+
# auto-download from HuggingFace to ~/.cache/{huggingface,supertonic}
|
|
76
|
+
# on first use.
|
|
77
|
+
[project.optional-dependencies]
|
|
78
|
+
local = [
|
|
79
|
+
"livekit-agents[silero]~=1.5",
|
|
80
|
+
"supertonic>=1.3",
|
|
81
|
+
"pywhispercpp>=1.3",
|
|
82
|
+
"llama-cpp-python>=0.3",
|
|
83
|
+
"soxr>=0.5",
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
[project.scripts]
|
|
87
|
+
# The `bithuman` console script lives here in 2.2.7+. The entry shim
|
|
88
|
+
# (`bithuman_cli._entry:main`) locates `_bin/bithuman` (the Rust binary
|
|
89
|
+
# staged at wheel-build time) and `execvpe`s into it, setting env vars
|
|
90
|
+
# so the Rust binary's `embedded_agent_worker` finds this wheel's
|
|
91
|
+
# `agent.py` + the venv's Python interpreter.
|
|
92
|
+
bithuman = "bithuman_cli._entry:main"
|
|
93
|
+
|
|
94
|
+
[project.urls]
|
|
95
|
+
Homepage = "https://bithuman.ai"
|
|
96
|
+
Documentation = "https://docs.bithuman.ai"
|
|
97
|
+
Source = "https://github.com/bithuman-product/bithuman-sdk"
|
|
98
|
+
|
|
99
|
+
[tool.scikit-build]
|
|
100
|
+
minimum-version = "0.10"
|
|
101
|
+
build-dir = "build/{wheel_tag}"
|
|
102
|
+
# Pure-Python wheel — no CMake C extension to build. scikit-build-core
|
|
103
|
+
# still copies the ENTIRE package directory tree (every file, not just
|
|
104
|
+
# *.py) into the wheel, so the staged `_bin/bithuman` + dylib closure
|
|
105
|
+
# + livekit-server + agent.py + local_plugins/ all ride along
|
|
106
|
+
# automatically.
|
|
107
|
+
wheel.packages = ["src/bithuman_cli"]
|
|
108
|
+
# Explicit: never exclude anything from the copied package tree.
|
|
109
|
+
wheel.exclude = []
|
|
110
|
+
# Pure-Python wheel: no CMakeLists.txt to run. Without this, scikit-
|
|
111
|
+
# build-core 0.10+ unconditionally tries to invoke CMake and fails the
|
|
112
|
+
# build with "source directory does not contain CMakeLists.txt".
|
|
113
|
+
wheel.cmake = false
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Build the `bithuman-cli` wheel inside the libessence/manylinux-x86_64
|
|
3
|
+
# (or aarch64) image. Phase B split (2026-05-28): produces the slim,
|
|
4
|
+
# pure-Python `bithuman-cli` wheel; the C-extension `bithuman` SDK
|
|
5
|
+
# wheel is built by the SDK repo's
|
|
6
|
+
# `bithuman-sdk/sdks/python/scripts/build-wheel-in-container.sh`.
|
|
7
|
+
#
|
|
8
|
+
# Wave 11 in-container layout (the caller — cli/scripts/build-linux.sh
|
|
9
|
+
# or the cli-release workflow — hardlinks both checkouts under /src to
|
|
10
|
+
# satisfy these legacy paths):
|
|
11
|
+
# /src/cpp — libessence cmake src (bithuman-sdk/engine)
|
|
12
|
+
# /src/cpp/bindings/rust — cargo workspace (bithuman-apps/cli)
|
|
13
|
+
# /src/cpp/bindings/python — SDK Python (bithuman-sdk/sdks/python)
|
|
14
|
+
# /src/cpp/bindings/python-cli — this wheel src (bithuman-apps/cli/wheel)
|
|
15
|
+
#
|
|
16
|
+
# Env:
|
|
17
|
+
# PYTAG cp311 (default) / cp310 / cp312 / cp313 / cp314
|
|
18
|
+
# ARCH_INSIDE x86_64 (default) / aarch64
|
|
19
|
+
#
|
|
20
|
+
# What this produces:
|
|
21
|
+
# cli/wheel/dist/bithuman_cli-<ver>-*-manylinux_2_28_*.whl
|
|
22
|
+
#
|
|
23
|
+
# Wheel contents (staged BEFORE `python -m build`):
|
|
24
|
+
# bithuman_cli/_bin/bithuman — Rust CLI binary
|
|
25
|
+
# bithuman_cli/_bin/lib/*.so* — vendored ldd closure
|
|
26
|
+
# bithuman_cli/_bin/livekit-server — Go SFU child
|
|
27
|
+
# bithuman_cli/_entry.py — entry shim
|
|
28
|
+
# bithuman_cli/agent.py — embedded conversation brain
|
|
29
|
+
# bithuman_cli/local_plugins/ — on-device STT/LLM/TTS
|
|
30
|
+
#
|
|
31
|
+
# Pure-Python wheel — no auditwheel repair needed (the binary is
|
|
32
|
+
# already self-contained: cargo + RPATH=$ORIGIN/lib). We DO NOT run
|
|
33
|
+
# auditwheel here: it would reject the Rust binary's newer-than-
|
|
34
|
+
# manylinux_2_28 glibc symbol versions.
|
|
35
|
+
|
|
36
|
+
set -euo pipefail
|
|
37
|
+
|
|
38
|
+
PYTAG="${PYTAG:-cp311}"
|
|
39
|
+
ARCH_INSIDE="${ARCH_INSIDE:-x86_64}"
|
|
40
|
+
|
|
41
|
+
echo "== bithuman-cli wheel build =="
|
|
42
|
+
echo " python: $PYTAG"
|
|
43
|
+
echo " arch: $ARCH_INSIDE"
|
|
44
|
+
echo " gcc: $(gcc --version | head -1)"
|
|
45
|
+
|
|
46
|
+
# Phase 4b §3.3 rationale (carried over): the cmake/cargo path that
|
|
47
|
+
# builds libessence.a (for the binary's link) must use the same Rust
|
|
48
|
+
# toolchain as the binary's cargo invocation, or two libstd copies
|
|
49
|
+
# end up in the link → duplicate-symbol error from rust-lld. Refresh
|
|
50
|
+
# the toolchain BEFORE cmake.
|
|
51
|
+
export PATH="/root/.cargo/bin:${PATH}"
|
|
52
|
+
if ! ldconfig -p | grep -q libclang.so; then
|
|
53
|
+
echo "::error::libclang not in the image — rebuild the manylinux container"
|
|
54
|
+
echo " docker build --platform linux/${ARCH_INSIDE/x86_64/amd64} -t libessence/manylinux-${ARCH_INSIDE}:0.1 -f bithuman-sdk/sdks/python/scripts/Dockerfile.manylinux-${ARCH_INSIDE} bithuman-sdk/sdks/python/scripts/"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
echo "==> rustup update stable (pre-cmake — keep one libstd across all cargo invocations)"
|
|
58
|
+
rustup update stable 2>&1 | tail -3
|
|
59
|
+
rustup default stable
|
|
60
|
+
|
|
61
|
+
cd /src/cpp
|
|
62
|
+
BUILD_LINUX_DIR="build-linux-${ARCH_INSIDE}"
|
|
63
|
+
# 1. Build libessence_core for Linux — same as the SDK-wheel container
|
|
64
|
+
# script. The Rust bithuman-cli binary links libbithuman_imx.a
|
|
65
|
+
# against libessence.a.
|
|
66
|
+
cmake -GNinja -B "$BUILD_LINUX_DIR" -S . -DCMAKE_BUILD_TYPE=Release \
|
|
67
|
+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
|
|
68
|
+
-DONNX_RUNTIME_DIR=/opt/bes-deps \
|
|
69
|
+
-DCMAKE_PREFIX_PATH="/opt/bes-deps;/usr/local"
|
|
70
|
+
cmake --build "$BUILD_LINUX_DIR" --target essence -j"$(nproc)"
|
|
71
|
+
ls -la "$BUILD_LINUX_DIR/libessence.a"
|
|
72
|
+
|
|
73
|
+
# 2. Stage the Rust CLI binary + dylib closure + livekit-server into the
|
|
74
|
+
# bithuman-cli wheel source tree.
|
|
75
|
+
echo
|
|
76
|
+
echo "== STAGE BUNDLED CLI =="
|
|
77
|
+
echo " cargo: $(cargo --version)"
|
|
78
|
+
echo " rustc: $(rustc --version)"
|
|
79
|
+
|
|
80
|
+
export ESSENCE_BUILD_DIR="/src/cpp/${BUILD_LINUX_DIR}"
|
|
81
|
+
export CARGO_TARGET_DIR="/src/cpp/bindings/rust/target-linux-${ARCH_INSIDE}"
|
|
82
|
+
|
|
83
|
+
# bindgen + espeak-rs-sys: see build-linux-in-container.sh for the
|
|
84
|
+
# long rationale on libclang path + pthread linker flag seeding.
|
|
85
|
+
export LIBCLANG_PATH="${LIBCLANG_PATH:-/usr/lib64}"
|
|
86
|
+
export LDFLAGS="${LDFLAGS:-} -pthread"
|
|
87
|
+
export CFLAGS="${CFLAGS:-} -pthread"
|
|
88
|
+
export CXXFLAGS="${CXXFLAGS:-} -pthread"
|
|
89
|
+
|
|
90
|
+
LINK_RPATHS=(
|
|
91
|
+
"-C" "link-arg=-Wl,-rpath,/opt/bes-deps/lib"
|
|
92
|
+
"-C" "link-arg=-Wl,-rpath,/opt/bes-deps/lib64"
|
|
93
|
+
"-C" "link-arg=-Wl,-rpath,/usr/local/lib"
|
|
94
|
+
"-C" "link-arg=-Wl,-rpath,/usr/local/lib64"
|
|
95
|
+
"-C" "link-arg=-Wl,-rpath,/usr/lib64"
|
|
96
|
+
"-C" "link-arg=-Wl,-rpath,\$ORIGIN"
|
|
97
|
+
"-C" "link-arg=-Wl,-rpath,\$ORIGIN/lib"
|
|
98
|
+
"-C" "link-arg=-static-libgcc"
|
|
99
|
+
)
|
|
100
|
+
export RUSTFLAGS="${RUSTFLAGS:-} ${LINK_RPATHS[*]}"
|
|
101
|
+
|
|
102
|
+
cd /src/cpp/bindings/rust
|
|
103
|
+
cargo clean -p espeak-rs-sys 2>/dev/null || true
|
|
104
|
+
# Phase A: the binary crate is `bithuman-cli` (was `bithuman` pre-rename).
|
|
105
|
+
cargo build --release -p bithuman-cli
|
|
106
|
+
|
|
107
|
+
BIN_SRC="$CARGO_TARGET_DIR/release/bithuman"
|
|
108
|
+
[ -f "$BIN_SRC" ] || { echo "cargo built no binary at $BIN_SRC"; exit 1; }
|
|
109
|
+
strip --strip-all "$BIN_SRC" 2>/dev/null || true
|
|
110
|
+
|
|
111
|
+
# Stage _bin/ into the CLI wheel package.
|
|
112
|
+
CLI_PKG_DIR="/src/cpp/bindings/python-cli/src/bithuman_cli"
|
|
113
|
+
BIN_STAGE="$CLI_PKG_DIR/_bin"
|
|
114
|
+
rm -rf "$BIN_STAGE/lib"
|
|
115
|
+
mkdir -p "$BIN_STAGE/lib"
|
|
116
|
+
cp "$BIN_SRC" "$BIN_STAGE/bithuman"
|
|
117
|
+
chmod +x "$BIN_STAGE/bithuman"
|
|
118
|
+
|
|
119
|
+
# Recursive ldd closure — auditwheel manylinux_2_28 baseline.
|
|
120
|
+
BASELINE_SONAMES=" libc.so.6 libm.so.6 libdl.so.2 librt.so.1 libpthread.so.0 libgcc_s.so.1 libstdc++.so.6 libgomp.so.1 libz.so.1 ld-linux-x86-64.so.2 ld-linux-aarch64.so.1 "
|
|
121
|
+
is_baseline() { case " $BASELINE_SONAMES " in *" $1 "*) return 0 ;; *) return 1 ;; esac; }
|
|
122
|
+
declare -A SEEN
|
|
123
|
+
_collect_iter() {
|
|
124
|
+
while read -r line; do
|
|
125
|
+
local soname path
|
|
126
|
+
if [[ "$line" == *"=>"* ]]; then
|
|
127
|
+
soname="${line%% =>*}"; soname="${soname##*[[:space:]]}"
|
|
128
|
+
path="${line#*=> }"; path="${path%% (0x*}"; path="${path%% }"
|
|
129
|
+
else
|
|
130
|
+
path="${line%% (0x*}"; path="$(echo "$path" | xargs 2>/dev/null || true)"
|
|
131
|
+
soname="$(basename "$path" 2>/dev/null || true)"
|
|
132
|
+
fi
|
|
133
|
+
[[ -z "${path:-}" || ! -f "$path" ]] && continue
|
|
134
|
+
case "$soname" in linux-vdso.so*|ld-linux*) continue ;; esac
|
|
135
|
+
is_baseline "$soname" && continue
|
|
136
|
+
if [[ -z "${SEEN[$soname]:-}" ]]; then
|
|
137
|
+
SEEN[$soname]=1
|
|
138
|
+
cp -L "$path" "$BIN_STAGE/lib/$soname"
|
|
139
|
+
chmod u+w "$BIN_STAGE/lib/$soname"
|
|
140
|
+
_collect_iter < <(ldd "$path" 2>/dev/null || true)
|
|
141
|
+
fi
|
|
142
|
+
done
|
|
143
|
+
}
|
|
144
|
+
_collect_iter < <(ldd "$BIN_SRC" 2>/dev/null)
|
|
145
|
+
BUNDLED_COUNT="$(ls -1 "$BIN_STAGE/lib" | wc -l | tr -d ' ')"
|
|
146
|
+
echo " bundled $BUNDLED_COUNT shared libs into _bin/lib/"
|
|
147
|
+
[[ "$BUNDLED_COUNT" -lt 5 ]] && { echo "::error::suspiciously small dep closure ($BUNDLED_COUNT)"; exit 1; }
|
|
148
|
+
|
|
149
|
+
patchelf --set-rpath '$ORIGIN/lib' "$BIN_STAGE/bithuman"
|
|
150
|
+
for so in "$BIN_STAGE/lib"/*; do
|
|
151
|
+
patchelf --set-rpath '$ORIGIN' "$so" 2>/dev/null || true
|
|
152
|
+
done
|
|
153
|
+
|
|
154
|
+
# audio_encoder.onnx — RUNTIME asset, sourced from the SDK wheel tree.
|
|
155
|
+
cp /src/cpp/bindings/python/src/bithuman/lib/audio_encoder.onnx "$BIN_STAGE/lib/audio_encoder.onnx"
|
|
156
|
+
|
|
157
|
+
# livekit-server (Go SFU). Same source-priority logic as the SDK wheel
|
|
158
|
+
# script (see history in bithuman-sdk/sdks/python/scripts/build-wheel-
|
|
159
|
+
# in-container.sh).
|
|
160
|
+
LK_VER="${BITHUMAN_LIVEKIT_SERVER_VER:-1.12.0}"
|
|
161
|
+
case "$ARCH_INSIDE" in
|
|
162
|
+
x86_64) LK_ARCH=linux_amd64 ;;
|
|
163
|
+
aarch64) LK_ARCH=linux_arm64 ;;
|
|
164
|
+
*) echo "::error::unknown ARCH_INSIDE=$ARCH_INSIDE"; exit 1 ;;
|
|
165
|
+
esac
|
|
166
|
+
if [[ -n "${BITHUMAN_LIVEKIT_SERVER_URL:-}" ]]; then
|
|
167
|
+
echo " fetching livekit-server from override URL: $BITHUMAN_LIVEKIT_SERVER_URL"
|
|
168
|
+
curl -fsSL "$BITHUMAN_LIVEKIT_SERVER_URL" -o /tmp/livekit.tar.gz
|
|
169
|
+
elif [[ "${BITHUMAN_LIVEKIT_SERVER_MIRROR:-0}" == "1" ]]; then
|
|
170
|
+
echo " fetching livekit-server v${LK_VER} ${LK_ARCH} from bithuman mirror"
|
|
171
|
+
if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
|
|
172
|
+
mkdir -p /tmp/lk-mirror && cd /tmp/lk-mirror
|
|
173
|
+
gh release download "livekit-server-mirror-v${LK_VER}" \
|
|
174
|
+
--repo bithuman-product/bithuman-sdk \
|
|
175
|
+
--pattern "livekit_${LK_VER}_${LK_ARCH}.tar.gz" \
|
|
176
|
+
--clobber
|
|
177
|
+
mv "livekit_${LK_VER}_${LK_ARCH}.tar.gz" /tmp/livekit.tar.gz
|
|
178
|
+
cd - >/dev/null
|
|
179
|
+
else
|
|
180
|
+
echo "::error::mirror fetch needs gh-cli (preferred) or GH_TOKEN/GITHUB_TOKEN env" >&2
|
|
181
|
+
echo " set BITHUMAN_LIVEKIT_SERVER_URL to bypass, or unset BITHUMAN_LIVEKIT_SERVER_MIRROR." >&2
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
else
|
|
185
|
+
LK_URL="https://github.com/livekit/livekit/releases/download/v${LK_VER}/livekit_${LK_VER}_${LK_ARCH}.tar.gz"
|
|
186
|
+
echo " fetching livekit-server v${LK_VER} ${LK_ARCH} from upstream"
|
|
187
|
+
curl -fsSL "$LK_URL" -o /tmp/livekit.tar.gz
|
|
188
|
+
fi
|
|
189
|
+
mkdir -p /tmp/lk-extract
|
|
190
|
+
tar -xzf /tmp/livekit.tar.gz -C /tmp/lk-extract
|
|
191
|
+
LK_BIN="$(find /tmp/lk-extract -name livekit-server -type f -executable | head -1)"
|
|
192
|
+
[ -n "$LK_BIN" ] || { echo "::error::livekit-server not in archive"; ls -la /tmp/lk-extract; exit 1; }
|
|
193
|
+
cp "$LK_BIN" "$BIN_STAGE/livekit-server"
|
|
194
|
+
chmod +x "$BIN_STAGE/livekit-server"
|
|
195
|
+
rm -rf /tmp/lk-extract /tmp/livekit.tar.gz
|
|
196
|
+
|
|
197
|
+
# 3. Build the wheel — pure Python, no scikit-build CMake step.
|
|
198
|
+
cd /src/cpp/bindings/python-cli
|
|
199
|
+
PY="/opt/python/${PYTAG}-${PYTAG}/bin/python"
|
|
200
|
+
"$PY" -m pip install --quiet --upgrade pip build scikit-build-core
|
|
201
|
+
mkdir -p dist
|
|
202
|
+
rm -f dist/bithuman_cli-*-${PYTAG}-${PYTAG}-*${ARCH_INSIDE}*.whl
|
|
203
|
+
"$PY" -m build --wheel --outdir dist/
|
|
204
|
+
|
|
205
|
+
WHL=$(ls dist/bithuman_cli-*-${PYTAG}-${PYTAG}-linux_${ARCH_INSIDE}.whl 2>/dev/null | head -1)
|
|
206
|
+
[ -n "$WHL" ] || { echo "no raw wheel produced"; ls dist/; exit 1; }
|
|
207
|
+
echo
|
|
208
|
+
echo "== raw wheel =="
|
|
209
|
+
ls -la "$WHL"
|
|
210
|
+
|
|
211
|
+
# 4. Rename to manylinux_2_28 (no auditwheel — the binary is already
|
|
212
|
+
# self-contained, and auditwheel would reject the rust-lld glibc
|
|
213
|
+
# symbol versions). Just relabel the platform tag.
|
|
214
|
+
REPAIRED="${WHL/linux_${ARCH_INSIDE}/manylinux_2_28_${ARCH_INSIDE}}"
|
|
215
|
+
mv "$WHL" "$REPAIRED"
|
|
216
|
+
echo " -> $REPAIRED"
|
|
217
|
+
ls -lh "$REPAIRED"
|
|
218
|
+
|
|
219
|
+
# 5. Smoke test inside a clean venv.
|
|
220
|
+
echo
|
|
221
|
+
echo "== smoke test =="
|
|
222
|
+
"$PY" -m venv /tmp/smoke-cli
|
|
223
|
+
# bithuman-cli depends on bithuman (the SDK wheel). The SDK wheel
|
|
224
|
+
# might or might not be available locally — try a sibling dist/, else
|
|
225
|
+
# just install bithuman-cli on its own (pip will resolve the dep from
|
|
226
|
+
# the local index if present or from PyPI).
|
|
227
|
+
SDK_DIST="/src/cpp/bindings/python/dist"
|
|
228
|
+
if ls "$SDK_DIST"/bithuman-*-${PYTAG}-${PYTAG}-manylinux_2_28_${ARCH_INSIDE}.whl >/dev/null 2>&1; then
|
|
229
|
+
/tmp/smoke-cli/bin/pip install --quiet \
|
|
230
|
+
"$SDK_DIST"/bithuman-*-${PYTAG}-${PYTAG}-manylinux_2_28_${ARCH_INSIDE}.whl \
|
|
231
|
+
"$REPAIRED"
|
|
232
|
+
else
|
|
233
|
+
echo " (no sibling SDK wheel — installing bithuman-cli alone; bithuman dep resolved from PyPI/index)"
|
|
234
|
+
/tmp/smoke-cli/bin/pip install --quiet "$REPAIRED"
|
|
235
|
+
fi
|
|
236
|
+
/tmp/smoke-cli/bin/bithuman --version
|
|
237
|
+
/tmp/smoke-cli/bin/bithuman --help | head -5
|
|
238
|
+
|
|
239
|
+
echo
|
|
240
|
+
echo "DONE — wheel at: $REPAIRED"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""bithuman-cli — the bitHuman command-line tool.
|
|
2
|
+
|
|
3
|
+
Internal package. Users interact via the `bithuman` console script
|
|
4
|
+
installed by this wheel:
|
|
5
|
+
|
|
6
|
+
bithuman run model.imx # live avatar
|
|
7
|
+
bithuman render -a in.wav -o out.mp4
|
|
8
|
+
bithuman doctor
|
|
9
|
+
|
|
10
|
+
Programmatic invocation is also supported:
|
|
11
|
+
|
|
12
|
+
python -m bithuman_cli # equivalent to running `bithuman`
|
|
13
|
+
|
|
14
|
+
For embedding the bitHuman runtime in a Python application, use the
|
|
15
|
+
bitHuman SDK directly (this wheel depends on it):
|
|
16
|
+
|
|
17
|
+
from bithuman import AsyncBithuman
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
# Keep aligned with cpp/bindings/python-cli/pyproject.toml.
|
|
22
|
+
__version__ = "2.3.0"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""bithuman-cli module entry: `python -m bithuman_cli <command>`.
|
|
2
|
+
|
|
3
|
+
Equivalent to running the `bithuman` console script installed by this
|
|
4
|
+
wheel — both call `bithuman_cli._entry:main`, which locates the
|
|
5
|
+
bundled Rust binary at `bithuman_cli/_bin/bithuman` and `execvpe`s
|
|
6
|
+
into it.
|
|
7
|
+
"""
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
from ._entry import main
|
|
11
|
+
|
|
12
|
+
sys.exit(main())
|