docs: README, roadmap 002 (feature gaps vs Pomfort, tiered), wireframes — grade-centric vs library-centric layouts in Reel tokens w/ recommendation (A main + B as library surface)
This commit is contained in:
parent
f4eb9b7a95
commit
014c7ca283
3 changed files with 469 additions and 0 deletions
61
README.md
Normal file
61
README.md
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
# Rainbow Dragon (Forge)
|
||||||
|
|
||||||
|
On-set live grading + DIT toolkit. Grades live **in the camera** over IP — no LUT box
|
||||||
|
required — plus verified offload, ASC MHL, clip logging, and proxy generation.
|
||||||
|
Sister product to dragonflight.
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
- **In-camera live grading over IP**
|
||||||
|
- ARRI ALEXA 35 / Mini LF — CAP protocol (binary TCP :5055): native ASC CDL push,
|
||||||
|
3D LUT (experimental), EVENT-driven metadata
|
||||||
|
- RED DSMC3 (Komodo/Raptor) — RCP2 (WebSocket :9998): native CDL via per-channel params
|
||||||
|
- Sony VENICE 2 — monitoring-only (protocol closed; grade via SDI chain)
|
||||||
|
- **Node-based grade engine** — input transform (LogC4 / Log3G10 / S-Log3 + gamuts),
|
||||||
|
CDL, saturation, monotone curves, 3D LUT, output transform; flattens to camera-ready
|
||||||
|
looks with CDL-split for live trim
|
||||||
|
- **Multicam** — gang slots, per-camera capability-aware flattening, debounced push
|
||||||
|
- **Auto clip logging** — rec events → shot records w/ camera metadata + grade snapshot
|
||||||
|
- **Deliverables** — ALE, CMX3600 EDL (ASC_SOP/SAT), CDL/CCC, CUBE, CSV
|
||||||
|
- **Offload** — multi-destination verified copy (xxHash64/MD5), **ASC MHL v2.0**
|
||||||
|
manifests (validates against official XSD), tamper detection, HTML/CSV reports
|
||||||
|
- **Proxies** — ffmpeg ProRes/DNxHR/H.264, grade bake via LUT, TC/clip burn-ins,
|
||||||
|
watch folders
|
||||||
|
- **Panels** — Tangent Wave control mapping (Hub TIPC shim lands in macOS phase)
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Core engine + protocol layer complete: **200 tests**, all camera drivers verified against
|
||||||
|
wire-faithful simulators built from real protocol research (`docs/research/`).
|
||||||
|
macOS app (SwiftUI + Metal preview + DeckLink + Tangent Hub) is the next phase.
|
||||||
|
|
||||||
|
## CLI
|
||||||
|
|
||||||
|
```
|
||||||
|
forge sim # run an ARRI CAP camera simulator
|
||||||
|
forge status --host <ip> --port 5055 # connection/rec state + metadata
|
||||||
|
forge push --host <ip> --look l.json --split-cdl
|
||||||
|
forge export --db forge.db --day "Day 01" --format ale|edl|ccc|cube|csv --out f
|
||||||
|
forge offload <card> --to /raid --to /shuttle --report report.html
|
||||||
|
forge verify <manifest.mhl>
|
||||||
|
forge proxy --db forge.db --day "Day 01" --media /raid --out /proxies --burn-look
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Swift 6.0+, Linux or macOS:
|
||||||
|
|
||||||
|
```
|
||||||
|
swift build && swift test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
- `Sources/ForgeColor` — color math (CDL, transfer functions, LUTs, curves)
|
||||||
|
- `Sources/ForgeGrade` — node stack, flattening, snapshots
|
||||||
|
- `Sources/ForgeCamera*` — driver seam + ARRI/RED/Sony drivers
|
||||||
|
- `Sources/ForgeSim` — protocol-faithful camera simulators
|
||||||
|
- `Sources/ForgeLogger` / `ForgeLibrary` — clip logging, SQLite shot store
|
||||||
|
- `Sources/ForgeExport` / `ForgeOffload` / `ForgeProxy` — deliverables, offload/MHL, proxies
|
||||||
|
- `Sources/ForgePanel` / `ForgeVideo` — control surfaces, video I/O seams
|
||||||
|
- `docs/plans/` — implementation plans; `docs/research/` — protocol + competitive research
|
||||||
342
docs/design/wireframes.html
Normal file
342
docs/design/wireframes.html
Normal file
|
|
@ -0,0 +1,342 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Forge — Wireframes (Reel tokens)</title>
|
||||||
|
<style>
|
||||||
|
/* ============ Reel design tokens (from dragonflight styles.css) ============ */
|
||||||
|
:root {
|
||||||
|
--bg-0: #08090C; --bg-1: #0C0E12; --bg-2: #111318; --bg-3: #181B22; --bg-4: #22262F;
|
||||||
|
--text-1: #F6F4EF; --text-2: #B4B0A6; --text-3: #86837B; --text-4: #63615B;
|
||||||
|
--accent: #F0A63C; --accent-hover: #F7B857; --accent-text: #F6C583;
|
||||||
|
--accent-soft: rgba(240,166,60,0.12);
|
||||||
|
--success: #5FBF97; --warning: #E6A93C; --danger: #E86A6A; --live: #FF3B30;
|
||||||
|
--live-soft: rgba(255,59,48,0.12); --success-soft: rgba(95,191,151,0.12);
|
||||||
|
--hairline: rgba(255,255,255,0.07); --hairline-2: rgba(255,255,255,0.12);
|
||||||
|
--hover-fill: rgba(255,255,255,0.028);
|
||||||
|
--mono: "Geist Mono", "SF Mono", ui-monospace, monospace;
|
||||||
|
--sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", sans-serif;
|
||||||
|
}
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body { background: #04050 6; background: #040506; color: var(--text-1);
|
||||||
|
font-family: var(--sans); font-size: 13px; letter-spacing: -0.006em; padding: 40px; }
|
||||||
|
h1 { font-size: 22px; font-weight: 600; margin-bottom: 6px; }
|
||||||
|
.intro { color: var(--text-3); margin-bottom: 36px; max-width: 720px; line-height: 1.5; }
|
||||||
|
h2 { font-size: 15px; font-weight: 600; margin: 42px 0 4px; color: var(--accent-text); }
|
||||||
|
.philosophy { color: var(--text-3); margin-bottom: 14px; max-width: 720px; line-height: 1.5; }
|
||||||
|
|
||||||
|
/* window chrome */
|
||||||
|
.window { background: var(--bg-0); border: 1px solid var(--hairline-2); border-radius: 10px;
|
||||||
|
overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,0.6); max-width: 1240px; }
|
||||||
|
.titlebar { height: 38px; background: var(--bg-1); border-bottom: 1px solid var(--hairline);
|
||||||
|
display: flex; align-items: center; padding: 0 14px; gap: 8px; }
|
||||||
|
.traffic { display: flex; gap: 7px; }
|
||||||
|
.traffic span { width: 11px; height: 11px; border-radius: 50%; background: var(--bg-4); }
|
||||||
|
.titlebar .title { flex: 1; text-align: center; color: var(--text-3); font-size: 12px; }
|
||||||
|
.toolbar { height: 44px; background: var(--bg-1); border-bottom: 1px solid var(--hairline);
|
||||||
|
display: flex; align-items: center; padding: 0 14px; gap: 10px; }
|
||||||
|
.tbtn { height: 28px; padding: 0 12px; border-radius: 4px; background: var(--bg-3);
|
||||||
|
border: 1px solid var(--hairline-2); color: var(--text-2); font-size: 12px;
|
||||||
|
display: inline-flex; align-items: center; gap: 6px; }
|
||||||
|
.tbtn.primary { background: var(--accent); color: #1A1206; border: none; font-weight: 600; }
|
||||||
|
.tspacer { flex: 1; }
|
||||||
|
|
||||||
|
.eyebrow { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.16em;
|
||||||
|
font-weight: 600; color: var(--text-4); padding: 12px 14px 6px; }
|
||||||
|
.mono { font-family: var(--mono); }
|
||||||
|
|
||||||
|
/* badges + dots */
|
||||||
|
.badge { font-size: 9.5px; text-transform: uppercase; font-weight: 600; letter-spacing: 0.08em;
|
||||||
|
padding: 2px 7px; border-radius: 999px; }
|
||||||
|
.badge.rec { background: var(--live-soft); color: var(--live); }
|
||||||
|
.badge.ok { background: var(--success-soft); color: var(--success); }
|
||||||
|
.badge.neutral { background: var(--bg-4); color: var(--text-3); }
|
||||||
|
.dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
|
||||||
|
.dot.rec { background: var(--live); box-shadow: 0 0 6px var(--live); animation: pulse 1.2s infinite; }
|
||||||
|
.dot.ok { background: var(--success); }
|
||||||
|
.dot.off { background: var(--text-4); }
|
||||||
|
@keyframes pulse { 50% { opacity: 0.4; } }
|
||||||
|
|
||||||
|
/* ============ LAYOUT A: grade-centric ============ */
|
||||||
|
.layoutA { display: grid; grid-template-columns: 232px 1fr 300px; height: 660px; }
|
||||||
|
.colA { border-right: 1px solid var(--hairline); background: var(--bg-1);
|
||||||
|
display: flex; flex-direction: column; }
|
||||||
|
.slot { margin: 0 8px 8px; border: 1px solid var(--hairline); border-radius: 5px;
|
||||||
|
background: var(--bg-2); padding: 10px 12px; }
|
||||||
|
.slot.active { border-color: var(--accent); background: var(--accent-soft); }
|
||||||
|
.slot .row1 { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
|
||||||
|
.slot .name { font-weight: 600; font-size: 12.5px; flex: 1; }
|
||||||
|
.slot .meta { font-family: var(--mono); font-size: 10.5px; color: var(--text-3);
|
||||||
|
display: flex; gap: 10px; }
|
||||||
|
.gang { margin: auto 8px 12px; padding: 10px 12px; border: 1px dashed var(--hairline-2);
|
||||||
|
border-radius: 5px; color: var(--text-3); font-size: 11.5px; }
|
||||||
|
.gang b { color: var(--accent-text); font-weight: 600; }
|
||||||
|
|
||||||
|
.center { background: var(--bg-0); display: flex; flex-direction: column; }
|
||||||
|
.preview { flex: 1; margin: 12px; border-radius: 6px; background:
|
||||||
|
linear-gradient(135deg, #1a1d24 0%, #232833 50%, #1a1d24 100%);
|
||||||
|
border: 1px solid var(--hairline); position: relative; min-height: 260px; }
|
||||||
|
.preview .tc { position: absolute; top: 10px; right: 12px; font-family: var(--mono);
|
||||||
|
font-size: 13px; color: var(--text-2); background: rgba(0,0,0,0.55);
|
||||||
|
padding: 3px 8px; border-radius: 4px; }
|
||||||
|
.preview .cam { position: absolute; top: 10px; left: 12px; font-family: var(--mono);
|
||||||
|
font-size: 11px; color: var(--accent-text); background: rgba(0,0,0,0.55);
|
||||||
|
padding: 3px 8px; border-radius: 4px; }
|
||||||
|
.preview .recbug { position: absolute; bottom: 10px; left: 12px; display: flex;
|
||||||
|
align-items: center; gap: 6px; font-size: 11px; color: var(--live);
|
||||||
|
background: rgba(0,0,0,0.55); padding: 3px 8px; border-radius: 4px; }
|
||||||
|
.nodes { border-top: 1px solid var(--hairline); background: var(--bg-1); padding-bottom: 12px; }
|
||||||
|
.nodestrip { display: flex; gap: 8px; padding: 0 14px; }
|
||||||
|
.node { min-width: 118px; border: 1px solid var(--hairline-2); border-radius: 5px;
|
||||||
|
background: var(--bg-2); padding: 8px 10px; }
|
||||||
|
.node.sel { border-color: var(--accent); }
|
||||||
|
.node .k { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em;
|
||||||
|
color: var(--text-4); font-weight: 600; margin-bottom: 4px; }
|
||||||
|
.node .v { font-family: var(--mono); font-size: 11px; color: var(--text-2); line-height: 1.5; }
|
||||||
|
.node.bypass { opacity: 0.45; }
|
||||||
|
|
||||||
|
.colC { border-left: 1px solid var(--hairline); background: var(--bg-1); display: flex;
|
||||||
|
flex-direction: column; }
|
||||||
|
.shotrow { display: grid; grid-template-columns: 44px 1fr auto; gap: 10px; align-items: center;
|
||||||
|
padding: 8px 14px; border-bottom: 1px solid var(--hairline); }
|
||||||
|
.shotrow:hover { background: var(--hover-fill); }
|
||||||
|
.thumb { width: 44px; height: 26px; border-radius: 3px;
|
||||||
|
background: linear-gradient(135deg, #2a2f3a, #3a4150); }
|
||||||
|
.shotrow .cname { font-family: var(--mono); font-size: 11.5px; color: var(--text-1); }
|
||||||
|
.shotrow .ctc { font-family: var(--mono); font-size: 10px; color: var(--text-4); }
|
||||||
|
|
||||||
|
/* ============ LAYOUT B: library-centric ============ */
|
||||||
|
.layoutB { display: grid; grid-template-columns: 232px 1fr 320px; height: 660px; }
|
||||||
|
.libtable { flex: 1; overflow: hidden; }
|
||||||
|
.librow { display: grid; grid-template-columns: 56px 1.2fr 1fr 1fr 0.7fr 0.7fr auto;
|
||||||
|
gap: 12px; align-items: center; padding: 9px 14px;
|
||||||
|
border-bottom: 1px solid var(--hairline); font-size: 12px; }
|
||||||
|
.librow.head { color: var(--text-4); font-size: 10.5px; text-transform: uppercase;
|
||||||
|
letter-spacing: 0.12em; font-weight: 600; border-bottom: 1px solid var(--hairline-2); }
|
||||||
|
.librow:not(.head):hover { background: var(--hover-fill); }
|
||||||
|
.librow.sel { background: var(--accent-soft); }
|
||||||
|
.lthumb { width: 56px; height: 32px; border-radius: 3px;
|
||||||
|
background: linear-gradient(135deg, #2a2f3a, #3a4150); }
|
||||||
|
.side-section { border-bottom: 1px solid var(--hairline); padding-bottom: 10px; }
|
||||||
|
.kv { display: flex; justify-content: space-between; padding: 3px 14px; font-size: 11.5px; }
|
||||||
|
.kv .k { color: var(--text-4); }
|
||||||
|
.kv .v { font-family: var(--mono); color: var(--text-2); }
|
||||||
|
.treeitem { padding: 6px 14px; color: var(--text-2); font-size: 12.5px; display: flex;
|
||||||
|
gap: 8px; align-items: center; }
|
||||||
|
.treeitem.sel { background: var(--accent-soft); color: var(--accent-text);
|
||||||
|
border-left: 2px solid var(--accent); padding-left: 12px; }
|
||||||
|
.treeitem .cnt { margin-left: auto; font-family: var(--mono); font-size: 10.5px;
|
||||||
|
color: var(--text-4); }
|
||||||
|
.footnote { color: var(--text-4); font-size: 11.5px; margin-top: 10px; max-width: 720px;
|
||||||
|
line-height: 1.5; }
|
||||||
|
.verdict { margin-top: 40px; padding: 18px 20px; border: 1px solid var(--hairline-2);
|
||||||
|
border-radius: 8px; background: var(--bg-1); max-width: 1240px; }
|
||||||
|
.verdict h3 { font-size: 13px; color: var(--accent-text); margin-bottom: 8px; }
|
||||||
|
.verdict p { color: var(--text-2); font-size: 12.5px; line-height: 1.6; margin-bottom: 6px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>Forge — main window wireframes</h1>
|
||||||
|
<p class="intro">Two layout philosophies, both rendered in Dragonflight "Reel" tokens
|
||||||
|
(cinema blacks, amber accent as tally, broadcast red = recording only, mono for all
|
||||||
|
technical values, hairline separation, 10.5px eyebrows). Structure is macOS-native:
|
||||||
|
NavigationSplitView three-pane, real toolbar. Same skin — different center of gravity.</p>
|
||||||
|
|
||||||
|
<!-- ================= LAYOUT A ================= -->
|
||||||
|
<h2>Layout A — grade-centric ("Livegrade philosophy")</h2>
|
||||||
|
<p class="philosophy">The preview + node stack IS the app. Cameras left, shots accumulate
|
||||||
|
right as a passive log. Optimized for the 95% moment: DP behind you, trackball in hand,
|
||||||
|
grade now. Library is glanceable, not navigable.</p>
|
||||||
|
|
||||||
|
<div class="window">
|
||||||
|
<div class="titlebar"><div class="traffic"><span></span><span></span><span></span></div>
|
||||||
|
<div class="title">Forge — Day 03 · Project Nightfall</div></div>
|
||||||
|
<div class="toolbar">
|
||||||
|
<button class="tbtn primary">● Push Look</button>
|
||||||
|
<button class="tbtn">Grab Still</button>
|
||||||
|
<button class="tbtn">Bypass</button>
|
||||||
|
<div class="tspacer"></div>
|
||||||
|
<span class="badge ok">3 CAMERAS ONLINE</span>
|
||||||
|
<button class="tbtn">Export Day…</button>
|
||||||
|
</div>
|
||||||
|
<div class="layoutA">
|
||||||
|
<!-- left: camera slots -->
|
||||||
|
<div class="colA">
|
||||||
|
<div class="eyebrow">Camera Slots</div>
|
||||||
|
<div class="slot active">
|
||||||
|
<div class="row1"><span class="dot rec"></span><span class="name">A — ALEXA 35</span>
|
||||||
|
<span class="badge rec">REC</span></div>
|
||||||
|
<div class="meta"><span>R001C007</span><span>EI 800</span><span>5600K</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="slot">
|
||||||
|
<div class="row1"><span class="dot ok"></span><span class="name">B — V-RAPTOR</span>
|
||||||
|
<span class="badge ok">CDL</span></div>
|
||||||
|
<div class="meta"><span>B001_C012</span><span>ISO 800</span><span>24.0</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="slot">
|
||||||
|
<div class="row1"><span class="dot off"></span><span class="name">C — VENICE 2</span>
|
||||||
|
<span class="badge neutral">MONITOR</span></div>
|
||||||
|
<div class="meta"><span>—</span><span>SDI chain</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="gang">GANG: <b>A + B linked</b> · edits propagate · C solo</div>
|
||||||
|
</div>
|
||||||
|
<!-- center: preview + nodes -->
|
||||||
|
<div class="center">
|
||||||
|
<div class="preview">
|
||||||
|
<span class="cam">A · LogC4 → Rec709</span>
|
||||||
|
<span class="tc mono">14:23:07:11</span>
|
||||||
|
<span class="recbug"><span class="dot rec"></span>REC R001C007</span>
|
||||||
|
</div>
|
||||||
|
<div class="nodes">
|
||||||
|
<div class="eyebrow">Node Stack — A (ganged with B)</div>
|
||||||
|
<div class="nodestrip">
|
||||||
|
<div class="node"><div class="k">Input</div><div class="v">LogC4 / AWG4</div></div>
|
||||||
|
<div class="node sel"><div class="k">CDL · native</div>
|
||||||
|
<div class="v">S 1.12 0.98 1.04<br>O +.02 .00 −.01<br>P 0.96 1.00 1.02 · Sat 1.10</div></div>
|
||||||
|
<div class="node"><div class="k">Curves</div><div class="v">master +2pt</div></div>
|
||||||
|
<div class="node bypass"><div class="k">Sat</div><div class="v">0.92 · bypassed</div></div>
|
||||||
|
<div class="node"><div class="k">LUT</div><div class="v">K1S1_Film.cube</div></div>
|
||||||
|
<div class="node"><div class="k">Output</div><div class="v">Rec709 2.4</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- right: shot log -->
|
||||||
|
<div class="colC">
|
||||||
|
<div class="eyebrow">Today — 23 Shots</div>
|
||||||
|
<div class="shotrow"><div class="thumb"></div>
|
||||||
|
<div><div class="cname">R001C007</div><div class="ctc">14:22:31 → rolling</div></div>
|
||||||
|
<span class="badge rec">REC</span></div>
|
||||||
|
<div class="shotrow"><div class="thumb"></div>
|
||||||
|
<div><div class="cname">R001C006</div><div class="ctc">14:18:02 → 14:19:44</div></div>
|
||||||
|
<span class="badge neutral">A</span></div>
|
||||||
|
<div class="shotrow"><div class="thumb"></div>
|
||||||
|
<div><div class="cname">B001_C012</div><div class="ctc">14:17:58 → 14:19:41</div></div>
|
||||||
|
<span class="badge neutral">B</span></div>
|
||||||
|
<div class="shotrow"><div class="thumb"></div>
|
||||||
|
<div><div class="cname">R001C005</div><div class="ctc">13:58:11 → 14:01:03</div></div>
|
||||||
|
<span class="badge neutral">A</span></div>
|
||||||
|
<div class="shotrow"><div class="thumb"></div>
|
||||||
|
<div><div class="cname">R001C004</div><div class="ctc">13:41:47 → 13:44:12</div></div>
|
||||||
|
<span class="badge neutral">A</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="footnote">Trackball focus always lands on the selected node of the active slot.
|
||||||
|
Slot switch = one keystroke / panel button. Shot log rows are read-only here — clicking
|
||||||
|
one recalls its grade as a new version, never edits history.</p>
|
||||||
|
|
||||||
|
<!-- ================= LAYOUT B ================= -->
|
||||||
|
<h2>Layout B — library-centric ("Silverstack philosophy")</h2>
|
||||||
|
<p class="philosophy">The shot table IS the app. Days/bins tree left, big sortable clip
|
||||||
|
table center, inspector right with grade + metadata for selection. Live grading is a mode
|
||||||
|
the inspector enters when a camera is selected. Optimized for data management, review,
|
||||||
|
exports — the DIT-cart-as-workstation story.</p>
|
||||||
|
|
||||||
|
<div class="window">
|
||||||
|
<div class="titlebar"><div class="traffic"><span></span><span></span><span></span></div>
|
||||||
|
<div class="title">Forge — Project Nightfall</div></div>
|
||||||
|
<div class="toolbar">
|
||||||
|
<button class="tbtn">Offload…</button>
|
||||||
|
<button class="tbtn">Verify</button>
|
||||||
|
<button class="tbtn">Proxies…</button>
|
||||||
|
<div class="tspacer"></div>
|
||||||
|
<span class="badge rec">A REC</span>
|
||||||
|
<button class="tbtn primary">Reports…</button>
|
||||||
|
</div>
|
||||||
|
<div class="layoutB">
|
||||||
|
<!-- left: project tree -->
|
||||||
|
<div class="colA">
|
||||||
|
<div class="eyebrow">Project</div>
|
||||||
|
<div class="treeitem">Day 01 <span class="cnt">41</span></div>
|
||||||
|
<div class="treeitem">Day 02 <span class="cnt">38</span></div>
|
||||||
|
<div class="treeitem sel">Day 03 <span class="cnt">23</span></div>
|
||||||
|
<div class="eyebrow">Cameras</div>
|
||||||
|
<div class="treeitem"><span class="dot rec"></span> A — ALEXA 35</div>
|
||||||
|
<div class="treeitem"><span class="dot ok"></span> B — V-RAPTOR</div>
|
||||||
|
<div class="treeitem"><span class="dot off"></span> C — VENICE 2</div>
|
||||||
|
<div class="eyebrow">Jobs</div>
|
||||||
|
<div class="treeitem">Offload A001 <span class="cnt">✓</span></div>
|
||||||
|
<div class="treeitem">Proxies Day 02 <span class="cnt">72%</span></div>
|
||||||
|
</div>
|
||||||
|
<!-- center: clip table -->
|
||||||
|
<div class="center">
|
||||||
|
<div class="libtable">
|
||||||
|
<div class="librow head"><span></span><span>Clip</span><span>TC In / Out</span>
|
||||||
|
<span>Camera · Look</span><span>EI / WB</span><span>Grade</span><span></span></div>
|
||||||
|
<div class="librow"><div class="lthumb"></div>
|
||||||
|
<span class="mono">R001C007</span>
|
||||||
|
<span class="mono" style="color:var(--text-3)">14:22:31 / —</span>
|
||||||
|
<span>A · K1S1_Film</span><span class="mono" style="color:var(--text-3)">800 · 5600K</span>
|
||||||
|
<span class="badge ok">CDL+LUT</span><span class="badge rec">REC</span></div>
|
||||||
|
<div class="librow sel"><div class="lthumb"></div>
|
||||||
|
<span class="mono">R001C006</span>
|
||||||
|
<span class="mono" style="color:var(--text-3)">14:18:02 / 14:19:44</span>
|
||||||
|
<span>A · K1S1_Film</span><span class="mono" style="color:var(--text-3)">800 · 5600K</span>
|
||||||
|
<span class="badge ok">CDL+LUT</span><span></span></div>
|
||||||
|
<div class="librow"><div class="lthumb"></div>
|
||||||
|
<span class="mono">B001_C012</span>
|
||||||
|
<span class="mono" style="color:var(--text-3)">14:17:58 / 14:19:41</span>
|
||||||
|
<span>B · CDL only</span><span class="mono" style="color:var(--text-3)">800 · 5600K</span>
|
||||||
|
<span class="badge ok">CDL</span><span></span></div>
|
||||||
|
<div class="librow"><div class="lthumb"></div>
|
||||||
|
<span class="mono">R001C005</span>
|
||||||
|
<span class="mono" style="color:var(--text-3)">13:58:11 / 14:01:03</span>
|
||||||
|
<span>A · K1S1_Film</span><span class="mono" style="color:var(--text-3)">800 · 5600K</span>
|
||||||
|
<span class="badge ok">CDL+LUT</span><span></span></div>
|
||||||
|
<div class="librow"><div class="lthumb"></div>
|
||||||
|
<span class="mono">R001C004</span>
|
||||||
|
<span class="mono" style="color:var(--text-3)">13:41:47 / 13:44:12</span>
|
||||||
|
<span>A · K1S1_Film</span><span class="mono" style="color:var(--text-3)">800 · 5600K</span>
|
||||||
|
<span class="badge ok">CDL+LUT</span><span></span></div>
|
||||||
|
<div class="librow"><div class="lthumb"></div>
|
||||||
|
<span class="mono">R001C003</span>
|
||||||
|
<span class="mono" style="color:var(--text-3)">13:22:09 / 13:25:40</span>
|
||||||
|
<span>A · K1S1_Film</span><span class="mono" style="color:var(--text-3)">1280 · 3200K</span>
|
||||||
|
<span class="badge ok">CDL+LUT</span><span></span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- right: inspector -->
|
||||||
|
<div class="colC">
|
||||||
|
<div class="eyebrow">Inspector — R001C006</div>
|
||||||
|
<div class="side-section">
|
||||||
|
<div class="preview" style="height:120px; margin:0 14px 10px; flex:none;"></div>
|
||||||
|
<div class="kv"><span class="k">Duration</span><span class="v">00:01:42:03</span></div>
|
||||||
|
<div class="kv"><span class="k">EI / WB / Tint</span><span class="v">800 / 5600K / 0</span></div>
|
||||||
|
<div class="kv"><span class="k">FPS</span><span class="v">24.000</span></div>
|
||||||
|
<div class="kv"><span class="k">Offload</span><span class="v" style="color:var(--success)">verified ×2</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="eyebrow">Grade Snapshot</div>
|
||||||
|
<div class="side-section">
|
||||||
|
<div class="kv"><span class="k">Slope</span><span class="v">1.12 0.98 1.04</span></div>
|
||||||
|
<div class="kv"><span class="k">Offset</span><span class="v">+.02 .00 −.01</span></div>
|
||||||
|
<div class="kv"><span class="k">Power</span><span class="v">0.96 1.00 1.02</span></div>
|
||||||
|
<div class="kv"><span class="k">Sat</span><span class="v">1.10</span></div>
|
||||||
|
<div class="kv"><span class="k">LUT</span><span class="v">K1S1_Film.cube</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="eyebrow">Actions</div>
|
||||||
|
<div style="padding: 4px 14px; display:flex; gap:8px; flex-wrap:wrap;">
|
||||||
|
<button class="tbtn">Recall Grade</button>
|
||||||
|
<button class="tbtn">Export CDL</button>
|
||||||
|
<button class="tbtn">Still</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="footnote">Grading here happens in the inspector (or a summonable grade drawer) —
|
||||||
|
one step removed from the image. Stronger for offload/verify/report days; weaker for
|
||||||
|
the "roll sound, grade now" moment.</p>
|
||||||
|
|
||||||
|
<div class="verdict">
|
||||||
|
<h3>Recommendation</h3>
|
||||||
|
<p><b>Layout A as the main window, with B's table one ⌘-key away (Library tab/window).</b>
|
||||||
|
Forge's differentiator is in-camera live grading — the app should open into the moment
|
||||||
|
it wins. The library table (B) is genuinely better for end-of-day work, so ship it as a
|
||||||
|
second surface using the same panes, not a compromise hybrid of both.</p>
|
||||||
|
<p>Shared skin either way: bg-0 chrome, amber tally accent, #FF3B30 strictly for REC,
|
||||||
|
SF Mono for TC/CDL/clip names, hairline dividers, 10.5px eyebrows — family resemblance
|
||||||
|
to dragonflight without pretending to be a web app.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
66
docs/plans/002-roadmap-feature-gaps.md
Normal file
66
docs/plans/002-roadmap-feature-gaps.md
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Roadmap 002 — Feature gaps vs Pomfort (from competitive research)
|
||||||
|
|
||||||
|
Source: docs/research/livegrade-silverstack-research.md + protocol research docs.
|
||||||
|
Status of core: 200 tests green; ARRI CAP + RED RCP2 drivers wire-verified; Sony monitoring-only.
|
||||||
|
|
||||||
|
## Tier 1 — differentiators / near-term (build next)
|
||||||
|
|
||||||
|
### T1.1 Look-match bridge (the Pomfort two-product moat, ours for free)
|
||||||
|
Grade snapshots already stored per shot keyed by clip name. Add:
|
||||||
|
- `forge ingest-match`: scan offloaded card, match clips to shot records by clip name,
|
||||||
|
auto-attach grade snapshot + emit per-clip .cdl/.cube alongside media
|
||||||
|
- This is Livegrade→Silverstack ShotHub flow without the cloud. Sister-product hook for
|
||||||
|
dragonflight later (shared JSON grade snapshot format already deterministic).
|
||||||
|
|
||||||
|
### T1.2 Offload scheduler upgrade (biggest Lab-parity gap)
|
||||||
|
- Separate copy vs verify jobs (verify-later scheduling)
|
||||||
|
- Per-drive concurrency caps (don't saturate slow shuttle drives)
|
||||||
|
- Source re-read verification mode (card read integrity, not just copy)
|
||||||
|
- Cascading offload (fast RAID first, then RAID→LTO/archive as second-stage job)
|
||||||
|
- Job model: small DAG, per-resource queues. ForgeOffload already has verified-copy core.
|
||||||
|
|
||||||
|
### T1.3 Checksum breadth
|
||||||
|
- Add XXH3/XXH128 (ASC MHL v2 supports both; spec'd) + C4ID (entertainment standard)
|
||||||
|
- SHA1 for legacy post houses. All slot into FileHasher + MHL writer cleanly.
|
||||||
|
|
||||||
|
### T1.4 Report engine
|
||||||
|
- PDF/HTML shot reports w/ still thumbnails + grades (library has stills + snapshots)
|
||||||
|
- Offload reports already HTML — unify styling w/ Reel design tokens.
|
||||||
|
|
||||||
|
## Tier 2 — solid adds
|
||||||
|
|
||||||
|
### T2.1 Grading model extensions
|
||||||
|
- Printer lights + LGG interaction modes over existing CDL (interaction layer, same math)
|
||||||
|
- HSL secondaries node; 1D LUT node
|
||||||
|
- ACES: IDT/ODT via existing ColorSpace machinery; AMF export later
|
||||||
|
|
||||||
|
### T2.2 Stream Deck + MIDI control
|
||||||
|
- DITs own Stream Decks. Cheap panel option beside Tangent. ForgePanel action model
|
||||||
|
already abstracted (PanelAction) — new input adapters only.
|
||||||
|
|
||||||
|
### T2.3 Slot filters (non-grade image ops)
|
||||||
|
- Frame lines, anamorphic desqueeze, flip, metadata burn-in as per-slot filter chain
|
||||||
|
in preview/output path (ForgeVideo FrameProcessor extension).
|
||||||
|
|
||||||
|
### T2.4 Audio/LTC (dailies-tier)
|
||||||
|
- BWF detection + LTC-from-audio TC extraction + auto sync. Feeds proxy engine.
|
||||||
|
|
||||||
|
## Tier 3 — explicitly deferred (Pomfort sells these as paid add-ons = niche signal)
|
||||||
|
- LED wall control, internet streaming, chroma keyer, composite multi-view slots,
|
||||||
|
50-input routing, LTFS/LTO, RAW debayer playback (huge scope; proxies via ffmpeg
|
||||||
|
sidestep), NDI input, router control (KUMO/Videohub).
|
||||||
|
|
||||||
|
## Verified protocol status (carry-forward)
|
||||||
|
| Camera | Transport | Look push | State |
|
||||||
|
|---|---|---|---|
|
||||||
|
| ARRI Alexa 35 / Mini LF | CAP binary TCP :5055 | CDL native (0x0050) + LUT experimental | driver rewritten, sim-verified |
|
||||||
|
| RED DSMC3 | RCP2 WebSocket :9998/rcp | CDL native (per-channel params), no live LUT | driver rewritten, sim-verified |
|
||||||
|
| Sony Venice 2 | closed (web remote only public) | none claimed | monitoring-only; SDI-chain grading path |
|
||||||
|
|
||||||
|
Note: Livegrade 7.2 ships Venice 2 in-camera grading — proves a partner wire path exists.
|
||||||
|
Escalation: Sony partner SDK or packet capture on hardware.
|
||||||
|
|
||||||
|
## Hardware-phase checklist (macOS, unchanged from plan 001 Phase 6)
|
||||||
|
1. SwiftUI shell + Metal preview + DeckLink + Tangent Hub TIPC
|
||||||
|
2. On-hardware verification: CAP port/MD5-concat-order/LUT chunking; RCP2 against Komodo;
|
||||||
|
Venice web-remote backend capture
|
||||||
Loading…
Reference in a new issue