Skip to main content

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 .pmx file and its texture directory (typically Tex/). The extractor searches recursively for the first .pmx file.

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 via postprocess()
  • ZIP extraction: extract_pmx_zip() extracts to a temp cache directory, registers it via gr.set_static_paths(), and returns a servable /gradio_api/file=... URL

Note: When using gr.update() in callbacks, absolute paths in model_url or audio_url are not auto-converted. Use extract_pmx_zip() for ZIP files — it returns the correct URL. For plain file paths, the postprocess() hook handles conversion on value, but for model_url and audio_url you 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)

Source distribution for gradio_mmd_viewer 0.0.21
File Size Uploaded Provenance
gradio_mmd_viewer-0.0.21.tar.gz 5.5 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for gradio_mmd_viewer 0.0.21
File Interpreter ABI Platform
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page