Skip to content

docs(prompting): add colour grading and film effects chapter - #2911

Open
vanceingalls wants to merge 4 commits into
mainfrom
docs/color-grading-chapter
Open

docs(prompting): add colour grading and film effects chapter#2911
vanceingalls wants to merge 4 commits into
mainfrom
docs/color-grading-chapter

Conversation

@vanceingalls

Copy link
Copy Markdown
Collaborator

Adds a Colour Grading and film effects chapter to the Prompt Guide, in Level 4 — Substance, plus two sections to the Colour Grading guide.

Ten A/B demos, each with the plain-language prompt that produced it and the payload it compiled to. Every render is a split screen against identical source media — ungraded left, graded right.

Renders are served from the CDN (docs/images/ is gitignored) and are already uploaded and reachable.

What the chapter covers

Section Point
The source has to have something to lose Every treatment works by removing something, so the shot must contain it
The pipeline order is fixed A global saturation drop defeats a hue key downstream
Grading qualifies by value, never by position No masks or tracking; a region has to become its own layer
Separating subject from background Matte separation and face-only redaction
Destroying the picture on purpose Dither, bloom, Kuwahara
Print and colour Two-ink press, hue-keyed spotlight
Analogue: three different failures Tape (transport), tube (glass), camera (capture)
Animating a grade The nine CSS custom properties, and what can't be tweened

Guide additions

Animating a Grade — the nine CSS custom properties, plus driving the payload from the timeline for effects that have none. Documents two verified limitations:

  • --hf-color-grading-intensity does not scale a grade at render time: a static 0.5 renders identically to 0.
  • Payload-rewrite animation is effect-dependent. Verified working for halftone and twoInkPrint; verified not working for crtCurvature, scanlines, chromaBleed, chromaticAberration, where the same payload renders correctly applied statically but produces no change when driven through setAttribute.

Limiting a Grade to Part of the Frame — the support matrix previously said "Face or region tracking: not supported" with nowhere to go. Now there are three layer recipes, the two compositing traps (subject-removed plate gives a dark rim; premultiplied alpha gives a black outline), and a worked face-redaction example with markup and prompt.

Notes for review

  • The chapter teaches technique and links to the guide for keys and bounds rather than duplicating the reference.
  • Two matte lessons are deliberately stated as opposites: matte-separation keeps layers separate so the subject is protected; the CRT merges them before grading because the warp belongs to the display. Cross-referenced so neither gets pattern-matched onto the other.
  • Validated: both MDX files compile, all ten video URLs return 200, all internal links and the deep anchor resolve.

🤖 Generated with Claude Code

Ten A/B demos, each with the plain-language prompt that produced it and
the payload it compiled to. Slots into Level 4 — Substance.

The chapter teaches technique and leaves the key/bound reference to the
Colour Grading guide rather than duplicating it.

Also adds two sections to docs/guides/color-grading.mdx:

- Animating a Grade — the nine CSS custom properties, plus driving the
  payload from the timeline for effects that have none. Documents that
  --hf-color-grading-intensity does not scale a grade at render time,
  and that payload-rewrite animation is effect-dependent: verified
  working for halftone and twoInkPrint, verified not working for
  crtCurvature, scanlines, chromaBleed and chromaticAberration.

- Limiting a Grade to Part of the Frame — grading qualifies by value,
  never by screen position, so a region has to become its own layer.
  Includes the three layer recipes and a worked face-redaction example.
  Previously the support matrix said "not supported" with nowhere to go.

Renders are served from the CDN; docs/images/ is gitignored.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mintlify

mintlify Bot commented Jul 31, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
hyperframes 🟢 Ready View Preview Jul 31, 2026, 5:56 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

The guide covers the contract; the chapter covers the two failures the
contract cannot express — choosing a source that has something for the
treatment to remove, and separating a subject so part of the frame can
be graded while the rest is protected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@miga-heygen miga-heygen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Colour Grading Chapter — Review

Excellent teaching chapter. The "source has to have something to lose" framing, the three analogue failure modes (tape/tube/camera), and the worked compositing traps are exactly what the prompt guide needs. Ten A/B demos, all 10 CDN URLs verified live (200). Cross-references between chapter and guide are correct in both directions. Nav placement in Level 4 is right.

One blocking issue, one observation.


Blocking: Bridge chain broken at generated-artwork

The nav now places color-grading between generated-artwork and vfx-and-liquid-glass, but generated-artwork.mdx still exits with:

Next: VFX and liquid glass — device mockups, frosted glass, and cinematic effects…

That bridge skips the new page entirely. A reader following the "Next" links goes from generated artwork straight to VFX, missing this chapter. Update the exit bridge to point to color-grading, and optionally add a forward bridge from color-grading to vfx-and-liquid-glass (the "Next steps" section already does this, so you're covered there).


Observation: Duplicated caveat list

The verified-not-working effects list (crtCurvature, scanlines, chromaBleed, chromaticAberration) appears verbatim in both the guide's "Animating a Grade" section and the chapter's summary. The teaching-vs-reference split is a valid pattern, but if that list grows or shrinks, both places need updating. Consider having the chapter link to the guide section for the detailed list rather than restating it — but not blocking on this; the current duplication is small and stable.


Verified

  • 10/10 video CDN URLs return 200
  • Nav placement: generated-artworkcolor-gradingvfx-and-liquid-glass
  • Chapter → guide cross-refs: /guides/color-grading, /guides/color-grading#limiting-a-grade-to-part-of-the-frame
  • Guide → chapter cross-ref: /prompting/color-grading in the Agent Guidance section
  • Support matrix row updated: "Face or region tracking" now links to new section
  • Chapter exit bridge: "Next steps" links to /prompting/vfx-and-liquid-glass
  • Pipeline order (adjust → wheels → curves → hueCurves → secondaries → lut → details → effects) — new information, correctly placed in teaching context
  • Internal anchors consistent between files
  • Both MDX files structurally valid

Fix the bridge chain and this ships.

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 2517f177 — layering on top of miga-heygen's review, not duplicating the bridge-chain fix or the duplicated-caveat observation.

This is a strong teaching chapter overall — the "source has to have something to lose" framing, the tape/tube/camera taxonomy, and the compositing traps (subject-removed plate rim, premultiplied-alpha outline) are exactly what the prompt guide needs. 10/10 video CDN URLs return 200 (spot-checked separately from miga).

Unique findings from this pass:

Blocker — the --hf-color-grading-* CSS custom property system doesn't exist in the runtime code. The "Animating a Grade" section in both files documents 9 custom properties (--hf-color-grading-ascii/bloom/blur/dither/exposure/intensity/kuwahara/lut/pixelate) with a working tl.to() example. Grepping the whole hyperframes repo returns zero occurrences of --hf-color-grading- outside these .mdx files, and the runtime's read path at packages/core/src/runtime/colorGrading.ts:268 reads only data-color-grading (JSON attribute) and resolves $variable refs against __hfVariables. The two MutationObservers (attribute filter on HF_COLOR_GRADING_ATTR at :255; style-attribute observer at :1519 that only computes a geometrySignature of transform/translate/rotate/scale/left/top/width/height) don't observe CSS custom properties either. Details on the guide's tl.to() example. If there's a code path I missed, point at it — otherwise the whole section needs collapsing to just the payload-rewrite (setAttribute) pattern, which IS backed by the MutationObserver at :255. The "verified working for halftone/twoInkPrint" bullet already documents that working path.

Consistency with sibling prompting chapters (vfx-and-liquid-glass.mdx, generated-artwork.mdx) — details inline:

  • 10/10 videos lack the italic *Rendered from the prompt above, unedited.* caption siblings consistently include underneath each <video>.
  • 10/10 videos lack the #t=0.1 posterframe hint that avoids the black-until-play state on load.
  • Prompt blockquotes don't open with a /skill-name slash-command like siblings do — decide whether that's intentional (grading annotations aren't one-shot composition briefs) or a drift to reconcile.

Nit — British/American spelling drift. The new chapter uses "Colour/colour" 14×, while the rest of docs/* uses "color" 247× (the file path, docs.json nav slug, and every cross-ref are all American). Reconcile one way — the current mix will confuse readers who search for one or the other.

Everything else lands clean — pipeline order (adjust → wheels → curves → hueCurves → secondaries → lut → details → effects) is a genuinely new piece of teaching, the three-layer face-redaction worked example is well-scoped, and the "source has to have something to lose" table is one of the sharpest pieces of prompting guidance I've seen in the docs.

Review by Rames D Jusso

```

```js
tl.to("#plate", { "--hf-color-grading-pixelate": 0.5, duration: 3, ease: "power2.inOut" }, 0.3);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocker — the --hf-color-grading-* CSS custom property system doesn't exist in the runtime code. Grepping the whole hyperframes repo for --hf-color-grading returns zero matches outside these .mdx files. packages/core/src/runtime/colorGrading.ts:268 (readColorGradingAttribute) reads only HF_COLOR_GRADING_ATTR (= data-color-grading) and resolves $variable refs via __hfVariables (see readVariablesForElement in runtime/variableScope.ts — reads only window.__hfVariables*, no CSS custom-property read). The MutationObserver at :255 filters by [HF_COLOR_GRADING_ATTR] — not style. The MutationObserver on the style attribute at :1519 computes a geometrySignature of transform | translate | rotate | scale | left | top | width | height only — never getPropertyValue('--hf-...'). So tl.to('#plate', { '--hf-color-grading-pixelate': 0.5 }) writes a CSS variable that nothing consumes.

If there's a code path where these custom properties get consumed that I couldn't locate, point at it — otherwise this whole section documents an unshipped feature. The payload-rewrite path (setAttribute('data-color-grading', ...)) IS backed by the MutationObserver at :255, and the halftone/twoInkPrint verification below confirms it works. Recommend collapsing the entire "Animating a Grade" section to the payload-rewrite pattern only — drop the 9-CSS-custom-property list and the tl.to() example, keep the data-color-grading onUpdate example.

Rames D Jusso


## Animating a grade

Nine properties expose a CSS custom property and tween directly — `ascii`, `bloom`, `blur`, `dither`, `exposure`, `intensity`, `kuwahara`, `lut`, `pixelate`. Start them at identity so the shot opens ungraded and every intermediate value renders.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Same fabrication mirrored here — see the inline on the guide's line 261 for the runtime-code evidence. "Nine properties expose a CSS custom property and tween directly" isn't backed by any code path I can find. Suggest revising to drop the "9 custom properties" framing entirely, and lead with the payload-rewrite path (the second bullet below) as the sole working mechanism. — Rames D Jusso

Comment thread docs/prompting/color-grading.mdx Outdated

> Take the talking-head clip and separate the subject from the room. Leave the person photographic — a gentle skin-softening pass and about a third of a stop of extra exposure, nothing that reads as an effect on skin. Grade the room behind them instead: across the four seconds bring up a halftone screen so the space resolves into small coloured dots, and let a restrained bloom build alongside it so the windows lift. Both start at zero so the shot opens ungraded.

<video controls muted loop playsinline preload="metadata" src="https://static.heygen.ai/hyperframes-oss/docs/images/prompting/grade-matte-separation-b0ef8e73.mp4" style={{ borderRadius: "0.5rem", marginTop: "0.75rem" }}></video>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Voice consistency with sibling prompting chapters. Adjacent files (prompting/vfx-and-liquid-glass.mdx, prompting/generated-artwork.mdx) consistently follow each demo <video> with an italic caption — *Rendered from the prompt above, unedited.* or a specific descriptor — AND include #t=0.1 on the src URL so the video shows a posterframe (first frame) instead of a black-until-play state. Neither is present on any of the 10 videos in this chapter. Same pattern for the 9 below. — Rames D Jusso

Comment thread docs/prompting/color-grading.mdx Outdated

### Grade the room, protect the face

> Take the talking-head clip and separate the subject from the room. Leave the person photographic — a gentle skin-softening pass and about a third of a stop of extra exposure, nothing that reads as an effect on skin. Grade the room behind them instead: across the four seconds bring up a halftone screen so the space resolves into small coloured dots, and let a restrained bloom build alongside it so the windows lift. Both start at zero so the shot opens ungraded.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Voice consistency: sibling prompting docs open each blockquote prompt with a /skill-name slash-command (> /motion-graphics 15-second 1920x1080 ..., > /product-launch-video ... in prompting/vfx-and-liquid-glass.mdx). Prompts in this chapter start straight into narrative ("Take the talking-head clip..."). Small voice drift — worth deciding whether it's intentional (these are grading annotations rather than one-shot composition briefs) or a reconciliation to make. Same pattern for the other 8 prompts below. — Rames D Jusso

- Repoint the generated-artwork exit bridge at color-grading. The nav
  inserted the new page between generated-artwork and vfx-and-liquid-glass
  but the "Next" link still skipped it (miga-heygen, blocking).
- Correct the LUT custom property name: --hf-color-grading-lut-intensity,
  not --hf-color-grading-lut. Real transcription error, surfaced while
  checking the CSS-variable review comment against the source table in
  packages/core/src/colorGrading.ts:921-931.
- Add #t=0.1 posterframe hints and a contextual italic caption to all ten
  videos, matching the sibling prompting chapters.
- Reconcile British spelling to American throughout. The file path, nav
  slug, page title and every cross-reference were already "color".
- De-duplicate the animatable-effect caveat list: the chapter now links to
  the guide's Animating a Grade section instead of restating which effects
  are verified working, so the list is maintained in one place.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vanceingalls

Copy link
Copy Markdown
Collaborator Author

Thanks both — pushed e4eac0c21. Four fixes, one correction found because of the blocker, and one finding I have to push back on with code.

🔴 The --hf-color-grading-* system does ship — declining this one

@james-russo-rames-d-jusso asked me to point at the code path, so here it is.

The property tablepackages/core/src/colorGrading.ts:921-931:

export const HF_COLOR_GRADING_ANIMATABLE_PROPERTIES = [
  { path: "intensity",        name: "--hf-color-grading-intensity",     min: 0, max: 1 },
  { path: "lut.intensity",    name: "--hf-color-grading-lut-intensity", min: 0, max: 1 },
  { path: "adjust.exposure",  name: "--hf-color-grading-exposure",      min: -2, max: 2 },
  { path: "effects.blur",     name: "--hf-color-grading-blur",          min: 0, max: 1 },
  ...
] as const;

The read pathpackages/core/src/runtime/colorGrading.ts:2965-2970:

function readAnimatedValue(element: HTMLElement, property: AnimatedProperty): number | null {
  const raw = element.style.getPropertyValue(property.name);
  ...
}

Consumed by isRuntimeColorGradingActive (:2973) and readAnimatedEffects (:2983), off ANIMATED_GRADING_PROPERTIES built from that table at :2947-2962. The reader is element.style.getPropertyValue on the inline style — which is exactly what a GSAP tl.to() on a custom property writes, so the style-attribute MutationObserver's geometrySignature isn't the relevant mechanism.

Also covered by tests — packages/core/src/runtime/colorGrading.test.ts:158 sets --hf-color-grading-blur directly, packages/parsers/src/gsapParser.test.ts:173 asserts the parser carries --hf-color-grading-intensity through a tl.to() — and it ships in packages/cli/dist/. It's also pre-existing documented behaviour in docs/guides/media-effects.mdx:199,209, which this PR didn't touch.

Empirically: three of the ten demos ramp through these properties and measurably move. painterly drives --hf-color-grading-kuwahara and detail falls 0.0543 → 0.0125 monotonically across the clip; bloom-out and signal-loss likewise. If they weren't consumed, those renders would be static.

I suspect the grep missed because the names are assembled in a table rather than appearing at their use site.

But it wasn't a wasted finding — checking your claim against that table caught a real error of mine: I had documented --hf-color-grading-lut, and the actual name is --hf-color-grading-lut-intensity. My original grep regex stopped at the hyphen. Fixed.

✅ Fixed

  • Bridge chain (@miga-heygen, blocking) — generated-artwork.mdx now exits to color-grading instead of skipping to vfx-and-liquid-glass.
  • #t=0.1 posterframes — all ten. Confirmed near-universal across siblings; this chapter was 0/11.
  • Captions — all ten, contextual rather than boilerplate. Worth noting the convention is contextual: generated-artwork uses "That clause, rendered…", and motion.mdx has one caption across twelve videos, so I wrote a distinct line per demo rather than repeating "Rendered from the prompt above, unedited" ten times.
  • Spelling — reconciled to American throughout, including the title. Path, nav slug and cross-refs were already color.
  • Duplicated caveat list (@miga-heygen) — the chapter now links to the guide's Animating a Grade rather than restating which effects are verified working, so it's maintained in one place.

🟠 Declining: /skill-name prompt prefix

motion.mdx — the closest structural sibling, A/B rule demos with paired prompts — opens its prompts without a slash-command (> 6-second 1920x1080 live telemetry panel: …). These prompts are grading annotations against existing media rather than one-shot composition briefs, same as motion's, so I've left them. Happy to add prefixes if you'd rather the convention be uniform.

Validated: all three MDX files compile, ten posterframes, ten captions, zero British spellings, all internal links and anchors resolve.

@miga-heygen miga-heygen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review — both concerns addressed

The review-address commit fixes everything I flagged:

  • Bridge chain fixed. generated-artwork.mdx now exits to color-grading instead of vfx-and-liquid-glass. Chain: generated-artwork → color-grading → vfx-and-liquid-glass. Correct.
  • Duplicated caveat list collapsed. The chapter no longer restates the verified-not-working effects list. Instead: "the verified list of which is which lives in the guide's Animating a Grade, so it only has to be maintained in one place." Single source of truth.
  • Video posterframes (#t=0.1) added to all 10 videos.
  • Italic captions added below all 10 videos.
  • Colour → Color spelling normalized across the chapter.

Ships clean from my side.

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delta from R1 (2517f177e4eac0c2) reads clean.

R1 blocker was overstated — owning it. I claimed the whole 9-prop --hf-color-grading-* list was fabricated, but 8/9 of them do exist at packages/core/src/colorGrading.ts:922-930 and are exercised by packages/core/src/runtime/colorGrading.test.ts via .style.setProperty. My R1 grep missed the block. The one prop that was wrong — the bare --hf-color-grading-lut — you correctly identified and replaced with the real --hf-color-grading-lut-intensity. Sorry for the noise on the other eight.

Other R1 items:

  • Posterframes (#t=0.1) + italic captions on all 10 videos ✓.
  • Moving the "verified working / verified not working" enumeration into the guide as SSOT — prompting page just points at #animating-a-grade — is the right consolidation.
  • Bridge from generated-artwork.mdxcolor-grading ✓ (per @miga-simon-sierra's R1 finding).
  • Colour → color: within this PR's files it's now uniformly "color". The 6 remaining \bcolour\b mentions in docs/ are all in pre-existing files not touched here (changelog.mdx, deploy/templates-on-lambda.mdx, prompting/motion.mdx) — scope-appropriate to leave.
  • The /skill-name opener nit I dropped in R1 was wrong on reflection — generated-artwork.mdx, design-systems.mdx, iterating.mdx, editing-existing-videos.mdx all use plain-language prompts too; only code-and-prs.mdx opens with /pr-to-video. Ignore.

CI green apart from the pre-existing Tests on windows-latest failure, which is unrelated to a docs-only PR.

LGTM from my side.

Review by Rames D Jusso

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bridge and SSOT fixes are clean, but one central runtime claim still needs correction before this ships. Both new pages say --hf-color-grading-intensity does not scale a grade and that 0.5 renders the same as 0. At this exact head, the runtime reads that CSS property into u_intensity (packages/core/src/runtime/colorGrading.ts), and the fragment shader computes mix(sampleColor.rgb, applyColorGrade(sampleColor.rgb), u_intensity). The existing runtime test also pins 0.25 and 0.75 reaching u_intensity. So it does scale the primary/advanced/LUT grade stack. What it does not scale are the independent details/effects applied after that mix (grain, vignette, halftone, bloom, etc.); those need their own supported property. Please correct the wording in both docs/guides/color-grading.mdx and docs/prompting/color-grading.mdx. No runtime change is needed.

Both pages said intensity does not scale a grade and that 0.5 renders the
same as 0. That is wrong, and the error was mine: I tested intensity only
against twoInkPrint and tapeDamage, then generalised from an effects-only
result.

The shader mixes ungraded against graded at u_intensity
(runtime/colorGrading.ts:1234), so it does scale adjust, wheels, curves,
hueCurves, secondaries and the LUT. Runtime tests pin 0.25 and 0.75
reaching the uniform. What it does not scale is details and effects —
grain, filmArtifacts, monoScreen, engraving, crosshatch, halftone,
twoInkPrint and the tape/CRT families are all applied after that mix
(:1235-1262), which is exactly what I had measured.

Both pages now say intensity ramps the primary grade only, and to animate
the specific effect when the look is effect-based.

Reported by miguel-heygen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vanceingalls

Copy link
Copy Markdown
Collaborator Author

@miguel-heygen you're right and the error was mine — corrected in dd9c86d07.

I verified the claim before accepting it, and the code says exactly what you said:

  • runtime/colorGrading.ts:1234vec3 color = mix(sampleColor.rgb, applyColorGrade(sampleColor.rgb), u_intensity);
  • runtime/colorGrading.test.ts:595-630 — pins 0.25 and 0.75 reaching u_intensity
  • :1235-1262 — grain, filmArtifacts, monoScreen, engraving, crosshatch, halftone, twoInkPrint are all applied after that mix

How I got it wrong: I only ever tested intensity against twoInkPrint and tapeDamage while trying to animate those two demos. Both are post-mix effects, so intensity genuinely did nothing to them — and I generalised an effects-only result into "intensity does not scale a grade." Your explanation accounts for my observation exactly rather than contradicting it.

Both pages now read:

--hf-color-grading-intensity scales the primary grade onlyadjust, wheels, curves, hueCurves, secondaries and the LUT. It does not scale details or effects, which are applied after that mix, so it will not ramp grain, halftone, bloom or the tape and CRT families. Reach for the specific effect instead of treating it as a master dial.

That's a more useful statement than the original even had it been true, since it tells you which half of the stack the dial reaches.


Thanks also @james-russo-rames-d-jusso for retracting the R1 blocker — no noise caused, checking it against the source table is what caught my real --hf-color-grading-lut-lut-intensity mistake.

Tests on windows-latest is failing on main too and is unrelated to a docs-only change.

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.

4 participants