Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
689928a
Add DaVinci Resolve Plugin with Timeline Integration
ethan-mcmanus-dev Jan 8, 2026
d9ae35f
I think I fixed the corrupted files?
eshaan-mehta Jan 8, 2026
b9640e4
Merge pull request #43 from ClipABit/plugin-for-staging2
eshaan-mehta Jan 9, 2026
41481cc
Merge pull request #42 from ClipABit/plugin-for-staging
safiyamak Jan 18, 2026
7e58ac7
Merge branch 'main' into staging
eshaan-mehta Jan 18, 2026
a34e39a
split modal app into 3
eshaan-mehta Jan 19, 2026
64fa8ac
mostly done splitting. Still debugging
eshaan-mehta Jan 19, 2026
10860a7
cli and cross-env fixes
eshaan-mehta Jan 19, 2026
d1037a9
abstracted dev mode version for local testing
eshaan-mehta Jan 19, 2026
3abf8ba
renaming + tests
eshaan-mehta Jan 19, 2026
d8182b7
successful split? plsssssss
eshaan-mehta Jan 20, 2026
fad1dbc
made file naming consistent
eshaan-mehta Jan 20, 2026
ad2060d
fixes
eshaan-mehta Jan 20, 2026
c834619
linter fixes
eshaan-mehta Jan 20, 2026
6e06fde
feat: restore batch upload handler with validation and orchestration
adithayyil Jan 21, 2026
3d83d55
feat: integrate upload handler into router for batch uploads
adithayyil Jan 21, 2026
fb245db
test: add batch upload tests and fix test fixtures
adithayyil Jan 21, 2026
0c995d8
refactor: move service classes from shared to services directory
adithayyil Jan 21, 2026
8841ad0
refactor: update imports to use services directory
adithayyil Jan 21, 2026
d72620c
fix: add services directory to search and server images
adithayyil Jan 21, 2026
ae37129
Merge pull request #64 from ClipABit/split-backend
eshaan-mehta Jan 21, 2026
e23f8e7
WIP
eshaan-mehta Jan 21, 2026
3cc8363
rename apps
eshaan-mehta Jan 21, 2026
0cb1f00
renaming app
eshaan-mehta Jan 21, 2026
8de7cc1
fixed naming
eshaan-mehta Jan 21, 2026
1be01cf
added missing package
eshaan-mehta Jan 21, 2026
01e3933
load models at docker build instead of container build
eshaan-mehta Jan 21, 2026
0942276
should fix pagination issue
eshaan-mehta Jan 21, 2026
08323d4
fixed naming
eshaan-mehta Jan 21, 2026
32711e2
added missing package
eshaan-mehta Jan 21, 2026
dd874e1
load models at docker build instead of container build
eshaan-mehta Jan 21, 2026
442aa5c
Merge branch 'staging' into staging-issues
eshaan-mehta Jan 21, 2026
46e220f
Merge pull request #65 from ClipABit/staging-issues
eshaan-mehta Jan 22, 2026
0aad7f8
Add DaVinci Resolve Plugin with Timeline Integration
ethan-mcmanus-dev Jan 8, 2026
8aeff92
I think I fixed the corrupted files?
eshaan-mehta Jan 8, 2026
50070c7
split modal app into 3
eshaan-mehta Jan 19, 2026
ce24dc4
mostly done splitting. Still debugging
eshaan-mehta Jan 19, 2026
0ba91ea
cli and cross-env fixes
eshaan-mehta Jan 19, 2026
c10e46a
abstracted dev mode version for local testing
eshaan-mehta Jan 19, 2026
992c377
renaming + tests
eshaan-mehta Jan 19, 2026
b98bc33
successful split? plsssssss
eshaan-mehta Jan 20, 2026
1f49ff5
made file naming consistent
eshaan-mehta Jan 20, 2026
1dd6932
fixes
eshaan-mehta Jan 20, 2026
3156557
linter fixes
eshaan-mehta Jan 20, 2026
51aed1d
feat: restore batch upload handler with validation and orchestration
adithayyil Jan 21, 2026
36c72da
feat: integrate upload handler into router for batch uploads
adithayyil Jan 21, 2026
8703c57
test: add batch upload tests and fix test fixtures
adithayyil Jan 21, 2026
54f80c4
refactor: move service classes from shared to services directory
adithayyil Jan 21, 2026
d49d7e8
refactor: update imports to use services directory
adithayyil Jan 21, 2026
8b9e46a
fix: add services directory to search and server images
adithayyil Jan 21, 2026
e7ba415
renaming app
eshaan-mehta Jan 21, 2026
ab2e202
fixed naming
eshaan-mehta Jan 21, 2026
1b2da3e
added missing package
eshaan-mehta Jan 21, 2026
9d9d068
load models at docker build instead of container build
eshaan-mehta Jan 21, 2026
197b7b3
why does git hate me
eshaan-mehta Jan 22, 2026
4062e45
Merge remote-tracking branch 'refs/remotes/origin/staging' into staging
eshaan-mehta Jan 23, 2026
42edfd2
fixed unit test
eshaan-mehta Jan 24, 2026
1718e25
chore: removes unused files
eshaan-mehta Jan 24, 2026
7ef0315
use onnx instead of pytorch for model runtime
eshaan-mehta Jan 25, 2026
a2c6260
refactor: exposes search service as its own endpoint to remove double…
eshaan-mehta Jan 25, 2026
29c58cf
init files
eshaan-mehta Jan 25, 2026
148703b
linter errors
eshaan-mehta Jan 25, 2026
9a95f43
added missing tests
eshaan-mehta Jan 26, 2026
50ccf33
removes bad comment
eshaan-mehta Jan 26, 2026
0343721
chore: fixes linter errors
eshaan-mehta Jan 26, 2026
4d4f5f3
Merge pull request #67 from ClipABit/microservices
eshaan-mehta Jan 26, 2026
ebb9296
fix: url for search service
eshaan-mehta Jan 26, 2026
b4fff03
reurl fixes
eshaan-mehta Jan 26, 2026
05ca533
missing image
eshaan-mehta Jan 26, 2026
f56634c
hopefully this works lol
eshaan-mehta Jan 26, 2026
295a3ce
fixed image
eshaan-mehta Jan 26, 2026
f71b7af
simplified url
eshaan-mehta Jan 26, 2026
7a7f18e
add /auth/device/code and /auth/device/poll endpoints for plugin auth…
warren-xu Jan 26, 2026
f91e3c8
Merge branch 'staging' into feat/cli-67-firebase-auth-apis
warren-xu Jan 26, 2026
b1a4d63
Merge pull request #68 from ClipABit/feat/cli-67-firebase-auth-apis
warren-xu Jan 27, 2026
f29dd9d
temp change
eshaan-mehta Jan 27, 2026
b5a64c4
abstraction
eshaan-mehta Jan 27, 2026
cbae63a
logging
eshaan-mehta Jan 27, 2026
acc8cb4
url name fix
eshaan-mehta Jan 27, 2026
2d85f90
i'm so dumb holy shit
eshaan-mehta Jan 27, 2026
24de589
remove plugin and watchdog script for main merge
ethan-mcmanus-dev Jan 28, 2026
21c456a
Merge pull request #69 from ClipABit/remove-plugin-watchdog-20260125
eshaan-mehta Jan 28, 2026
f74e89f
Merge branch 'main' into staging
eshaan-mehta Jan 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ concurrency:
permissions:
contents: write

# Note: We deploy the individual apps (server.py, search_app.py, processing_app.py)
# for optimal cold start performance. The dev_combined.py app is ONLY for local
# development and should never be deployed to staging/prod.

jobs:
# ------------------------------------------------------------------
# STAGING DEPLOYMENT (Runs on push to 'staging')
Expand All @@ -38,15 +42,29 @@ jobs:
- name: Install dependencies
run: uv sync --frozen

- name: Deploy to Modal (Staging)
- name: Deploy Processing App (Staging)
env:
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
ENVIRONMENT: staging
run: uv run modal deploy apps/processing_app.py

- name: Deploy Search App (Staging)
env:
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
ENVIRONMENT: staging # for OS
run: uv run modal deploy main.py
ENVIRONMENT: staging
run: uv run modal deploy apps/search_app.py

- name: Deploy Server (Staging)
env:
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
ENVIRONMENT: staging
run: uv run modal deploy apps/server.py

# ------------------------------------------------------------------
# PRODUCTION DEPLOYMENT (Runs only when manually triggered)
# PRODUCTION DEPLOYMENT (Runs on push to 'main')
# ------------------------------------------------------------------
deploy-prod:
name: Deploy Production
Expand All @@ -69,9 +87,23 @@ jobs:
- name: Install dependencies
run: uv sync --frozen

- name: Deploy to Modal (Prod)
- name: Deploy Processing App (Prod)
env:
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
ENVIRONMENT: prod
run: uv run modal deploy apps/processing_app.py

- name: Deploy Search App (Prod)
env:
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
ENVIRONMENT: prod
run: uv run modal deploy apps/search_app.py

- name: Deploy Server (Prod)
env:
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
ENVIRONMENT: prod
run: uv run modal deploy main.py
run: uv run modal deploy apps/server.py
101 changes: 80 additions & 21 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
# ClipABit Backend

Video processing backend that runs on Modal. Accepts video uploads via FastAPI and processes them in serverless containers.
Video processing backend that runs on Modal. Built as a microservices architecture with three specialized apps for optimized cold start times.

## Architecture

The backend uses different architectures for development vs production:

### Production (staging/prod)

Split into three Modal apps for optimal cold start times:

| App | Purpose | Dependencies |
|-----|---------|--------------|
| **server** | API gateway, handles requests, lightweight operations | Minimal (FastAPI, boto3) |
| **search** | Semantic search with CLIP text encoder | Medium (torch, transformers) |
| **processing** | Video processing, embedding generation | Heavy (ffmpeg, opencv, torch, transformers) |

This architecture ensures that lightweight API calls (health, status, list) don't need to load heavy ML models.

### Local Development (dev)

Single combined Modal app (`dev_combined.py`) with all three services:

| App | Purpose |
|-----|---------|
| **dev-combined** | Server + Search + Processing in one app |
This allows hot-reload on all services without cross-app lookup issues. Cold start time is acceptable for local development where iteration speed matters more than cold start performance.

## Quick Start

Expand All @@ -11,34 +36,58 @@ uv sync
# 2. Authenticate with Modal (first time only - opens browser)
uv run modal token new

# 3. Configure Modal secrets (dev and prod)
modal secret create dev \
ENVIRONMENT=dev \
PINECONE_API_KEY=your_pinecone_api_key \
R2_ACCOUNT_ID=your_r2_account_id \
R2_ACCESS_KEY_ID=your_r2_access_key_id \
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key

modal secret create prod \
ENVIRONMENT=prod \
PINECONE_API_KEY=your_pinecone_api_key \
R2_ACCOUNT_ID=your_r2_account_id \
R2_ACCESS_KEY_ID=your_r2_access_key_id \
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key

# 4. Start dev server (hot-reloads on file changes, uses "dev" secret)
# 3. Start dev server
uv run dev
```

Note: `uv run` automatically uses the virtual environment - no need to activate it manually.

## Development CLI

### Local Development (Combined App)

For local development, use the combined app that includes all services in one:

| Command | Description |
|---------|-------------|
| `uv run dev` | Run combined dev app (server + search + processing in one) |

This uses `apps/dev_combined.py` which combines all three services into a single Modal app. Benefits:
- Hot-reload works on all services (server, search, processing)
- No cross-app lookup issues
- Easy to iterate on any part of the system

**Note:** Cold starts will be slower since all dependencies load together, but this is acceptable for local development where iteration speed matters more than cold start performance.

### Individual Apps (For Testing/Debugging)

You can also run individual apps if needed:

| Command | Description |
|---------|-------------|
| `uv run server` | Run just the API server |
| `uv run search` | Run just the search app |
| `uv run processing` | Run just the processing app |


**Note:** Cross-app communication only works between deployed apps, not ephemeral serve apps. For full system testing, use `uv run dev` (combined app) or deploy the apps.

## How It Works

- `main.py` defines a Modal App with a `Server` class
- `/upload` endpoint accepts video files and spawns background processing jobs
### Production Architecture (staging/prod)

- `apps/server.py` - API gateway, delegates heavy work to other apps via `modal.Cls.from_name()`
- `apps/search_app.py` - Handles semantic search queries with CLIP text encoder
- `apps/processing_app.py` - Processes video uploads (chunking, embedding, storage)
- Cross-app communication uses Modal's `Cls.from_name()` for lookups and `spawn()`/`remote()` for calls
- Environment variables stored in Modal secrets (no .env files needed)
- `uv run dev` automatically uses "dev" secret for development
- Production deployment handled via CI/CD or direct Modal CLI

### Local Development Architecture (dev)

- `apps/dev_combined.py` - All three services in one app for easy iteration
- Uses `api/fastapi_router.py` (configured for dev combined mode) which accepts worker class references instead of doing lookups
- No cross-app lookups needed - services call each other directly within the same app
- Hot-reload works on all services simultaneously

## Managing Dependencies

Expand All @@ -56,3 +105,13 @@ uv run pytest # Run all tests
uv run pytest -v # Verbose output
uv run pytest --cov # With coverage
```

Note: Some integration tests require `ffmpeg` to be installed locally.

## Deployment

Deployment is handled via GitHub Actions CI/CD. **Only the individual apps are deployed** (not dev_combined.py):

1. `processing_app.py` (heavy dependencies)
2. `search_app.py` (medium dependencies)
3. `server.py` (API gateway - depends on the other two)
5 changes: 3 additions & 2 deletions backend/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .fastapi_router import FastAPIRouter
from .server_fastapi_router import ServerFastAPIRouter
from .search_fastapi_router import SearchFastAPIRouter

__all__ = ["FastAPIRouter"]
__all__ = ["ServerFastAPIRouter", "SearchFastAPIRouter"]
Loading
Loading