# Dragonflight

Self-hosted broadcast media-asset management system that replaces legacy tools like Grass Valley AMPP and FramelightX. Handles live ingest, growing-file editing, scheduling, transcoding, and asset management in a single operator-focused interface.

> Repo renamed from `wild-dragon` → `dragonflight` (2026-05-23). The old URL still redirects.

## Home Dashboard

<img src="docs/screenshots/01-home.png" alt="Home Dashboard" width="800" />

The home screen provides quick access to all major features and displays system status at a glance:
- **Library** — Browse projects, bins, and assets with hover-scrub previews
- **Recorders** — View configured capture devices and their status
- **Editor** — Timeline editor with cross-clip preview and render queue
- **Jobs** — Proxy and thumbnail queue with retry controls
- **Settings** — Configure storage, encoder, growing files, and capture SDK
- **Dashboard** — Operations view showing recent activity, job queue, and cluster health

---

## Core Features

### 1. Live Ingest & Capture
**Multi-protocol source capture with per-recorder codec settings**

Dragonflight ingests from multiple sources simultaneously:
- **SRT** (Secure Reliable Transport) — caller and listener modes
- **RTMP** — standard streaming protocol
- **SDI** — via Blackmagic DeckLink cards with FFmpeg SDK 16.x patches

Each recorder can be configured with independent codec settings:
- ProRes (hi-res masters)
- H.264 / H.265 (proxies)
- DNxHR (Avid compatibility)

Audio routing and per-source configuration ensure flexibility for multi-camera productions.

### 2. Growing-File Editing
**Live editing in Premiere Pro while capture is still writing**

Editors mount the SMB landing zone directly in Premiere Pro and edit the live master file as it's being written. The included CEP (Custom Extension Panel) provides:
- Real-time clip detection and frame-accurate trimming
- One-click relink to final S3 master after promotion
- No waiting for capture to finish before editorial begins

### 3. Recorder Scheduler
**Time-windowed recording automation**

Schedule recordings with:
- One-shot, daily, or weekly recurrence
- Automatic start/stop via 15-second tick loop
- Conflict detection across recorders
- Project and bin assignment at schedule time

### 4. Library & Asset Management
**Browse, search, and organize captured footage**

The Library screen provides:
- Project and bin hierarchy
- Asset detail view with frame-anchored persistent comments
- Right-click context menu (move-to-bin, rename, delete)
- Global cmd/ctrl-K search across assets, projects, recorders, jobs, and users
- Hover-scrub preview with HLS playback

### 5. Jobs Queue
**BullMQ-backed proxy and thumbnail generation**

Automated background processing:
- Per-job retry logic with exponential backoff
- Bulk "retry all failed" for batch recovery
- Inline error messages with actionable diagnostics
- Status tracking: ingesting → processing → ready

Proxy encoder options:
- CPU-based: libx264 (H.264)
- GPU-accelerated: NVENC (NVIDIA) or VAAPI (AMD/Intel)

### 6. Timeline Conform & Export
**FCP XML export with server-side FFmpeg rendering**

The Premiere Pro panel exports FCP XML with:
- Server-side conform via FFmpeg
- Multiple output formats: H.264, H.265, ProRes
- Resolution presets: Broadcast, Web, Archive
- Batch processing with job queue integration

### 7. Hi-Res Auto-Relink
**One-click batch relink of proxy clips to frame-accurate server-trimmed masters**

After editing on proxies:
- Select clips in Premiere
- Trigger relink from the CEP panel
- Server trims hi-res segments to exact in/out points
- Concurrent trim worker pool for speed
- 24-hour TTL with automatic cleanup

### 8. Settings & Configuration
**Centralized control for storage, encoding, and capture**

Configure:
- **S3 Storage** — endpoint, bucket, credentials (with env-var fallback)
- **Proxy Encoder** — CPU vs GPU, bitrate, resolution
- **Growing Files** — SMB path, retention, auto-promotion
- **Capture SDK** — Blackmagic, AJA, or Deltacast uploader selection

### 9. Cluster & Distributed Capture
**Primary + worker topology with remote DeckLink nodes**

- Primary node runs API, scheduler, and web UI
- Worker nodes handle proxy/thumbnail jobs
- Remote capture nodes run DeckLink cards off-host
- Heartbeat health monitoring
- Automatic failover and recovery

### 10. Admin & User Management
**Role-based access, token auth, and cluster monitoring**

- User creation and role assignment
- API token generation for integrations
- Container and cluster node status
- System health dashboard

---

## Quick Start

```bash
# Clone (repo renamed; old URL still redirects)
git clone https://forge.wilddragon.net/zgaetano/dragonflight.git
cd dragonflight

# Configure
cp .env.example .env
# Edit .env — S3 credentials + SESSION_SECRET at minimum

# Launch
docker compose up -d

# Open
open http://localhost:47434
```

## Architecture

```
SDI / SRT / RTMP ──► capture (FFmpeg)
                       ├─ HLS preview tee ──► /live/<assetId>/index.m3u8
                       └─ master output
                            ├─ growing_enabled=true:
                            │    /growing/<projectId>/<clip>.mov
                            │      (Premiere mounts SMB, edits live)
                            │      └─► promotion worker uploads to S3
                            │
                            └─ growing_enabled=false:
                                 multipart stream → S3

assets POST ──► proxy job ──► worker
                                ├─ libx264 (CPU) or NVENC/VAAPI (GPU)
                                ├─ thumbnail job
                                └─ status: ingesting → processing → ready
```

## Tech Stack

- **Runtime:** Node.js 22, Docker Compose
- **Backend:** Express, PostgreSQL 16, Redis 7 + BullMQ
- **Frontend:** Vanilla React via in-browser Babel (no bundler), hls.js
- **Media:** FFmpeg 7.1 with SDK 16 DeckLink patches
- **Codecs:** ProRes, H.264, H.265, DNxHR, MOV/MP4/MXF containers
- **Storage:** S3-compatible (RustFS) for masters, proxies, thumbnails

## Services

| Service | Port | Purpose |
|---------|------|---------|
| **web-ui** | 47434 | Browser SPA + capture controls |
| **mam-api** | 47432 | REST API + recorder orchestration + scheduler |
| **capture** | 47433 / 9000 / 1935 | DeckLink/SRT/RTMP ingest sidecar |
| **worker** | — | BullMQ proxy + thumbnail workers |
| **db** | 5432 | PostgreSQL 16 |
| **queue** | 6379 | Redis 7 |

---

## Workflow Example: Live-to-Edit

1. **Operator** schedules a recording on Recorder A for 14:00–15:30, assigns to "News/Segment-A" project
2. **Capture** starts at 14:00, writes ProRes master to SMB landing zone
3. **Editor** mounts SMB in Premiere, opens the live .mov file via the CEP panel
4. **Editor** trims and marks in/out points while capture is still writing
5. **Capture** finishes at 15:30, promotion worker uploads master to S3
6. **Editor** clicks "Relink to Master" in CEP panel
7. **Server** trims hi-res segment to exact in/out, stores for 24 hours
8. **Premiere** relinks proxy clips to trimmed master
9. **Editor** exports final timeline via FCP XML conform

Total time from end of capture to relinked master: ~2 minutes.

---

## Operations

- `deploy/api-smoke.sh` — verify every API endpoint after deploy
- `deploy/onboard-node.sh` — provision a remote worker host
- `deploy/test-cluster.sh` — primary↔worker connectivity smoke test
- `docs/GROWING_FILES_QUICKSTART.md` — Premiere CEP panel install + growing-file flow

## Authentication

Dragonflight uses local username/password authentication with two transports:

- **Browser:** session cookie (`dragonflight.sid`), 8 hour absolute + 1 hour idle timeout.
- **Premiere panel / scripts:** SHA-256-hashed bearer tokens issued from `Settings → API Tokens`.

### First-run setup

On a fresh install with `AUTH_ENABLED=true`, navigate to the web UI in a browser.
With no users in the database, the login screen renders a "First-run setup" form
instead — fill it in to create the first admin and you are logged in immediately.

Subsequent users are created from `Settings → Users` (any signed-in user can
create others — flat access).

### Dev mode

Setting `AUTH_ENABLED=false` disables all auth checks; a synthetic `dev` user
is attached to every request. **Never deploy this way.** The dev user row is
seeded with a hash that no real password can match, so flipping
`AUTH_ENABLED=true` later does not expose the dev account.

### Recovering a forgotten admin password

Any signed-in user can reset another user's password from `Settings → Users`.
If no one can sign in (all admins forgot their passwords), reset directly in
Postgres:

```sql
-- generate a fresh bcrypt hash with:
--   node -e "import('bcrypt').then(b => b.default.hash(process.argv[1], 12).then(h => console.log(h)))" 'new-passphrase-here'
UPDATE users SET password_hash = '<bcrypt-hash>', password_updated_at = NOW()
 WHERE username = 'admin';
```

### `AUTH_ENABLED` transition

When flipping `AUTH_ENABLED=false` → `true` on an existing install:

1. Ensure `SESSION_SECRET` is set to a stable value (rotating it logs everyone out).
2. Set `ALLOWED_ORIGINS` to the public origin(s) of the web UI.
3. Set `TRUST_PROXY=true` when behind nginx (required for rate-limit accuracy).
4. Restart `mam-api`.
5. Visit the UI — first-run setup will appear if no real users exist yet.

---

## License

Proprietary — Wild Dragon LLC, all rights reserved.
