Dragonflight - self-hosted broadcast media asset management. SRT/RTMP/SDI ingest via Blackmagic DeckLink, FFmpeg proxy generation, growing-file editing via SMB + Premiere Pro CEP panel, BullMQ job queue, S3-compatible storage (RustFS). Replaces Grass Valley AMPP FramelightX.
Find a file
opencode 04ce096e67 chore: 1.2 ship-prep sweep — close 38 issues
Frontend / UX / a11y
- Sidebar collapse/expand toggle with localStorage persistence (#142)
- Settings sections wrap inputs in <form> with Enter-to-submit + native
  validation; password autocomplete=new-password (#141, #138)
- Asset thumbnails get descriptive alt text (#140)
- Production deploy now precompiles JSX via esbuild and loads the
  production React UMD instead of dev builds + in-browser Babel (#139,
  #122)
- Search wrapper gets role=search; global search input gets aria-label,
  role=combobox, aria-controls/aria-expanded/aria-activedescendant
  wiring (#137, #135)
- Dashboard and Library no longer share the same nav icon (#136)
- Sidebar collapses off-canvas with a topbar menu button below 768 px;
  mobile default is collapsed (#134)
- --text-3 bumped to #8B92A0 for WCAG AA contrast on --bg-0 (#133)
- Schedule and Library routes were rendering empty inside the .main
  flex container — switched to flex:1 + min-height:0 (#131, #132,
  editor + asset detail get the same fix)
- Jobs nav badge now polls /jobs?status=active every 10 s and reflects
  the live count (#130, #113)
- aria-label sweep on every icon-only button (#126)
- Premiere panel release list moved to window.PREMIERE_RELEASES in
  data.jsx; Editor + Settings read from the same source (#125)
- Typo setPgMclips → setPgmClips (#124)
- Stray console.error / console.warn calls gated behind
  window.DF_LOG.{warn,error} (#123)
- Hardcoded /api/v1 paths route through window.ZAMPP_API_PREFIX (#115)
- Schedule rows no longer crash on null recorder_id (#117)
- EditorKeyboard guards against document.activeElement === null (#116)
- Unmount-safe timers for PasswordResetModal, Containers, Editor (#111)
- Player seek clamps below totalMs, server-side range clamping +
  uncached 416 on EOF, client-side EOF-stall watchdog (#143)
- Duration badge overlap fix on narrow asset cards (#52)

Backend / security / reliability
- GET /recorders fixed N+1: single LATERAL JOIN for live_asset_id;
  Docker inspects bounded to actually-recording rows (#121)
- Upload disk-storage (multer.diskStorage) streams parts to S3 instead
  of buffering 500 MB in RAM (#120)
- /assets list clamps limit to MAX_LIMIT=500 to prevent OOM (#119)
- SDK upload archive listing + post-extract sanitize block zip-slip /
  tar-slip and symlink escapes (#118)
- Migrations track applied state in schema_migrations, run in a
  transaction, and exit non-zero on failure (#107)
- node-agent BMD_COUNT override uses BMD_DEVICE_PREFIX; filesystem
  detection wins (#109, #127)
- GPU_COUNT override now merges with nvidia-smi enrichment (#108)
- /cluster/heartbeat requires a node-bound token or admin user;
  tokens carry bound_hostname (#106)
- /recorders/:id/start error responses no longer echo the Docker
  create payload — env vars stay out of client responses (#105)
- /recorders/probe restricts schemes (srt/rtmp/rtsp/udp/rtp), blocks
  private + loopback hosts for non-admins, denies common service
  ports (#104)
- Scheduler tick guarded by a Postgres advisory lock; pending/running
  rows claimed via UPDATE...RETURNING + FOR UPDATE SKIP LOCKED to
  survive multi-node deploys (#103)
- UUID validateUuid('id') param middleware on every /:id route (#102)
- Error handler scrubs Postgres error messages and 5xx detail (#101)
- Graceful SIGTERM/SIGINT shutdown — stops scheduler, drains the HTTP
  server, ends the pool, 25 s force-exit watchdog (#100)
- AMPP sync moved from fire-and-forget to a persisted retry queue
  (ampp_sync_status / attempts / next_attempt_at + scheduler retry
  loop with exponential backoff) (#77)

Migrations
- 019: api_tokens.bound_hostname (#106)
- 020: assets.ampp_sync_status + retry bookkeeping (#77)

Other
- Defer #92 Growing-files per-upload toggle, #80 Audio tab, #57
  Dashboard redesign, #56 Editor SPA polish phase 3, #114 S3
  migration tool to v1.3
2026-05-27 02:06:14 +00:00
deploy test: deploy/api-smoke.sh — exercises every API surface 2026-05-23 04:24:10 +00:00
docs Add home dashboard screenshot 2026-05-26 01:28:44 +00:00
services chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
.env.example fix(infra+workers): S3 creds, ffprobe, BullMQ awaits, thumbnail seek, bin optional, docker-compose vars, jobs Redis, recorders stop codes: .env.example 2026-05-16 00:29:45 -04:00
.gitignore feat(premiere-plugin): ZXP + Windows installer build pipeline 2026-05-23 16:13:20 -04:00
DESIGN.md feat(schedule): EPG stylesheet + impeccable context (PRODUCT/DESIGN.md) 2026-05-23 16:19:25 -04:00
docker-compose.gpu.yml feat: docker-compose.gpu.yml overlay — NVIDIA GPU pass-through + NVENC worker 2026-05-20 14:19:02 -04:00
docker-compose.worker.yml chore: 1.2 ship-prep sweep — close 38 issues 2026-05-27 02:06:14 +00:00
docker-compose.yml fix: remove openreel editor; fire df:assets-changed on upload/ingest complete 2026-05-24 20:36:04 -04:00
PRODUCT.md feat(schedule): EPG stylesheet + impeccable context (PRODUCT/DESIGN.md) 2026-05-23 16:19:25 -04:00
README.md Use HTML img tag for screenshot 2026-05-26 01:47:28 +00:00
setup-repo.sh add setup-repo.sh 2026-04-07 21:58:16 -04:00

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-dragondragonflight (2026-05-23). The old URL still redirects.

Home Dashboard

Home Dashboard

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

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

# 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:0015: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

License

Proprietary — Wild Dragon LLC, all rights reserved.