Spaces:
Running
Running
| """ | |
| FastAPI server for the OpenX Rerun Viewer HF Space. | |
| Runs the selection UI and serves .rrd files. | |
| When running locally, also starts a local Rerun web viewer to avoid mixed-content issues. | |
| """ | |
| import json | |
| import os | |
| import subprocess | |
| import sys | |
| import time | |
| from pathlib import Path | |
| from fastapi import FastAPI | |
| from fastapi.responses import FileResponse, HTMLResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.middleware.cors import CORSMiddleware | |
| app = FastAPI(title="OpenX Rerun Viewer") | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["GET", "HEAD", "OPTIONS"], | |
| allow_headers=["*"], | |
| expose_headers=[ | |
| "Content-Length", "Content-Type", "Accept-Ranges", | |
| "Cross-Origin-Resource-Policy", | |
| ], | |
| ) | |
| DATA_DIR = Path(__file__).parent / "data" | |
| MANIFEST_PATH = DATA_DIR / "manifest.json" | |
| IS_LOCAL = "SPACE_ID" not in os.environ and "HF_SPACE" not in os.environ | |
| def load_manifest(): | |
| if MANIFEST_PATH.exists(): | |
| return json.loads(MANIFEST_PATH.read_text()) | |
| return [] | |
| async def index(): | |
| html = (Path(__file__).parent / "templates" / "index.html").read_text() | |
| # Inject the viewer base URL: use local viewer for dev, app.rerun.io for production | |
| if IS_LOCAL: | |
| viewer_base = "http://localhost:9090" | |
| else: | |
| viewer_base = "https://app.rerun.io/version/0.26.2" | |
| html = html.replace("{{VIEWER_BASE}}", viewer_base) | |
| return HTMLResponse(html) | |
| async def list_datasets(): | |
| manifest = load_manifest() | |
| return [ | |
| { | |
| "slug": m["slug"], | |
| "robot_type": m["robot_type"], | |
| "fps": m.get("fps", 0), | |
| "camera_keys": m.get("camera_keys", []), | |
| "camera_labels": m.get("camera_labels", []), | |
| "num_episodes_total": m.get("num_episodes_total", 0), | |
| "state_dim": m.get("state_dim", 0), | |
| "action_dim": m.get("action_dim", 0), | |
| "episodes_available": [ | |
| {"index": ep["index"], "frames": ep.get("frames", "?")} | |
| for ep in m.get("episodes_available", []) | |
| ], | |
| } | |
| for m in manifest | |
| ] | |
| async def list_episodes(slug: str): | |
| manifest = load_manifest() | |
| for m in manifest: | |
| if m["slug"] == slug: | |
| return m["episodes_available"] | |
| return [] | |
| async def serve_rrd(slug: str, index: str): | |
| filepath = DATA_DIR / slug / f"episode_{index}.rrd" | |
| if not filepath.exists(): | |
| return HTMLResponse(status_code=404, content="Episode not found") | |
| return FileResponse( | |
| filepath, | |
| media_type="application/octet-stream", | |
| headers={ | |
| "Accept-Ranges": "bytes", | |
| "Access-Control-Allow-Origin": "*", | |
| "Cross-Origin-Resource-Policy": "cross-origin", | |
| "Cache-Control": "public, max-age=3600", | |
| }, | |
| ) | |
| static_dir = Path(__file__).parent / "static" | |
| if static_dir.exists(): | |
| app.mount("/static", StaticFiles(directory=str(static_dir)), name="static") | |
| def start_local_viewer(): | |
| """Start Rerun web viewer on port 9090 for local development.""" | |
| import rerun as rr | |
| rr.serve_web_viewer(web_port=9090, open_browser=False) | |
| # serve_web_viewer returns immediately after starting the server in a thread | |
| if __name__ == "__main__": | |
| import uvicorn | |
| port = int(os.environ.get("PORT", 8000)) | |
| if IS_LOCAL: | |
| print("Local mode: starting Rerun web viewer on http://localhost:9090") | |
| start_local_viewer() | |
| time.sleep(0.5) | |
| uvicorn.run(app, host="0.0.0.0", port=port) | |