import gradio as gr import requests import tempfile import os def display_3d_model(url): """ Download a GLB file from a URL and return its path for Model3D. """ if not url: return None # Validate URL (basic check) if not (url.startswith("http://") or url.startswith("https://")): return None # Optional: check if URL ends with .glb (but not mandatory) # Download the file try: response = requests.get(url, stream=True, timeout=10) response.raise_for_status() content_type = response.headers.get("content-type", "") if "model/gltf-binary" not in content_type and not url.lower().endswith(".glb"): print(f"Warning: Unexpected content type {content_type} for {url}") # Save to a temporary file with tempfile.NamedTemporaryFile(suffix=".glb", delete=False) as tmp: for chunk in response.iter_content(chunk_size=8192): tmp.write(chunk) tmp_path = tmp.name return tmp_path except Exception as e: print(f"Error downloading model: {e}") return None def cleanup(file_path): """Delete the temporary file after use.""" if file_path and os.path.exists(file_path): os.unlink(file_path) # Gradio interface with gr.Blocks(title="GLB Viewer") as demo: gr.Markdown("## 🌐 GLB Model Viewer from URL") gr.Markdown("Enter a direct URL to a `.glb` (binary glTF) file. The model will be displayed below.") with gr.Row(): url_input = gr.Textbox( label="GLB File URL", placeholder="https://example.com/model.glb", scale=4 ) submit_btn = gr.Button("Load Model", variant="primary", scale=1) model_output = gr.Model3D( label="3D Model", clear_color=[0.2, 0.2, 0.2, 0.8], camera_position=(2, 2, 3), scale=1.0 ) # When the button is clicked, download and display submit_btn.click( fn=display_3d_model, inputs=url_input, outputs=model_output, queue=False ) # Optional: cleanup temporary files after session ends # Gradio doesn't have a built-in session end hook, but we can ignore # because files will be deleted when the space restarts or after a while. if __name__ == "__main__": demo.launch()