body-models-viser
Browser-side body model evaluation for viser.
Python owns the body model asset loaders and the prepare_identity() /
prepare_pose() calls. TypeScript owns the browser model lifecycle and WASM
buffers. Rust owns the stateless fallback kernels.
Usage
Skinned Body Models
Use add_body_model() for any body_models.SkinnedModel, including SMPL,
SMPL-X, MANO, FLAME, MHR, SOMA, SKEL, ANNY, and GarmentMeasurements.
import body_models_viser as bmv
import viser
from body_models.smpl.numpy import SMPL
server = viser.ViserServer()
model = SMPL(gender="neutral")
handle = bmv.add_body_model(server.scene, "/smpl", model, color=(173, 216, 230))
pose = handle.body_pose.copy()
pose[2, 0] = 0.5
handle.body_pose = pose
translation = handle.global_translation.copy()
translation[1] = 0.25
handle.set_transform(global_translation=translation)
shape = handle.shape.copy()
shape[0] = 1.0
handle.set_identity(shape=shape)
# Apply an additional scene-node transform after the body-model transform.
handle.position = (0.0, 0.0, 0.5)
handle.wxyz = (1.0, 0.0, 0.0, 0.0)
handle.visible = False
add_body_model() returns a generic handle with set_identity(...),
set_pose(...), set_transform(...), remove(), visible, position, wxyz,
global_rotation, global_translation, and the parameter properties declared
by the model. position and wxyz are scene-node deltas applied after the
body-model's global transform.
Pose correctives are disabled by default. Enable them explicitly when their visual fidelity is needed:
handle = bmv.add_body_model(
server.scene,
"/smpl",
model,
use_pose_correctives=True,
)
Correctives are evaluated in the client. Enabling them sends the model's dense or sparse corrective basis once per shared asset, quantized to signed 16-bit values, then sends only the small coefficient vector on each pose update. The basis is not retransmitted per body or frame. Browser clients receive this model data, so applications must ensure that doing so is compatible with the asset's license.
Skeletons
Use add_skeleton() for a standalone clickable skeleton. It takes joint
positions and a parent index for each joint.
import body_models_viser as bmv
pose = model.get_rest_pose()
skeleton = model.forward_skeleton(**pose)
joint_positions = skeleton[:, :3, 3]
handle = bmv.add_skeleton(
server.scene,
"/skeleton",
joint_positions,
model.parents,
joint_names=tuple(model.joint_names),
)
handle.visible = True
handle.joint_positions = joint_positions
Runtime
bmv.add_body_model(scene, name, model) does three things:
- Injects
body-models-viser.jsandbody-models-viser.wasm. - Sends shared topology and sparse skin weights once, followed by the current identity and pose as little-endian binary buffers.
- Returns a body model handle.
handle.set_identity(...) sends rest vertices and pose state.
handle.set_pose(...) sends only joint transforms and, when requested, pose
coefficients. handle.set_transform(...) sends only the global transform.
Without correctives, Rust applies sparse linear-blend skinning in WASM. With
correctives, a fused WebGPU kernel evaluates the corrective basis and skinning
together; the runtime falls back to WASM when WebGPU is unavailable. Both paths
preserve the basis representation exposed by body-models: dense bases remain
dense, while sparse bases remain sparse. The resulting vertex buffer is sent to
viser as a regular mesh message.
The browser protocol is model-agnostic. It consumes only the public
SkinningSpec and prepared identity and pose state from body-models 0.24.1
or newer.
viser compatibility
This package patches viser private internals (message serializer, websock
client state, and the client React tree) to inject its runtime. The supported
minimum is viser 1.1.0. When raising it, run uv run pytest and
uv run scripts/visualize_models.py against the new minimum, then check that
a browser renders the body model.
Development
Build the Rust crate:
cargo test
Build the browser bundle and WASM:
cd client
npm ci
npm test
The browser build requires a Rust toolchain with wasm32-unknown-unknown
installed, for example:
rustup target add wasm32-unknown-unknown
Run the small visualizer:
uv run --no-sync scripts/visualize_models.py
Check NumPy/WASM vertex parity for all supported models:
uv run scripts/check_model_parity.py
Stress ten full-resolution SMPL-X bodies at 60 FPS:
OPENBLAS_NUM_THREADS=1 uv run scripts/stress_smplx.py
OPENBLAS_NUM_THREADS=1 uv run scripts/stress_smplx.py --use-pose-correctives
In the browser console, BodyModelsViser.stats() reports render FPS, model
update FPS, the corrective backend, and corrective batch time.
Metadata
Release files for body-models-viser 0.7.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| body_models_viser-0.7.1.tar.gz | 61.2 kB | Without provenance | Details for body_models_viser-0.7.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| body_models_viser-0.7.1-py3-none-any.whl | Python 3 | none | any | Details for body_models_viser-0.7.1-py3-none-any.whl |
Total release size: 95.9 kB
Release files / body_models_viser-0.7.1.tar.gz
| Download URL | body_models_viser-0.7.1.tar.gz |
|---|---|
| Size | 61.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
469af8bfd8684d80bfc405316a13a8898932e0711f37dd95a9a4dd4bec2873a4
|
|
BLAKE2b-256 checksum How to use checksums |
cd06c853651501fbba846155757d1d63dbd6704325c5f80cedb4fcee10bb941e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / body_models_viser-0.7.1-py3-none-any.whl
| Download URL | body_models_viser-0.7.1-py3-none-any.whl |
|---|---|
| Size | 34.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a3720f8786fb665e228de3d89862a6fc3e6d10a9247e2044c6105c97b622da00
|
|
BLAKE2b-256 checksum How to use checksums |
9d877f80ff18e236b97b1e92a2e46625b716149af7a1a596b8616bae95db6cb1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for body-models-viser 0.7.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.