AI-powered video restoration and super-resolution. B.Sc. Computer Science final project (Deep Learning specialization).
A pnpm + Turborepo monorepo with three apps and a shared full-stack contract chain:
apps/
├── frontend Vite 8 + React 19 SPA (Tailwind v4, shadcn/ui, RTK Query) :5173
├── backend NestJS 11 API under /api (uploads, jobs, SSE, streaming) :3000
└── ai Python FastAPI + PyTorch inference service :8000
packages/
├── consts Endpoint path strings and app constants
├── schemas Zod 4 schemas + inferred types (single source of truth)
├── contracts Typed EndpointContract objects (consts + schemas)
├── eslint-config Shared ESLint 9 flat-config presets
└── typescript-config Shared strict tsconfig presets
- The frontend uploads a video (
POST /api/upload, multipart, XHR progress) and receives ajobId. - The backend stores the file on disk (Multer), tracks the job in memory, and calls the AI service (
POST /process), consuming an NDJSON progress stream. - The AI service runs BasicVSR + SPyNet (V3 checkpoint, 4x scale) over the video frames and writes the enhanced output to
storage/results. - The frontend follows progress over SSE (
/api/upload/events/:jobId, with polling fallback), then plays/downloads the result via HTTP Range streaming (/api/upload/stream/:jobId). - Jobs can be cancelled end-to-end (
POST /api/upload/cancel/:jobIdbridges to the AI service).
Errors follow RFC 7807 (ProblemDetails) with a traceId from the request-id middleware. All request/response shapes live in @repo/schemas; the backend wraps them with nestjs-zod DTOs and the frontend validates responses against @repo/contracts.
- Node >= 24 (see
.nvmrc) - pnpm 10 (
corepack enableornpm i -g pnpm) - Python 3.11+ with pip (for the AI service)
- The model checkpoint at
apps/ai/checkpoints/vsr_model_best.pth(not in git)
pnpm install
# one-time Python setup
pnpm --filter ai setup
# copy env examples (optional — sane defaults exist)
cp apps/backend/.env.development.example apps/backend/.env.development
cp apps/frontend/.env.development.example apps/frontend/.env.development
# start everything (frontend 5173, backend 3000, ai 8000)
pnpm devSwagger UI is served at http://localhost:3000/docs in development.
| Command | Purpose |
|---|---|
pnpm dev |
Start all apps in watch mode |
pnpm dev:web |
Start frontend + backend only (no AI service) |
pnpm dev:ai |
Start the AI inference service only |
pnpm build |
Build all packages and apps (bottom-up, cached) |
pnpm preview |
Build, then run in local production-rehearsal mode |
pnpm preview:web |
Build, then run frontend + backend only |
pnpm preview:ai |
Run the AI service in production mode (no reload) |
pnpm start:prod |
Build, then run in pure production mode |
pnpm start:prod:web |
Build, then run frontend + backend in prod mode |
pnpm start:prod:ai |
Run the AI service in production mode |
pnpm lint |
Lint everything (--max-warnings 0) |
pnpm check-types |
Type-check everything |
pnpm format |
Prettier-format the repo |
Filter to one app: pnpm --filter backend dev, pnpm --filter backend test:e2e, etc.
Each app commits .env.development.example / .env.production.example. Backend env is Zod-validated at startup (apps/backend/src/utils/env.validation.ts) — see CLAUDE.md for the full table. Key ones:
- backend:
PORT,CORS_ORIGIN,AI_SERVICE_URL,UPLOAD_DIR,RESULT_DIR,MAX_FILE_SIZE_MB,ALLOWED_VIDEO_EXTENSIONS - frontend:
VITE_PORT,VITE_API_BASE_URL(backend origin, no/apisuffix) - ai:
CHECKPOINT_PATH,DEVICE,MAX_INPUT_HEIGHT,HOST,PORT
apps/ai/baseline/ contains the V3 architecture: BasicVSR with a SPyNet optical-flow backbone (sequence length 15, 4x upscale). vsr_inference.py exposes VSRInferenceEngine with frame-window batching, progress callbacks, and cooperative cancellation. Training artifacts live in Model_v3.ipynb. Inference parameters are owned by the engine/checkpoint — the backend does not override them.
There is no mock fallback: if the AI service is down or the checkpoint is missing, jobs fail with a clear error.
- Job state is in-memory; a backend restart loses all jobs.
- Single-node disk storage (
storage/, gitignored). - Deploy script builds the frontend but static hosting must be configured separately (see
deploy-upscale-ai.sh).
deploy-upscale-ai.sh (triggered via .github/workflows/deploy.yml over SSH) pulls main, runs pnpm install && pnpm build, and restarts the backend and AI service under PM2. See the script header for the remaining manual steps.
The full project characterization (architecture decisions, pipeline design, milestones) lives in docs/Upscale-Project-Characterization.pdf. Agent-facing guides: AGENTS.md (root and per-app) and CLAUDE.md.