Skip to main content

Gradio custom component: 3D MMD model viewer powered by Babylon.js + babylon-mmd

Project description

gradio_mmd_widget

[!WARNING] Unewviewed AI code Unewviewed AI code still remains.

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gradio_mmd_viewer-0.0.11.tar.gz (5.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gradio_mmd_viewer-0.0.11-py3-none-any.whl (3.6 MB view details)

Uploaded Python 3

File details

Details for the file gradio_mmd_viewer-0.0.11.tar.gz.

File metadata

  • Download URL: gradio_mmd_viewer-0.0.11.tar.gz
  • Upload date:
  • Size: 5.5 MB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for gradio_mmd_viewer-0.0.11.tar.gz
Algorithm Hash digest
SHA256 775a02ade1054982e0f95db75d78d56e1b37a8b46bd0023ec7a2ec787c2b4da2
MD5 cbdc92993f86e511466d166a30be9945
BLAKE2b-256 5e801ae621d0970865c5c0a6e2a628c6b49cc511aaed564fdc498f1894685aee

See more details on using hashes here.

File details

Details for the file gradio_mmd_viewer-0.0.11-py3-none-any.whl.

File metadata

  • Download URL: gradio_mmd_viewer-0.0.11-py3-none-any.whl
  • Upload date:
  • Size: 3.6 MB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for gradio_mmd_viewer-0.0.11-py3-none-any.whl
Algorithm Hash digest
SHA256 e3b12023b27cc5f727151f7c2d3992cb4520a05114e4d330ef3c6411728e16ec
MD5 b54065582b701915995a3bd5be343b5e
BLAKE2b-256 662a348271bc9bf163369056c1c9516810ddd5e5aa8d9e8e258ee9b708393b1b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page