sushilideaclan01 commited on
Commit
0af7cf6
·
1 Parent(s): 2f9de1b
Files changed (5) hide show
  1. .dockerignore +15 -0
  2. Dockerfile +25 -0
  3. README.md +46 -5
  4. backend/main.py +14 -0
  5. backend/utils/public_url.py +4 -1
.dockerignore ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .git
2
+ **/.venv
3
+ **/__pycache__
4
+ **/*.pyc
5
+ **/node_modules
6
+ frontend/dist
7
+ .env
8
+ .env.*
9
+ **/.env.local
10
+ storage
11
+ showcase_output
12
+ reference_videos
13
+ *.mp4
14
+ *.png
15
+ **/.DS_Store
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1
2
+ # Hugging Face Spaces (Docker) — FastAPI + Vite build. Listens on $PORT (default 7860).
3
+
4
+ FROM node:22-bookworm-slim AS frontend-build
5
+ WORKDIR /app/frontend
6
+ COPY frontend/package.json frontend/package-lock.json ./
7
+ RUN npm ci
8
+ COPY frontend/ ./
9
+ RUN npm run build
10
+
11
+ FROM python:3.12-slim-bookworm
12
+ RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg \
13
+ && rm -rf /var/lib/apt/lists/*
14
+
15
+ WORKDIR /app
16
+ COPY backend/requirements.txt /app/backend/requirements.txt
17
+ RUN pip install --no-cache-dir -r /app/backend/requirements.txt
18
+ COPY backend/ /app/backend/
19
+ COPY --from=frontend-build /app/frontend/dist /app/frontend/dist
20
+
21
+ ENV PYTHONPATH=/app/backend
22
+ ENV PORT=7860
23
+
24
+ WORKDIR /app/backend
25
+ CMD ["sh", "-c", "exec uvicorn main:app --host 0.0.0.0 --port ${PORT:-7860}"]
README.md CHANGED
@@ -1,10 +1,51 @@
1
  ---
2
- title: ProductShowcaseStudio
3
- emoji: 📉
4
- colorFrom: gray
5
  colorTo: indigo
6
  sdk: docker
7
- pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Product Showcase Studio
3
+ emoji: 🎬
4
+ colorFrom: slate
5
  colorTo: indigo
6
  sdk: docker
7
+ app_port: 7860
8
  ---
9
 
10
+ # Product Showcase Studio
11
+
12
+ Cinematic product video pipeline: **shot planning** → **KIE Veo / Seedance** → **FFmpeg merge**, with optional **GPT Image** keyframes and **product URL** import.
13
+
14
+ ## Deploy on Hugging Face Spaces
15
+
16
+ 1. **Create a Space** → **Docker** → link this repository (or push these files to a new repo under your account).
17
+ 2. **Settings → Repository secrets** (or **Variables and secrets**): add at least:
18
+ - **`VITE_API_BASE_URL`** — your Space’s public app URL, same as the address in the browser when the app loads, with no trailing slash (for example `https://YOUR-USERNAME-YOUR-SPACE-NAME.hf.space`). This is required so **callback URLs** and **hosted images** use the correct origin.
19
+ - **`KIE_API_KEY`** — if you use KIE Veo.
20
+ - **`OPENAI_API_KEY`** — optional, for LLM shot plans and GPT Image keyframes.
21
+ - **`REPLICATE_API_TOKEN`** — optional Seedance fallback when KIE is not used.
22
+ 3. Wait for the build (Node build + Python image). Open the Space URL when the build is **Running**.
23
+
24
+ The container runs **uvicorn** on **`PORT`** (Spaces set this; default **7860**). **FFmpeg** is installed for the merge step.
25
+
26
+ ### Local Docker (optional)
27
+
28
+ ```bash
29
+ docker build -t product-showcase .
30
+ docker run --rm -p 7860:7860 \
31
+ -e VITE_API_BASE_URL=http://127.0.0.1:7860 \
32
+ -e KIE_API_KEY=... \
33
+ product-showcase
34
+ ```
35
+
36
+ Then open `http://127.0.0.1:7860`.
37
+
38
+ ## Local development
39
+
40
+ See [FLOW.md](FLOW.md) for architecture and env details.
41
+
42
+ ```bash
43
+ # API
44
+ cd backend && python -m venv .venv && source .venv/bin/activate
45
+ pip install -r requirements.txt && python main.py
46
+
47
+ # UI (separate terminal)
48
+ cd frontend && npm install && npm run dev
49
+ ```
50
+
51
+ With a built `frontend/dist`, `python main.py` also serves the SPA from the same origin.
backend/main.py CHANGED
@@ -4,10 +4,12 @@ Video pipeline aligned with python-backend (KIE Veo, image hosting, merge).
4
  """
5
 
6
  from contextlib import asynccontextmanager
 
7
  import os
8
  import shutil
9
 
10
  from fastapi import FastAPI
 
11
  from fastapi.middleware.cors import CORSMiddleware
12
 
13
  from api.video_generation import router as video_router
@@ -78,6 +80,10 @@ app.include_router(image_router, prefix="/api")
78
  app.include_router(export_router, prefix="/api")
79
 
80
 
 
 
 
 
81
  @app.get("/health")
82
  def health():
83
  return {
@@ -96,6 +102,14 @@ def health():
96
  }
97
 
98
 
 
 
 
 
 
 
 
 
99
  if __name__ == "__main__":
100
  import uvicorn
101
 
 
4
  """
5
 
6
  from contextlib import asynccontextmanager
7
+ from pathlib import Path
8
  import os
9
  import shutil
10
 
11
  from fastapi import FastAPI
12
+ from fastapi.staticfiles import StaticFiles
13
  from fastapi.middleware.cors import CORSMiddleware
14
 
15
  from api.video_generation import router as video_router
 
80
  app.include_router(export_router, prefix="/api")
81
 
82
 
83
+ _REPO_ROOT = Path(__file__).resolve().parent.parent
84
+ _FRONTEND_DIST = _REPO_ROOT / "frontend" / "dist"
85
+
86
+
87
  @app.get("/health")
88
  def health():
89
  return {
 
102
  }
103
 
104
 
105
+ if _FRONTEND_DIST.is_dir():
106
+ app.mount(
107
+ "/",
108
+ StaticFiles(directory=str(_FRONTEND_DIST), html=True),
109
+ name="frontend",
110
+ )
111
+
112
+
113
  if __name__ == "__main__":
114
  import uvicorn
115
 
backend/utils/public_url.py CHANGED
@@ -10,7 +10,10 @@ def get_server_port_str() -> str:
10
 
11
 
12
  def get_public_base_url() -> str:
13
- explicit = (os.getenv("VITE_API_BASE_URL") or "").strip().rstrip("/")
 
 
 
14
  if explicit:
15
  return explicit
16
  return f"http://127.0.0.1:{get_server_port_str()}"
 
10
 
11
 
12
  def get_public_base_url() -> str:
13
+ """Public origin for callbacks and hosted URLs. Set VITE_API_BASE_URL or PUBLIC_BASE_URL on deploy (e.g. https://YOUR-SPACE.hf.space)."""
14
+ explicit = (
15
+ (os.getenv("VITE_API_BASE_URL") or os.getenv("PUBLIC_BASE_URL") or "").strip().rstrip("/")
16
+ )
17
  if explicit:
18
  return explicit
19
  return f"http://127.0.0.1:{get_server_port_str()}"