Skill Tracer
Skills › HyperFrames › media-use › grading.md

grading.md

163 lines · skills/media-use/references/grading.md at a595755

Open on GitHub
1# Color grading — grade blocks and LUTs
2
3Use `grade` when you need a canonical HyperFrames grading/effects payload for
4an `<img>` or `<video>`. Core presets and params-backed LUT entries resolve
5locally; future CDN-backed LUT entries require network unless already
6frozen. Persist a decided payload with the CLI rather than editing HTML by
7hand:
8
9For a vague but explicit polish request, do not jump directly from intent to a
10preset name. Read `media-treatments.md`, choose a treatment whose subject and
11avoid rules match the actual media, apply its conservative base with only
12justified bounded tuning, then complete its visual verification steps. A named
13owned treatment uses the exact preset/payload in its recipe; do not run the
14generic grade/LUT resolver first.
16Stop here and use that treatment workflow for requests such as retro, old home
17video, camcorder, film, print, ASCII, glitch, privacy, or a media reveal. Do not
18assemble those from a generic LUT plus handmade CSS vignette/grain/opacity.
20**Never `cat`/read a `.cube` file into context.** A 3D LUT is ~size^3 lines of raw numbers (33^3 ≈ 36k lines at the default size). It bloats context and carries zero human/agent-legible signal. To understand or choose a LUT, use `hyperframes grade-compare` to see it rendered. `npx hyperframes media-use resolve --type lut --intent "<look description>" --project .` validates generated or downloaded LUTs before freezing them; the validator is bundled in the CLI, not shipped as a standalone skill script. Read `<project>/.media/index.md` or `luts/index.json` for the description. Never read the LUT body itself.
22```bash
23npx hyperframes media-use resolve --type grade --intent "warm daylight" --project . --json
24```
26Preset-first output uses the core runtime vocabulary and does not freeze a file:
28```json
30 "preset": "warm-daylight",
31 "intensity": 1
33```
35Apply that payload to one unambiguous real media element:
37```bash
38hyperframes media-treatment --project . --file index.html \
39 --selector '#hero' \
40 --grading '{"preset":"warm-daylight","intensity":1}' --apply --json
41```
43On Windows PowerShell, put the payload in a file and pass `--grading grading.json` (or pipe it with `--grading -`); inline JSON loses its quotes there.
45Use `--dry-run` before writing when scope is uncertain and `--clear` to remove
46the treatment. The low-level persisted result is still normal HTML:
48```html
49<video
50 class="clip"
51 src="./media/scene.mp4"
52 data-color-grading='{"preset":"warm-daylight","intensity":1}'
53></video>
54```
56Direct attribute authoring is a fallback for environments where the CLI is not
57available, not the primary agent workflow.
59To build a treatment that is not already represented by a recipe, inspect the
60canonical toolbox first:
62```bash
63hyperframes media-treatment --capabilities --json
64```
66It reports a concise family map. Read `--capability grading` for the processing
67order, then request only the focused family needed to get its legal controls
68and ranges from Core. Compose one nested payload and pass it back through
69`hyperframes media-treatment`; the command rejects unknown keys before
70mutation. Do not generate or hand-edit a LUT merely to combine controls already
71owned by the realtime shader.
73For seek-safe effect motion, animate only the runtime-supported CSS properties
74on that same real media element with its registered paused GSAP timeline:
76| CSS property | Range |
77| ---------------------------------- | ------- |
78| `--hf-color-grading-intensity` | 0 to 1 |
79| `--hf-color-grading-lut-intensity` | 0 to 1 |
80| `--hf-color-grading-exposure` | -2 to 2 |
81| `--hf-color-grading-blur` | 0 to 1 |
82| `--hf-color-grading-bloom` | 0 to 3 |
83| `--hf-color-grading-kuwahara` | 0 to 1 |
84| `--hf-color-grading-pixelate` | 0 to 1 |
85| `--hf-color-grading-ascii` | 0 to 1 |
86| `--hf-color-grading-dither` | 0 to 1 |
88Once set (inline, in a stylesheet or on a parent), a property overrides the
89payload's value for that control, so set it only on media you animate: put the
90tween's first value in the element's inline `style`, then use finite `tl.to()`
91keyframes. Leave it unset for a static grade. Do not use a frame-zero `tl.set()`, CSS
92animation clocks, timers, random values, or `onUpdate` callbacks. The static
93`data-color-grading` payload remains the fallback and source of the other
94controls.
96For a reusable color transform beyond the preset vocabulary, freeze a validated
97`.cube` under `.media/luts/` and return a block that references it:
99```bash
100npx hyperframes media-use resolve --type grade --intent "teal orange blockbuster" --project . --json
101```
103```json
105 "intensity": 1,
106 "lut": { "src": ".media/luts/grade_001.cube", "intensity": 0.85 }
108```
110Use `lut` when you only need the reusable `.cube` file:
112```bash
113npx hyperframes media-use resolve --type lut --intent "teal orange blockbuster" --project .
114```
116For a describable technical look, author an explicit parametric LUT with `--params`:
118```bash
119npx hyperframes media-use resolve --type lut --params '{"contrast":0.2,"temperature":-0.3}' --project .
120npx hyperframes media-use resolve --type grade --params '{"exposure":0.2}' --project . --json
121```
123For a LUT generated by your own script, ingest it with `--from`; media-use validates it before registration and rejects invalid or oversized cubes:
125```bash
126npx hyperframes media-use resolve --type lut --from custom.cube --project .
127```
129Parametric math (`buildCube`) cannot reproduce real film stocks or emulsion
130transforms. Use a CDN-backed scanned `.cube` entry or ingest a real scanned
131`.cube` for those.
133For visual selection, list reusable LUT candidates with
134`resolve --type grade --candidates`, write the promising entries to a
135`grades.json`, run
136`hyperframes grade-compare --for <frame> --grades grades.json`, then commit the
137winner with `resolve -t grade` as the final `data-color-grading` block.
139For media already selected in a composition, use `media-treatment --analyze`
140when you need side-effect-free `ffmpeg`/`ffprobe` signalstats evidence. It
141returns source metadata, HDR/unknown-LOG warnings, and a bounded `adjust`
142suggestion without modifying the composition. The suggestion is a starting
143point for visual review, not an automatic neutralization of intentional color.
145```bash
146hyperframes media-treatment --project . --file index.html \
147 --selector '#hero' --analyze --json
148```
150For an unbound source file, `resolve --type grade --for ... --analyze` remains
151available. Without `--analyze`, that resolver records a grade candidate in
152`.media`; use that form only when you intend to keep the candidate.
154Library LUT entries live in `luts/index.json`. Each entry keeps `id`,
155`description`, `tags`, and `intensity`, then supplies either compact `params`
156for on-demand `buildCube(params)` generation or a direct CDN `url` for future
157scanned `.cube` files. Do not commit generated `.cube` bodies; resolve
158validates generated or downloaded cubes as it freezes them under
159`.media/luts/`.
161```bash
162npx hyperframes media-use resolve --type lut --intent "teal orange blockbuster" --project . --json
163```

Color grading — grade blocks and LUTs

Use grade when you need a canonical HyperFrames grading/effects payload for an <img> or <video>. Core presets and params-backed LUT entries resolve locally; future CDN-backed LUT entries require network unless already frozen. Persist a decided payload with the CLI rather than editing HTML by hand:

For a vague but explicit polish request, do not jump directly from intent to a preset name. Read media-treatments.md, choose a treatment whose subject and avoid rules match the actual media, apply its conservative base with only justified bounded tuning, then complete its visual verification steps. A named owned treatment uses the exact preset/payload in its recipe; do not run the generic grade/LUT resolver first.

Stop here and use that treatment workflow for requests such as retro, old home video, camcorder, film, print, ASCII, glitch, privacy, or a media reveal. Do not assemble those from a generic LUT plus handmade CSS vignette/grain/opacity.

**Never cat/read a .cube file into context.** A 3D LUT is ~size^3 lines of raw numbers (33^3 ≈ 36k lines at the default size). It bloats context and carries zero human/agent-legible signal. To understand or choose a LUT, use hyperframes grade-compare to see it rendered. npx hyperframes media-use resolve --type lut --intent "<look description>" --project . validates generated or downloaded LUTs before freezing them; the validator is bundled in the CLI, not shipped as a standalone skill script. Read <project>/.media/index.md or luts/index.json for the description. Never read the LUT body itself.

npx hyperframes media-use resolve --type grade --intent "warm daylight" --project . --json

Preset-first output uses the core runtime vocabulary and does not freeze a file:

{
  "preset": "warm-daylight",
  "intensity": 1
}

Apply that payload to one unambiguous real media element:

hyperframes media-treatment --project . --file index.html \
  --selector '#hero' \
  --grading '{"preset":"warm-daylight","intensity":1}' --apply --json

On Windows PowerShell, put the payload in a file and pass --grading grading.json (or pipe it with --grading -); inline JSON loses its quotes there.

Use --dry-run before writing when scope is uncertain and --clear to remove the treatment. The low-level persisted result is still normal HTML:

<video
  class="clip"
  src="./media/scene.mp4"
  data-color-grading='{"preset":"warm-daylight","intensity":1}'
></video>

Direct attribute authoring is a fallback for environments where the CLI is not available, not the primary agent workflow.

To build a treatment that is not already represented by a recipe, inspect the canonical toolbox first:

hyperframes media-treatment --capabilities --json

It reports a concise family map. Read --capability grading for the processing order, then request only the focused family needed to get its legal controls and ranges from Core. Compose one nested payload and pass it back through hyperframes media-treatment; the command rejects unknown keys before mutation. Do not generate or hand-edit a LUT merely to combine controls already owned by the realtime shader.

For seek-safe effect motion, animate only the runtime-supported CSS properties on that same real media element with its registered paused GSAP timeline:

CSS propertyRange
--hf-color-grading-intensity0 to 1
--hf-color-grading-lut-intensity0 to 1
--hf-color-grading-exposure-2 to 2
--hf-color-grading-blur0 to 1
--hf-color-grading-bloom0 to 3
--hf-color-grading-kuwahara0 to 1
--hf-color-grading-pixelate0 to 1
--hf-color-grading-ascii0 to 1
--hf-color-grading-dither0 to 1

Once set (inline, in a stylesheet or on a parent), a property overrides the payload's value for that control, so set it only on media you animate: put the tween's first value in the element's inline style, then use finite tl.to() keyframes. Leave it unset for a static grade. Do not use a frame-zero tl.set(), CSS animation clocks, timers, random values, or onUpdate callbacks. The static data-color-grading payload remains the fallback and source of the other controls.

For a reusable color transform beyond the preset vocabulary, freeze a validated .cube under .media/luts/ and return a block that references it:

npx hyperframes media-use resolve --type grade --intent "teal orange blockbuster" --project . --json
{
  "intensity": 1,
  "lut": { "src": ".media/luts/grade_001.cube", "intensity": 0.85 }
}

Use lut when you only need the reusable .cube file:

npx hyperframes media-use resolve --type lut --intent "teal orange blockbuster" --project .

For a describable technical look, author an explicit parametric LUT with --params:

npx hyperframes media-use resolve --type lut --params '{"contrast":0.2,"temperature":-0.3}' --project .
npx hyperframes media-use resolve --type grade --params '{"exposure":0.2}' --project . --json

For a LUT generated by your own script, ingest it with --from; media-use validates it before registration and rejects invalid or oversized cubes:

npx hyperframes media-use resolve --type lut --from custom.cube --project .

Parametric math (buildCube) cannot reproduce real film stocks or emulsion transforms. Use a CDN-backed scanned .cube entry or ingest a real scanned .cube for those.

For visual selection, list reusable LUT candidates with resolve --type grade --candidates, write the promising entries to a grades.json, run hyperframes grade-compare --for <frame> --grades grades.json, then commit the winner with resolve -t grade as the final data-color-grading block.

For media already selected in a composition, use media-treatment --analyze when you need side-effect-free ffmpeg/ffprobe signalstats evidence. It returns source metadata, HDR/unknown-LOG warnings, and a bounded adjust suggestion without modifying the composition. The suggestion is a starting point for visual review, not an automatic neutralization of intentional color.

hyperframes media-treatment --project . --file index.html \
  --selector '#hero' --analyze --json

For an unbound source file, resolve --type grade --for ... --analyze remains available. Without --analyze, that resolver records a grade candidate in .media; use that form only when you intend to keep the candidate.

Library LUT entries live in luts/index.json. Each entry keeps id, description, tags, and intensity, then supplies either compact params for on-demand buildCube(params) generation or a direct CDN url for future scanned .cube files. Do not commit generated .cube bodies; resolve validates generated or downloaded cubes as it freezes them under .media/luts/.

npx hyperframes media-use resolve --type lut --intent "teal orange blockbuster" --project . --json
Raw lines 1 to 163