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.
@@ -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())