gradio_mmd_widget
A Gradio custom component for rendering MMD motion data in the browser with Babylon.js and babylon-mmd.
Why this component?
- Play VMD motion files with a built-in MMD character
- Use it directly as a Gradio input or output component
- Great for demos, interactive storytelling, and lightweight 3D previews
Installation
pip install gradio_mmd_viewer
Quick start
import gradio as gr
from gradio_mmd_viewer import MMDViewer
with gr.Blocks() as demo:
gr.Markdown("## MMD Viewer")
viewer = MMDViewer(
value="asset/demo.vmd",
label="MMD Viewer",
scale=2,
min_width=800,
)
if __name__ == "__main__":
demo.launch()
User guide
Component parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
value |
str | None |
None |
VMD motion file path or URL |
model_url |
str | None |
None |
PMX/BPMX model file path or URL. If None, uses the built-in model |
pmx_zip |
str | None |
None |
Path to a ZIP containing a PMX model. Extracted automatically → model_url |
physics_enabled |
bool |
False |
Enable physics simulation for the model |
grey_mode |
bool |
False |
Render in flat grey (no textures) |
camera_position |
tuple[float, float, float] |
(0, 38, -25) |
Initial camera position (x, y, z) |
camera_rotation |
tuple[float, float] |
(0, 0) |
Initial camera rotation (alpha, beta) in radians |
audio_url |
str | None |
None |
Audio file path for animation sync |
1. Built-in model + VMD motion
The simplest usage — uses the built-in MMD model and plays a VMD motion:
import gradio as gr
from gradio_mmd_viewer import MMDViewer
with gr.Blocks() as demo:
viewer = MMDViewer(
value="asset/demo.vmd",
label="MMD Viewer",
scale=2,
min_width=800,
)
demo.launch()
2. Upload VMD motion dynamically
Use gr.File to let users upload .vmd files, then update the viewer via callback:
import gradio as gr
from gradio_mmd_viewer import MMDViewer
def load_motion(vmd_file):
if vmd_file is None:
return gr.update()
return gr.update(value=vmd_file)
with gr.Blocks() as demo:
vmd_input = gr.File(label="Upload VMD", file_types=[".vmd"])
viewer = MMDViewer(label="MMD Viewer", scale=2, min_width=800)
vmd_input.change(fn=load_motion, inputs=vmd_input, outputs=viewer)
demo.launch()
3. Upload PMX model via ZIP
Users can upload a ZIP containing a PMX model (with textures). The component extracts it and serves the model + textures automatically:
import gradio as gr
from gradio_mmd_viewer import MMDViewer, extract_pmx_zip
def load_model(pmx_zip):
if pmx_zip is None:
return gr.update()
model_url = extract_pmx_zip(pmx_zip)
return gr.update(model_url=model_url)
with gr.Blocks() as demo:
zip_input = gr.File(label="Upload PMX ZIP", file_types=[".zip"])
viewer = MMDViewer(label="MMD Viewer", scale=2, min_width=800)
zip_input.change(fn=load_model, inputs=zip_input, outputs=viewer)
demo.launch()
ZIP structure: The ZIP should contain a
.pmxfile and its texture directory (typicallyTex/). The extractor searches recursively for the first.pmxfile.
4. Full example: VMD + PMX ZIP + audio + camera control
import gradio as gr
from gradio_mmd_viewer import MMDViewer, extract_pmx_zip
def update_viewer(vmd_file, pmx_zip, audio_file, physics, grey, cam_x, cam_y, cam_z):
updates = {
"physics_enabled": physics,
"grey_mode": grey,
"camera_position": (cam_x, cam_y, cam_z),
}
if vmd_file is not None:
updates["value"] = vmd_file
if pmx_zip is not None:
updates["model_url"] = extract_pmx_zip(pmx_zip)
if audio_file is not None:
updates["audio_url"] = audio_file
return gr.update(**updates)
with gr.Blocks() as demo:
with gr.Row():
with gr.Column(scale=1):
vmd_input = gr.File(label="VMD Motion", file_types=[".vmd"])
pmx_input = gr.File(label="PMX Model (ZIP)", file_types=[".zip"])
audio_input = gr.File(label="Audio", file_types=[".mp3", ".wav", ".ogg"])
physics = gr.Checkbox(label="Physics", value=False)
grey = gr.Checkbox(label="Grey Mode", value=False)
cam_x = gr.Number(label="Camera X", value=0)
cam_y = gr.Number(label="Camera Y", value=38)
cam_z = gr.Number(label="Camera Z", value=-25)
btn = gr.Button("Load", variant="primary")
with gr.Column(scale=2):
viewer = MMDViewer(
label="3D Viewport",
scale=1,
min_width=600,
camera_position=(0, 38, -25),
)
btn.click(
fn=update_viewer,
inputs=[vmd_input, pmx_input, audio_input, physics, grey, cam_x, cam_y, cam_z],
outputs=viewer,
)
demo.launch()
Path handling
The component handles file paths automatically:
- Relative paths (e.g.
"asset/demo.vmd"): passed through as-is, served by Gradio's asset system - Absolute paths (e.g.
"C:/models/demo.vmd"): auto-converted to/gradio_api/file=...URLs viapostprocess() - ZIP extraction:
extract_pmx_zip()extracts to a temp cache directory, registers it viagr.set_static_paths(), and returns a servable/gradio_api/file=...URL
Note: When using
gr.update()in callbacks, absolute paths inmodel_urloraudio_urlare not auto-converted. Useextract_pmx_zip()for ZIP files — it returns the correct URL. For plain file paths, thepostprocess()hook handles conversion onvalue, but formodel_urlandaudio_urlyou should convert manually or pass them through the constructor.
Demo
Run the bundled demo with:
python demo/app.py
Development notes
Technical implementation details, architecture notes, build steps, and troubleshooting guidance are maintained in AGENTS.md.
Metadata
Release files for gradio_mmd_viewer 0.0.21
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 | |
|---|---|---|---|---|
| gradio_mmd_viewer-0.0.21.tar.gz | 5.5 MB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gradio_mmd_viewer-0.0.21-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 9.1 MB
Release files / gradio_mmd_viewer-0.0.21.tar.gz
| Download URL | gradio_mmd_viewer-0.0.21.tar.gz |
|---|---|
| Size | 5.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a2f8f25ab46fb2ddd8a9ff39c43ae5dd03599cec5cb7cb2fc31c1402fe7cf06c
|
|
BLAKE2b-256 checksum How to use checksums |
b530ab291a81b607afed50a41565702a0056ab28cdf18bb5cf93339b0a59ea5d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","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 / gradio_mmd_viewer-0.0.21-py3-none-any.whl
| Download URL | gradio_mmd_viewer-0.0.21-py3-none-any.whl |
|---|---|
| Size | 3.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f6f8b8bbf19c575215c64b7218802e5a4e485cdb521f0ded161c6a92da407902
|
|
BLAKE2b-256 checksum How to use checksums |
08d0f23874d5c99edab93fd5d962356ac08042147c6b9bd577ba6e9fecadbe71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","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 gradio_mmd_viewer 0.0.21
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.