nightwave / app.py
ratandeep's picture
Upload folder using huggingface_hub
021c59c verified
Raw
History Blame Contribute Delete
3 kB
"""HF Spaces entrypoint for NIGHTWAVE (shipped via the Docker SDK).
================================================================================
HOW THIS IS SERVED (Docker SDK -> `uvicorn app:app`)
--------------------------------------------------------------------------------
The Space runs `uvicorn app:app --host 0.0.0.0 --port 7860` (see ../space/Dockerfile
and the README front-matter: `sdk: docker`, `app_port: 7860`). That makes the
combined FastAPI ASGI `app` the single, deterministic server -- no guessing about
which object an HF gradio-launcher would pick up.
The module-level `app` is built FastAPI-FIRST and is ALWAYS functional:
* GET / -> the raw skeuomorphic radio document (top-level, so mic
+ autoplay permissions work without extra iframe nesting)
* POST /api/broadcast, /api/call, /api/seek -> same-origin proxy to Modal
(browser never sees Modal creds; graceful canned
fallback so the radio never goes silent)
A minimal Gradio Blocks (the iframe-wrapped radio) is then mounted at /gradio so
the Space is a bona-fide Gradio app (Off-Brand: a custom frontend past the default
Gradio look). The mount is OPPORTUNISTIC: if gradio import/mount fails for any
reason, the radio + /api/* still serve -- a gradio hiccup can never take the
product down. This is the deliberate <24h ship-safety choice.
================================================================================
"""
import logging
import os
from fastapi.responses import HTMLResponse
from server import create_api, radio_iframe_html, read_radio_html
_log = logging.getLogger("nightwave")
# 1) FastAPI app with the same-origin proxy routes. This ALWAYS works (no gradio).
app = create_api()
# Serve the radio at the root as the RAW document (top-level mic/autoplay).
@app.get("/", response_class=HTMLResponse)
def root_radio() -> HTMLResponse:
return HTMLResponse(read_radio_html())
# 2) Opportunistically mount a minimal Gradio Blocks at /gradio so the Space is a
# genuine Gradio app. Never let a gradio problem break the product.
demo = None
try:
import gradio as gr
with gr.Blocks(
title="NIGHTWAVE",
theme=gr.themes.Base(primary_hue="indigo", neutral_hue="slate"),
css="footer{display:none !important} .gradio-container{max-width:100% !important}",
) as demo:
gr.HTML(radio_iframe_html())
app = gr.mount_gradio_app(app, demo, path="/gradio")
_log.info("Gradio mounted at /gradio")
except Exception as exc: # pragma: no cover - defensive: never break serving
_log.warning("Gradio mount skipped (%r); serving radio + /api/* without it", exc)
if __name__ == "__main__":
# Runs locally too: with gradio absent (local Py3.9) the try/except above just
# skips the mount and we still serve the radio + /api/* exactly as on HF.
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", "7860")))