Skip to content

Panda video scaffold - #470

Closed
Philipcyrus wants to merge 11 commits into
calesthio:mainfrom
Philipcyrus:panda-video-scaffold
Closed

Panda video scaffold#470
Philipcyrus wants to merge 11 commits into
calesthio:mainfrom
Philipcyrus:panda-video-scaffold

Conversation

@Philipcyrus

@Philipcyrus Philipcyrus commented Aug 3, 2026

Copy link
Copy Markdown

No description provided.

Philipcyrus and others added 10 commits August 3, 2026 17:50
Panda Mobile agentic video pipeline on top of pristine upstream:
- pipeline_defs/panda-video.yaml: stages + 3 human-approval gates
  (script, storyboard stills, final video)
- skills/pipelines/panda-video/storyboard-director.md: one-still-per-scene then gate
- tools/video/montage_svc_compose.py: THE HINGE — compose delegates to montage-svc
- config/panda-elements.json: panda brand/element wiring (placeholders)
- styles/panda.yaml: look of generated imagery (overlays stay in montage-svc)

Ported from OpenMontage-main (NOT in upstream — verified):
- tools/video/higgsfield_mcp_video.py: Higgsfield MCP-bridge provider
- skills/meta/higgsfield-mcp-bridge.md: agent-side MCP protocol

SCAFFOLD: stubs carry TODOs; not yet runnable end to end. Prove the hinge first.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Consolidate to ONE deployable: vendor montage-svc's proven render pipeline
(vendor/montage_svc + vendor/brand) and call it in-process instead of over HTTP.

- tools/video/panda_render.py: CLEAN compose tool (ugc/no-brand profile), stages
  assets into a montage run and calls run_compose verbatim. Round-trip tested:
  1080x1920 h264, clips + xfade + audio mix, branded=False.
- pipeline_defs/panda-video.yaml: compose stage now uses panda_render; produces the
  clean master that hits GATE 3. Branding is explicitly NOT applied here.
- Removed tools/video/montage_svc_compose.py (the HTTP hinge) + MONTAGE_SVC_URL.
- vendor/data gitignored (render scratch).

Branding stays a separate, on-demand, post-approval step (panda_brand — next).
Per architecture decision: branding only when the user asks, on the approved master.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds vendor/brand/fonts/msyhbd.ttc = Noto Sans SC (SIL OFL), instanced to a static
Bold (wght=700), aliased to the filename the brand profiles expect. Replaces the
system dependency on proprietary Microsoft YaHei — the repo now renders Chinese
captions on Linux/EC2 with no font install step. OFL.txt + README included.

Verified: full SC glyph coverage (避坑套餐…), usWeightClass=700, CJK caption render
through panda_render succeeds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- brand/panda-mobile/mascot/Panda-Mobile-Smiling-Hero-Turnaround-v1.png (6336x2688)
- brand/panda-mobile/customer/Customer-V3-Hero-Turnaround-v1.png (6336x2688, new customer/)
- config/panda-elements.json: reference both as character-consistency master sheets
  (panda + customer), for seeding Higgsfield element ids.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The engine is not a service; this small FastAPI app is the networked surface Dify
talks to. It starts/resumes runs and surfaces the 3 approval gates, with local
file-based job storage (no S3/Postgres — Phase 5 deferred).

- app.py: POST /jobs, GET /jobs/{id}, POST /jobs/{id}/respond, GET artifacts, /health
- store.py: per-job local folder (state.json + artifacts/)
- runner.py: MockRunner (no LLM; fakes script/storyboard, REALLY renders a clean
  master via folded panda_render) + ClaudeCodeRunner skeleton (EC2 path)
- test_dify_flow.py: in-process mock-Dify test — PASSES the full gate handshake
  start -> script -> storyboard(+revision) -> real final.mp4 (branded=False) -> done
- Storyboard gate accepts user-supplied stills from Dify.

data/jobs/ gitignored. Swap MockRunner->claude + local storage->S3 on EC2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per request, generated motion clips now get their own human-approval gate before
assembly — not just stills and the final cut.

- panda-video.yaml: assets stage human_approval_default=true (GATE 3); final is GATE 4
- runner.py: new _do_clips (one clip per approved still); revise supports per-shot
  regeneration via {"decision":"revise","shots":[i,...]} — only those shots re-run;
  refactored resume() so revise regenerates the current gate's artifact
- app.py: Respond gains `shots`; test covers the clips gate + a per-shot revision

Flow verified end to end: script -> storyboard -> clips (+revise shot) -> final -> done.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Exact Dify workflow wiring: auth header, the gate loop, per-gate request/response
bodies, artifact fields to display, the polling requirement for the real agent,
a curl smoke test, and the deploy snippet to obtain {BASE_URL}.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Makes the repo clone-and-run ready on the box behind dev.om.mvnoc.ai:
- deploy/install.sh: system deps + venv + launcher deps + import/render smoke test
- deploy/panda-launcher.service: systemd (uvicorn 127.0.0.1:8600, --root-path /panda)
- deploy/nginx-panda.conf: reverse-proxy block (subpath or subdomain options)
- deploy/requirements-launcher.txt: minimal launcher+render deps
- deploy/README.md: end-to-end deploy steps

No secrets; .env is created from .env.example on the box.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ange

dev.om.mvnoc.ai already forwards to 8501; the launcher now listens there (montage-svc
retired, since its render is folded into the engine). So:
- systemd: uvicorn on 127.0.0.1:8501, no --root-path
- README: stop montage-svc, run launcher on 8501, proxy unchanged
- DIFY_INTEGRATION + curl: BASE_URL = https://dev.om.mvnoc.ai (root)
- nginx: documents "no change needed"; subdomain kept as optional

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ClaudeCodeRunner now drives Claude Code headless against the engine and adapts
OpenMontage's checkpoint system to the launcher gates:
- start/resume run `claude -p`; checkpoint-based resume (each leg reads latest checkpoint)
- _sync maps stage+status -> gate (script/scene_plan/assets/compose) and done/failed
- _mirror_artifacts copies project files into the job store, grouped stills/clips/final
- _approve_stage writes completed + human_approved to clear a gate
- config via CLAUDE_BIN/CLAUDE_EXTRA_ARGS/CLAUDE_TIMEOUT_S/PANDA_PIPELINE_TYPE

FIX: panda-video.yaml had stability: experimental (schema allows only production|beta)
and a non-schema `notes:` field — the whole manifest silently failed to load, so the
engine used the DEFAULT 9-stage pipeline and our gates were NOT enforced. Now loads as
idea/script/scene_plan/assets/edit/compose with gates on script/scene_plan/assets/compose.

test_claude_adapter.py verifies the adapter (mapping/mirroring/sync/approval) against the
real lib/checkpoint. Mock flow still passes. .env.example + README document the runner.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Philipcyrus
Philipcyrus requested a review from calesthio as a code owner August 3, 2026 14:53
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Philipcyrus Philipcyrus closed this by deleting the head repository Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant