Pelagic Video Fidelity

Why our AI-generated video ads were inventing logos, wordmarks, and construction details on real products — and how switching to real catalog photos, not a hand-written prompt, actually fixed it. A full trace from measurement through fix.

62%real master pass rate — not the 20% everyone assumed (that was a derive statistic)
4 / 4previously-broken ads fixed, once real catalog photos replaced the degraded reference stack
3real bugs found and fixed in the pipeline
~$15total spend across every experiment tonight

Headline finding: the fix that actually scales isn't a cleverer prompt — it's simpler than that. Feed the model real, undegraded catalog photos instead of the padded/AI-outpainted stack production has been building, and a fully generic prompt (no per-product authoring at all) gets every headline defect fixed. A hand-written, per-product prompt was tried first and looked like the answer — it wasn't. See Section 5.

Contents

  1. The real problem
  2. Three bugs found and fixed
  3. The Atlas outage
  4. Going direct: three providers compared
  5. The real fix — naming real marks
  6. Does this scale to production?
  7. Still running
  8. Spend summary
  9. Recommended next steps

1The real problem

Pelagic Gear's video ads were being judged as roughly 20% pass. That number was measuring the wrong thing.

189 "video ads" were actually 18 real generations plus 171 derives

A derive is a free crop/retitle of an already-existing master into a different aspect ratio — it never generates new pixels. Splitting the two out:

Pass rate
Real generations (masters)62% 8 of 13 judged
Derives of those masters16% 24 of 148

Worse: 44 derives of a passing master still failed, and 9 derives of a failing master passed. Production QC on a derive is largely noise — the ~20% headline number was a derive statistic, not a generation-quality statistic.

Even the real 62% wasn't the full story

Production's own quality check judges each video against the reference stack it was given — which is itself padded, cropped, or AI-outpainted, not the real product photo. Judging the same 14 masters directly against the native catalog photograph instead:

4 / 14clean against the real product photo
0ads production QC failed that were actually clean
4ads production QC passed that had real invented marks

2Three bugs found and fixed

A. A live money leak — refinedProducts missing from the catalog query

The code that decides "can we free-crop this reference, or do we have to pay for an AI outpaint" needs YOLO-detected product boxes. The query loading sibling reference images for a video simply never requested that field. Every auto-assembled sibling was forced onto the paid path regardless of whether a free crop was possible.

Found a teammate had already fixed this in a copy of the code that isn't the one actually running in production. Fixed in the live renderer, deployed.

B. Seed images padded at the wrong scale

The product-only seed image was padded to the video's delivery resolution (as small as 720×720 for the product itself) instead of the source photo's own resolution — throwing away most of the real detail before the video model ever saw it.

Fixed — pad now derives its canvas from the source image, preserving up to 3× more real pixels of the product.

C. The "zoom to detail" instruction was the single biggest source of invented defects

Counting every defect found across the 14-ad blind pass by the video timestamp it appeared at: the frame at the midpoint — exactly where the prompt says "slow zoom toward the most distinctive product detail" — carried 6 of 11 total defects. The zoom wasn't panning across real pixels; it was cutting to a newly generated close-up, and that's where the model invented things.

Partially addressed — see the real fix in Section 5, which supersedes the original "just remove the zoom" attempt.

3The Atlas outage — a real forensic trace

Partway through testing the fixes above, every 10-second/9:16 video regenerate started failing. Three ads produced videos that looked suspiciously identical to their originals. This needed a real answer, not a guess.

What was verified, directly against Atlas's own API

The exact same combination that had been generating successfully all day — duration=10, aspect_ratio=9:16 — started returning:

HTTP 500 → "All channels failed. Last error: HTTP 422:
The model 【omni_flash-10s-portrait】 does not exist"

Confirmed by fetching the byte hash of the "new" video and finding it identical to the pre-outage file — Atlas never generated anything new, and critically, never billed for it either. One real generation that landed during the same window (a different ad, retried automatically) proved the persist logic itself was fine — when Atlas returns a real video, it saves correctly. The failure was isolated to one internal Atlas routing channel for that specific duration+aspect combination, confirmed by direct API calls, not inferred.

A retry policy was also caught and stopped mid-flight — it was about to auto-resubmit two more ads into the same dead channel.

4Going direct — three video providers compared

The outage forced the question: could we bypass Atlas entirely and call the underlying model directly? Turns out yes — Atlas is a thin wrapper over Google's own gemini-omni-flash-preview model, and a direct API key was already available and already in use elsewhere in the codebase for other purposes.

Reference images actually supplied

Same three-image stack the production pipeline builds for every ad — shown here so the comparisons below are legible against real inputs, not assumed ones.

Reference 0 — padded product-only front
ref0 — padded product-only front (the seed)
Reference 1 — on-model full body
ref1 — on-model, full body
Reference 2 — waistband close-up
ref2 — waistband close-up (the only one that resolves the wordmark)

Three arms, same product, same original prompt

ArmWhat happenedVerdict
Gemini, reference_to_video
(all 3 images)
Invented a side-profile camera angle at ~2.5s that doesn't exist in any reference. Wordmark stayed correct, just softer than Atlas.Angle not a defect — see Section 5
Gemini, image_to_video
(seed image only — this task type can't take 3 images)
Stayed disciplined on camera framing, but regenerated the seed frame itself and corrupted the product's own wordmark.Worse fidelity
Grok Imagine
(all 3 images, new short prompt)
Correct marks, slightly softer than Atlas. Also settled a real pricing question — the catalog page and our own cost assumption were both wrong.Clean / minor

Same product, same prompt, three genuinely different outcomes — proof that the model, not just the reference prep, is a real variable in fidelity.

Gemini reference_to_video — full 3-image stack, invented a side angle
Gemini image_to_video — single seed only, corrupted the wordmark
Grok Imagine — full stack, new prompt, cleanest of the three
PELARIC misspelling
image_to_video's own corruption: PELAGIC became "PELARIC" — the model re-rendered the seed rather than locking its pixels

Side-by-side at the same timestamps

Three-way comparison at t=2.5s
t=2.5s — Atlas / Gemini r2v / Gemini i2v
Three-way comparison at t=5s
t=5s — Atlas / Gemini r2v / Gemini i2v

5The real fix — clean photos beat a clever prompt

"the side profile angle is fine actually, as long as the product still maintains fidelity... I am open to other camera movements or subject movements."— standing scoring rule from here forward

That single correction changed everything. Camera motion, subject motion, new viewpoints — none of it counts as a defect anymore. The only thing that disqualifies a video: an invented, altered, or missing detail on the product itself, checked against the real catalog photo.

First attempt: name the real marks in the prompt

The first fix tried was a hand-written prompt block per product, naming the real letters and — where a prior attempt had already failed — the exact garbled text to avoid. It worked, mostly:

AdWasWith hand-written marks
Vaportek hoodieInvented competitor label "JANA AARE"Fixed
Mako shortsGarbled tagline "BUILT FOR PISRING""Fixed" the wrong way — see below
Vaportek hoodie (16:9)Wrong logo, reversed fish, brand name missingFixed
Vaportek hoodie (chest + sleeve)Unboxed logo + invented sleeve printChest fixedsleeve unchanged

Why the hand-written approach hit a real wall

The sleeve print refused to clear no matter how the prompt was worded — the block explicitly said "forearms otherwise blank" and the model still copied a stacked invented print onto the sleeve. The reason: that print was already baked into the reference photo itself — a leftover artifact from an earlier AI-outpaint step. No prompt instruction can override what the model is literally shown in a picture.

Sleeve with hand-written marks — still garbled
Hand-written marks prompt, degraded reference — sleeve still garbled
Sleeve with clean catalog photo — genuinely blank
Same product, clean catalog photo instead — genuinely blank

Worse, on a second product the hand-written marks were factually wrong: the block said the waistband had "NO second line," but the real catalog photo genuinely shows BUILT FOR FISHING as a second line. The manual authoring had suppressed something that was actually true.

Waistband comparison across conditions
Left to right: original failure / hand-written-marks version / clean-photo version — only the clean-photo version matches the real catalog detail

The actual answer: skip the authoring, use the real photo

Re-running all four ads with zero product-specific prompt text — a fully generic instruction, paired with the real, undegraded catalog photos instead of the padded/outpainted stack — fixed every remaining defect, including the sleeve the hand-written version couldn't touch:

AdClean photos + generic prompt
Vaportek hoodie — neck labelClean
Mako shorts — waistbandClean, and matches the real catalog detail photo exactly
Vaportek hoodie — chest + sleeveBoth clean — the sleeve the other approach couldn't fix
Vaportek hoodie (16:9) — logo + sleeveBoth clean

Every fixed ad, before and after

JANA AARE before
Before — invented competitor label, fully legible
After — clean catalog photo, generic prompt, no per-product authoring
PISRING before
Before — garbled tagline
After — correct wordmark, matching the real catalog detail exactly
Wrong mark before
Before — wrong logo, reversed fish, brand name missing
After — correct boxed mark restored
Unboxed tuna before
Before — unboxed mark, wrong fish species, plus the sleeve print
After — chest AND sleeve both clean

Verified independently, on a fifth product

To make sure this wasn't specific to the four ads already under a microscope, the same clean-photo + generic-prompt approach was run on Leaderman — a product that had already passed under the old pipeline, used here as a check that the new approach doesn't regress a product that was already fine.

Leaderman, clean catalog photos, generic prompt
Leaderman waistband, generated
Waistband: PELAGIC / BUILT FOR FISHING, correctly reproduced

Mostly clean, with one honest miss worth keeping in the record: the waistband and construction came through perfectly, but a secondary hem tag came out with the wrong layout — the real tag reads "boxed P + fish icon, then PELAGIC below it"; the generated one swapped the order and dropped the box entirely.

Real hem tag
Real hem tag — boxed P + fish icon, PELAGIC below
Generated hem tag, wrong layout
Generated — PELAGIC on top, plain fish below, no box, no P

Clean photos plus a generic prompt gets you most of the way there — it fixed the hardest marks on every product tested — but it isn't a guaranteed clean sweep on every secondary detail. A mark the prompt never specifically calls out can still drift.

6Does this scale to production?

Yes — and it's simpler than the first attempt suggested. The path that actually works needs no per-product authoring at all.

What ships

  1. Build the reference stack from real catalog originals — the plain product photo, an on-model shot, and whichever detail photo actually has the readable branding — instead of the padded/AI-outpainted derivatives used today.
  2. Use the generic prompt, unchanged, for every product. No per-SKU writing.
  3. Optionally, tell the model explicitly which of the three photos to trust for fine print. This turned out to be a non-issue — see below.
  4. Keep hand-written marks only as a fallback, for the rare case where the reference stack is unavoidably degraded — never author them from a photo too small to actually show the real letters.

SettledDoes per-image staging require new classification? No — it's already there.

The remaining worry was real: if you want to tell the model which of the 3 photos to trust for fine print, don't you need to run a new vision pass on every catalog image first? Checked against production data: that classification already exists. Every catalog image already carries a label (plain product photo / on-model / detail shot), written once by an existing classifier and reused forever — verified directly against a real product's own 3 submitted photos, where the stored labels matched exactly what those photos show. A second existing field (extracted on-image text) already answers which photo has the readable branding.

One real caveat, also verified: on a different product, "detail" turned out to mean a fabric close-up, not a logo — so the fix reads the extracted text on the selected photo rather than trusting the label name alone. With that adjustment, no new spend is needed for this at all.

7Two more questions, both answered

AnsweredDoes telling the model which photo to trust help?

Tried explicitly staging the three photos by role — "use this one for the wide shot, use that one for fine print" — on top of the hand-written-marks approach. It worked cleanly, but a direct side-by-side against skipping staging entirely (clean photos, no staging, no per-product marks) showed the marks were reproduced just as accurately either way. Staging is a nice-to-have, not a requirement.

AnsweredDo you need a new vision pass to know which photo is which?

No. Checked against production data: every catalog photo already carries a label (plain product photo / on-model / detail shot), written once by an existing classifier and reused forever — verified directly against a real product's own 3 submitted photos, where the stored labels matched exactly what those photos show. A second existing field (extracted on-image text) already answers which photo has the readable branding, with one caveat: "detail" sometimes means a fabric close-up, not a logo, so the fix should check the extracted text, not just the label name. Either way, this is a code change reading data that already exists — not a new cost.

8Spend summary

WhatCost
Direct Gemini — Leaderman comparisons, both fix attempts across 4+1 ads, staging test, retry~$14.50
Grok Imagine — 2 real generations (first hit a length cap, cost $0)~$1.43
Atlas — one real successful generation during the outage window~$0.90
Total settled~$16.83

All spend tracked against a $50 approved budget for this investigation; nothing close to the limit. No billable request was ever retried after a failure — every failed attempt above cost $0, confirmed directly against each provider's own settlement record. One transient (unbilled) API error was retried once, which is why the count of real generations is slightly higher than the ad count.

9Recommended next steps

  1. Land the three pipeline fixes (money leak, pad scale, the reframe cache reconciliation) — already written and verified, not yet merged to trunk.
  2. Wire the real reference-selection path to catalog originals, not the padded/outpainted stack — this is the change that actually matters, confirmed across five products so far. A second round on five more products, using production's real selection logic, is in progress now to confirm this holds at broader scale.
  3. Retire the per-product hand-written marks approach as the default — keep it only as a fallback for the rare case where a clean reference genuinely isn't available.
  4. Build the minimal testing harness so this kind of investigation doesn't require hand-rolling a simulation every time — a true dry-run mode that shows exactly what production would submit without paying for it, plus a persisted record of what was actually sent to the model on each real ad.
  5. Fix the reference-preparation pipeline itself — the sleeve-print contamination came from an earlier AI-outpaint step, and switching to clean images sidesteps it here but doesn't fix the root cause for cases where a clean photo genuinely isn't available.