|
|
|
|
|
import gradio as gr |
|
|
import os |
|
|
import shutil |
|
|
import uuid |
|
|
import subprocess |
|
|
from threading import Timer |
|
|
|
|
|
from gradio_motioncanvasplayer import MotionCanvasPlayer |
|
|
|
|
|
example_project_path = "https://prathje-gradio-motioncanvasplayer.hf.space/gradio_api/file=/home/user/app/public/project-3.17.2.js" |
|
|
|
|
|
loading_project_path = "" |
|
|
failed_project_path = "" |
|
|
|
|
|
BUILD_TIMEOUT = 60 |
|
|
|
|
|
gr.set_static_paths(paths=[os.path.join(os.path.dirname(__file__), "public")]) |
|
|
|
|
|
def get_local_path(project_id): |
|
|
return os.path.join(os.path.dirname(__file__), "public", "project-" + project_id + ".js") |
|
|
|
|
|
def get_public_path(project_id): |
|
|
return "/gradio_api/file=" + get_local_path(project_id) |
|
|
|
|
|
|
|
|
def build_project(code): |
|
|
|
|
|
yield loading_project_path, "Preparing project...", |
|
|
|
|
|
|
|
|
project_id = str(uuid.uuid4()) |
|
|
|
|
|
tmp_dir = os.path.join("/tmp/", project_id) |
|
|
|
|
|
shutil.copytree(os.environ['MC_PROJECT_DIR'], tmp_dir, dirs_exist_ok=False) |
|
|
acc_logs = "" |
|
|
|
|
|
try: |
|
|
yield loading_project_path, "Building project...", |
|
|
|
|
|
process = subprocess.Popen( |
|
|
"npm install && npm run build", |
|
|
stdout=subprocess.PIPE, |
|
|
stderr=subprocess.PIPE, |
|
|
text=True, |
|
|
shell=True, |
|
|
cwd=tmp_dir |
|
|
) |
|
|
|
|
|
timer = Timer(BUILD_TIMEOUT, process.kill) |
|
|
timer.start() |
|
|
|
|
|
while True: |
|
|
line = process.stdout.readline() |
|
|
if line: |
|
|
acc_logs += line.rstrip() + "\n" |
|
|
yield loading_project_path, acc_logs |
|
|
elif process.poll() is not None: |
|
|
break |
|
|
timer.cancel() |
|
|
|
|
|
|
|
|
stderr_output = process.stderr.read() |
|
|
if stderr_output: |
|
|
acc_logs += "\n" + "Error building project: " + stderr_output |
|
|
|
|
|
|
|
|
if process.returncode != 0: |
|
|
yield failed_project_path, acc_logs |
|
|
else: |
|
|
|
|
|
shutil.copy(os.path.join(tmp_dir, "dist", "project.js"), get_local_path(project_id)) |
|
|
yield get_public_path(project_id), acc_logs |
|
|
|
|
|
except Exception as e: |
|
|
yield failed_project_path, acc_logs + "\n" + "Error building project: " + str(e) |
|
|
|
|
|
finally: |
|
|
|
|
|
shutil.rmtree(tmp_dir) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with gr.Blocks() as demo: |
|
|
gr.Markdown("# Motion Canvas MCP Server") |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
gr.Markdown("## TS Input for scene.ts") |
|
|
code = gr.Code(language="typescript") |
|
|
submit = gr.Button("Build") |
|
|
logs = gr.Textbox(value="", label="Build Logs", interactive=False) |
|
|
with gr.Column(): |
|
|
gr.Markdown("## Preview") |
|
|
player = MotionCanvasPlayer(example_project_path, auto=True, quality=0.5, width=1920, height=1080, variables="{}") |
|
|
|
|
|
|
|
|
submit.click(build_project, inputs=[code], outputs=[player, logs], api_name="build_project") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch(mcp_server=True, strict_cors=False) |