From 20af1b20c26527d9de4ef785175c444fa9873b4e Mon Sep 17 00:00:00 2001 From: type-two Date: Mon, 20 Jul 2026 17:51:28 +1000 Subject: [PATCH] =?UTF-8?q?[m5+m6]=20DIRECTOR=20MODE=20+=20FLOW=20VIDEO=20?= =?UTF-8?q?PLATES=20=E2=80=94=20all=20lanes=20+=20sync6=20seam=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lane A: grammar.js (shot/angle/focal/light/mark data), presets.js (bbox shot solver, light/mark appliers, DIRECT bar UI, NL box), stage video plates (VideoTexture plane/corner/dome, screen kind, syncVideos), dock video cards. Lane B: scenegod:direct β†’ grouped-undo keys/cuts, πŸ—£ lip-sync from audio via /rhubarb, Cmd+wheel zoom / wheel scroll, audio trim, video clock-follow via nullable entityVideo seam. Lane C: POST /director (LLM proxy, server-side op validation vs vocab+scene, mock-tested), render.js awaits stage.syncVideos. Sync6 (orchestrator): VIDEO_EXTS in server tree/media types (video primary, img poster as thumb), stage.entityVideo accessor, syncVideos forces videoTex.needsUpdate (rVFC never fires in hidden tabs β†’ black plates). Verified: 9 server groups + timeline + presets suites green; browser SYNC: one-click MCU framing lands camera+fov keys+cut (single undo), golden_hour relight keys, plate scrub-follow frame-exact, finalRender mp4 shows the Flow golden-hour street plate behind an animated character. Co-Authored-By: Claude Fable 5 --- lanes/A-stage.md | 11 ++ lanes/B-timeline.md | 11 ++ lanes/C-server.md | 11 ++ logs/laneA.md | 110 +++++++++++++++ logs/laneB.md | 70 +++++++++ logs/laneC.md | 49 +++++++ scenegod/server.py | 128 ++++++++++++++++- scenegod/web/dock.js | 57 ++++++-- scenegod/web/grammar.js | 57 ++++++++ scenegod/web/index.html | 7 + scenegod/web/presets.js | 249 +++++++++++++++++++++++++++++++++ scenegod/web/presets_test.mjs | 61 ++++++++ scenegod/web/render.js | 1 + scenegod/web/stage.js | 161 ++++++++++++++++++--- scenegod/web/stagestub.js | 25 +++- scenegod/web/style.css | 22 +++ scenegod/web/timeline.js | 121 +++++++++++++++- scenegod/web/timeline_test.mjs | 123 ++++++++++++++++ scenegod/web/tlui.js | 115 +++++++++++++-- scripts/test_server.py | 70 +++++++++ 20 files changed, 1407 insertions(+), 52 deletions(-) create mode 100644 scenegod/web/grammar.js create mode 100644 scenegod/web/presets.js create mode 100644 scenegod/web/presets_test.mjs diff --git a/lanes/A-stage.md b/lanes/A-stage.md index bab4a9b..b05ad5d 100644 --- a/lanes/A-stage.md +++ b/lanes/A-stage.md @@ -206,3 +206,14 @@ as keys via B (scrub proves it) and is undo-able. ### 2026-07-19 β€” M6 FLOW VIDEO PLATES queued behind M5 (full spec PLAN Β§5 M6). Do M5 first; M6 is unlocked the moment your M5 acceptance is logged. Test media will be arriving in assets/backdrops/video/ via scripts/flow_intake.py. + +### 2026-07-20 β€” M5+M6 ACCEPTED at SYNC 6 (all lanes ran as orchestrator subagents). +Verified live: DIRECT bar CU/low/frame β†’ camera+keys+cut, ONE undo reverts; +golden_hour keys; video plate follows the clock frame-exact; finalRender shows +the Flow plate behind an animating character. Orchestrator seam fixes to absorb: +(1) server: VIDEO_EXTS in tree/media-types, video beats poster as primary; +(2) stage.entityVideo(id) added (Lane B seam); (3) syncVideos forces +videoTex.needsUpdate β€” r160 VideoTexture rides requestVideoFrameCallback which +never fires in hidden tabs β†’ black plates in renders. Backlog carried: honor +audio in/out at mux (C), walk-to-mark prevPos pre-apply (A), live viseme asset +still owed by John. diff --git a/lanes/B-timeline.md b/lanes/B-timeline.md index 0c22c39..6f0b933 100644 --- a/lanes/B-timeline.md +++ b/lanes/B-timeline.md @@ -166,3 +166,14 @@ discover the panel scrolls β€” consider wheel = scroll, Cmd/Ctrl+wheel = zoom. ### 2026-07-19 β€” M6 FLOW VIDEO PLATES queued behind M5 (full spec PLAN Β§5 M6). Do M5 first; M6 is unlocked the moment your M5 acceptance is logged. Test media will be arriving in assets/backdrops/video/ via scripts/flow_intake.py. + +### 2026-07-20 β€” M5+M6 ACCEPTED at SYNC 6 (all lanes ran as orchestrator subagents). +Verified live: DIRECT bar CU/low/frame β†’ camera+keys+cut, ONE undo reverts; +golden_hour keys; video plate follows the clock frame-exact; finalRender shows +the Flow plate behind an animating character. Orchestrator seam fixes to absorb: +(1) server: VIDEO_EXTS in tree/media-types, video beats poster as primary; +(2) stage.entityVideo(id) added (Lane B seam); (3) syncVideos forces +videoTex.needsUpdate β€” r160 VideoTexture rides requestVideoFrameCallback which +never fires in hidden tabs β†’ black plates in renders. Backlog carried: honor +audio in/out at mux (C), walk-to-mark prevPos pre-apply (A), live viseme asset +still owed by John. diff --git a/lanes/C-server.md b/lanes/C-server.md index 32a90e8..470c478 100644 --- a/lanes/C-server.md +++ b/lanes/C-server.md @@ -161,3 +161,14 @@ it needs more than that. ### 2026-07-19 β€” M6 FLOW VIDEO PLATES queued behind M5 (full spec PLAN Β§5 M6). Do M5 first; M6 is unlocked the moment your M5 acceptance is logged. Test media will be arriving in assets/backdrops/video/ via scripts/flow_intake.py. + +### 2026-07-20 β€” M5+M6 ACCEPTED at SYNC 6 (all lanes ran as orchestrator subagents). +Verified live: DIRECT bar CU/low/frame β†’ camera+keys+cut, ONE undo reverts; +golden_hour keys; video plate follows the clock frame-exact; finalRender shows +the Flow plate behind an animating character. Orchestrator seam fixes to absorb: +(1) server: VIDEO_EXTS in tree/media-types, video beats poster as primary; +(2) stage.entityVideo(id) added (Lane B seam); (3) syncVideos forces +videoTex.needsUpdate β€” r160 VideoTexture rides requestVideoFrameCallback which +never fires in hidden tabs β†’ black plates in renders. Backlog carried: honor +audio in/out at mux (C), walk-to-mark prevPos pre-apply (A), live viseme asset +still owed by John. diff --git a/logs/laneA.md b/logs/laneA.md index c17d7f4..b78242e 100644 --- a/logs/laneA.md +++ b/logs/laneA.md @@ -185,3 +185,113 @@ BLOCKED/REQUESTS: I'll confirm live and Lane B can validate Rhubarb end-to-end. NEXT: hold at M4-A boundary. Available for a live viseme asset check and any SYNC findings. + +## 2026-07-20 session 5 (M5 DIRECTOR MODE + M6 FLOW VIDEO PLATES) +DONE β€” both milestones, headless-verified (no browser/servers touched per orchestrator order): + +M5: +- `web/grammar.js` (NEW, pure data, zero imports): SHOTS (exact spans/centers from the lane + spec), ANGLES (eye/low βˆ’18Β°/high +22Β°/dutch 8Β° roll/ots_L/ots_R), FOCALS [18,24,35,50,85], + LIGHTS (day/golden_hour/night/noir/horror-underlight/neon/overcast β€” {sun{color,intensity, + elev,azim}, ambient{color,intensity}, bg}), MARKS (center/two_shot_L/R/face_camera/face_other). +- `web/presets.js` (NEW, NO three.js import β€” node-runnable): fovForFocal (presets.js:11), + lookAtEuler w/ dutch roll + three-matching XYZ euler extraction (:14), solveShot bboxβ†’ + pos/rot/fov/dist deterministic solver incl. OTS over-the-shoulder placement (:37), + frameSubject (:62, bbox via new stage.entityBBox), applyLight (:75 β€” ensures/reuses one + sun+ambient pair, writes grammar values verbatim, aims a 20m sun boom via lookAtEuler, + background rides the AMBIENT entity as param `bg` so it's keyable AND survives save/load), + applyMark (:99, pos marks keep y; face marks yaw toward active cam / nearest character), + applyOps (:139) β€” ONE op runner shared by panel buttons and /director NL, fires + `scenegod:direct {op, ...values, entityIds}` per action (B keys them; I never touch the + timeline), mountDirectPanel (:174) β€” shot/angle/lens segments + πŸŽ₯ frame, light buttons, + mark buttons, NL box. +- NL box: POST /director {text, selected, entities:[{id,kind,label}]} β†’ expects {ops:[...]}, + applied via applyOps. Hidden by default; probe `GET /director` shows it on 405/200 (FastAPI + 405 = POST route exists); hides itself again when a POST returns 503. +- index.html:14 `#direct` bar + guarded dynamic import (:49) β€” page survives presets.js absent. + style.css:85 DIRECT styles (before the LANE B marker). +- stage.js additions for M5: entityBBox (stage.js:490, plain arrays β€” keeps presets three-free), + cameraWorldPos (:497), light param `bg` β†’ scene.background live (:393) + restored at + _buildLight (:335) so a loaded scene gets its sky back. + +M6: +- `_buildBackdrop` rework (stage.js:225): params.mode gains "video" (renders as plane), and + plane/corner/dome accept .mp4/.webm/.mov sources; THREE.VideoTexture muted+loop+playsInline, + SRGB; poster jpg (server /assets/thumb same-stem sidecar) shown until first play/seek then + swapped in via _swapOnPlay (:309). Standalone page (no timeline β†’ _mixerAuto) auto-plays as + ambient preview; with a timeline mounted videos stay paused at poster for B's clock. +- NEW kind `screen` (addEntity :165, _buildScreen :272): video plane, params {video,width, + emissive}, MeshStandard + emissiveMap boost (default 0.6) so club screens read "on" under + noir/night. ponytail: CRT curve skipped until a real TV asset asks. +- `stage.syncVideos(t)` (:506): seeks every video to ((tβˆ’videoStart) mod duration), pauses, + awaits 'seeked' per video (1.5s timeout guard so a stuck decoder can't hang a render), skips + sub-4ms deltas. render.js already awaits it per frame (Lane C landed the hook). Plus + videos() (:501) + setVideoPlaying(on) (:503) for Lane B's clock-follow, and params.videoStart + plumbed (inspector fields, dock.js:214/220). +- dock.js: _videoPath (:86, derives . from formats), 🎞 badge + πŸ“Ί + add-as-screen button on video backdrop cards (:106), click/drag adds mode:'video' plates + (:132 and _viewDrop), local .mp4 drop β†’ upload video plate, screen/backdrop inspector fields + (width/emissive/vid start; mode select gains 'video'). +- Lifecycle: removeEntity/_rebuild release the