Skip to content

Flow builder: aspect-ratio-aware display + visual crop (#668) - #700

Open
mcarlson wants to merge 6 commits into
stagefrom
feat/flow-aspect-ratio-crop
Open

Flow builder: aspect-ratio-aware display + visual crop (#668)#700
mcarlson wants to merge 6 commits into
stagefrom
feat/flow-aspect-ratio-crop

Conversation

@mcarlson

@mcarlson mcarlson commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

What & why

Fixes #668 — the studio flow builder rendered every keyframe in a fixed 140×100 object-fit: cover box, hiding each image's true aspect ratio. A stray portrait image slipped through unnoticed and the generated video came out distorted.

Per the issue thread (crop to match the video output) the flow now commits to a single output shape and crops keyframes to it — a transition clip can't morph between two shapes, so one shape is required.

🎥 Demo (local, against staging)

https://drive.google.com/file/d/1G26joyxWXjn7Qnp-8n_wdBi0lB91w5aC/view?usp=sharing

How it works

  • Majority wins. The auto output ratio is the most common keyframe shape. Frames that already match are left untouched — only the odd-aspect image(s) get cropped, flagged with a CROPPED badge in the strip.
  • Honest strip. Cards are sized to the output ratio and render each frame's effective crop, so the strip shows exactly what the video will use.
  • Visual crop editor. Click a frame's crop button → aspect-locked frame with a rule-of-thirds grid; drag to reposition, slide to zoom, reset-to-center. Picks the exact region kept.
  • Output-ratio selector. Auto (…) + 16:9 / 9:16 / 1:1 / 4:3 / 3:4 override in the settings panel.
  • Crop-on-generate. Before each i2v job, keyframes are cropped client-side (canvas) to the output shape and re-uploaded as image Dreams — the only way to honor an arbitrary user-selected region across models (server can only center-crop). Cached by a (sourceDream, crop, ratio) signature so unchanged crops don't re-upload; full-frame (already-matching) frames skip re-upload; crop/upload failures fall back to the original image (Bugsnag-logged).

Crops are derived (userCrop ?? centerCrop(for majority ratio)), so a majority shift or ratio override just recomputes — no stale state.

Scope notes

  • Frontend-only; no worker/backend changes.
  • flow.store bumped to v5 with a migration (defaults globalAspectRatio: "auto"); new per-keyframe fields persisted only for settled keyframes.

Testing

  • 136 unit tests pass (Vitest), incl. 30 new for crop geometry / majority resolution and store behavior; tsc --noEmit and ESLint clean.
  • Manually verified end-to-end against staging (proxy mode): honest strip, majority auto-shape with only the oddball cropped, crop editor drag/zoom, and ratio overrides — see video.

claude --resume bacf1207-b5e8-4df3-a36d-89b69e54bc91

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 30, 2026

Copy link
Copy Markdown

Deploying frontend-alpha with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1e43174
Status: ✅  Deploy successful!
Preview URL: https://1a85599e.frontend-btm.pages.dev
Branch Preview URL: https://feat-flow-aspect-ratio-crop.frontend-btm.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 30, 2026

Copy link
Copy Markdown

Deploying frontend-stage with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1e43174
Status: ✅  Deploy successful!
Preview URL: https://6c9d91d9.frontend-d7v.pages.dev
Branch Preview URL: https://feat-flow-aspect-ratio-crop.frontend-d7v.pages.dev

View logs

mcarlson and others added 5 commits July 30, 2026 17:11
Center-crop geometry, aspect-locked clamp, pixel conversion, preset/size
mapping, and a cache signature for the flow aspect-ratio crop feature.
23 unit tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add globalAspectRatio (auto|preset) with setGlobalAspectRatio that re-fits
every keyframe crop in the same set(). Add setKeyframeDimensions (seeds a
center crop on image load) and setKeyframeCrop (persists an editor selection
and invalidates the reupload cache). Extend FlowKeyframe with naturalWidth/
Height, crop, and croppedDreamUuid/Signature. Persist the new fields for
settled keyframes only; bump store to v5 with a migration.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Before generating each transition, crop both keyframes client-side to the
flow's output ratio (canvas), re-upload as image Dreams, and feed those UUIDs
to the i2v job — with a per-keyframe signature cache so unchanged crops don't
re-upload. Pass a matching size string so wan-i2v stops hard-coding 16:9.
Crop/upload failures fall back to the original image (Bugsnag-logged) so a
CORS/network hiccup degrades gracefully. Full-frame crops (source already
matches) skip the reupload.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Keyframe cards size to the output ratio and render each frame's stored crop,
  so the strip shows the real shape (no more hidden portrait/landscape).
- Capture natural dimensions on image load to seed a default center crop.
- Output aspect-ratio selector (auto + presets) in the settings panel; auto
  shows the ratio it resolves to.
- Visual crop editor modal: aspect-locked frame, drag to reposition, slider to
  zoom, rule-of-thirds grid, reset-to-center. Saves a normalized crop region.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Auto output ratio now derives from the MAJORITY keyframe shape (not the first
frame), so frames that already match are left untouched and only the odd-aspect
image(s) get cropped. Crops are derived (userCrop ?? centerCrop) rather than
eagerly seeded, so a majority shift or ratio override just recomputes; explicit
overrides clear stale user crops. Cropped frames get a 'cropped' badge in the
strip so the oddball is obvious. majorityPresetRatio + resolveFlowRatio added
with tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mcarlson
mcarlson force-pushed the feat/flow-aspect-ratio-crop branch from 62d3c2c to 2188aa5 Compare July 30, 2026 14:15
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

2 participants