refactor: bundle the whole template suite under flat-artist/ + fix references
flat-artist is now the single container: all 16 template skills + the R&D references/ moved inside flat-artist/. Cross-references updated — the orchestrator points to bundled `<name>/SKILL.md`, sub-skills point to `../<name>/SKILL.md`, and the R&D report path is relative. README catalog updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
---
|
||||
name: asset-sourcing
|
||||
description: How to source, license, AI-generate, prepare, and organize royalty-free assets (footage, images, textures, HDRIs, GLTF/GLB, icons, illustrations) for FlatRender Remotion templates — Iran-aware (geo-blocks), vendored-only, license-firewalled. Use when a template needs real media, when downloading/committing assets into public/, when grading/masking/looping footage or compositing it via Video/OffthreadVideo/Img/staticFile + Ken-Burns, or when generating bespoke assets with local AI models.
|
||||
---
|
||||
|
||||
# Asset sourcing for templates
|
||||
|
||||
Project: `services/remotion/`. Helpers: `src/lib/anim.ts` (`hexToRgba`, `mixHex`, `rand`), `src/lib/aspect.ts` (`useLayout` → `isWide/isSquare/isTall`, `vmin`, `unit`), `src/lib/branding.ts` (`colorSchema`, `BRAND`), `src/lib/fonts.ts` (`FONT` = Vazirmatn, RTL), `src/lib/three-kit.tsx` (`StudioEnv/Lights/Floor/Effects`, `Confetti3D`). Render is **headless Chrome in Docker** — every value derives from `useCurrentFrame()` (never `Math.random`/`Date.now`/`useFrame`; use `rand(i)`).
|
||||
|
||||
## The Iron Rule — vendor everything
|
||||
The Iran environment punishes runtime dependencies. **Download once (VPN if needed), commit into `public/`, reference with `staticFile()`.** Never put `https://…` in a shipped template — a geo-block or flaky tunnel kills the render mid-frame. Mirror npm/NuGet/Docker via Nexus (`mirror.soroushasadi.com`); asset *binaries* are sourced by hand. **Record the license at acquisition time, not later.** `public/` today holds only `fonts/` — you build the rest.
|
||||
|
||||
## License taxonomy (know cold — this is the firewall)
|
||||
| Class | Examples | Ship? |
|
||||
|---|---|---|
|
||||
| CC0 / Public Domain / Pixabay / Pexels / Unsplash | Poly Haven, ambientCG, Kenney, Mixkit | ✅ free, no credit — **default target** |
|
||||
| CC-BY | many Sketchfab, Bensound | ⚠️ ship only with a tracked on-screen/end-card credit |
|
||||
| CC-BY-SA | some Wikimedia | ❌ share-alike can infect our proprietary template |
|
||||
| CC-BY-NC | "free for personal" tiers | ❌ we are a **paid** product = commercial |
|
||||
| Editorial / rights-managed | news/celebrity stock | ❌ |
|
||||
| Paid stock | Envato, Adobe, Shutterstock | ✅ per license — **keep the receipt/PDF** |
|
||||
|
||||
No license row = unknown license = **do not ship**.
|
||||
|
||||
## Sourcing map (CC0 / no-attribution first) + Iran access
|
||||
| Type | Best CC0 sources | Commit to | Iran access |
|
||||
|---|---|---|---|
|
||||
| Footage (H.264 MP4, right-sized) | Pexels Video, Pixabay Video, Mixkit, Coverr, Videvo (filter CC0) | `public/footage/{nature,business,abstract}/` | Pixabay/Mixkit/Coverr OK; Pexels VPN-ish |
|
||||
| Images | Pexels, Pixabay, Unsplash, StockSnap, Burst | `public/images/` | Pixabay OK; Pexels/Unsplash VPN-ish |
|
||||
| Textures / overlays | Poly Haven, ambientCG; grain/light-leak/dust CC0 clips | `public/textures/`, `public/overlays/` | OK |
|
||||
| HDRIs (1k–2k for render speed) | Poly Haven, ambientCG | `public/hdri/` | OK |
|
||||
| 3D (**prefer GLB** over glTF+textures) | Poly Haven Models, Kenney, Khronos glTF samples, Sketchfab (check each) | `public/models/` | Poly Haven OK; Sketchfab VPN-ish |
|
||||
| Icons (bundle via Nexus npm, **never CDN**) | Lucide, Tabler, Heroicons, Phosphor | npm dep | npm via Nexus OK |
|
||||
| Illustrations (recolorable **SVG**) | unDraw, Open Peeps, Humaaans | `public/illustrations/` | OK |
|
||||
|
||||
For Persian/Iran imagery search English terms ("Tehran", "Iranian food") + self-shot/local stock. **Sanction-blocked at account/payment: Adobe Stock, Envato** — use a foreign account/partner or skip. **Mitigation: do one batched "asset run" over a stable tunnel, commit binaries, render never touches the open internet again.** Draco-compress GLBs (`gltf-pipeline -i in.glb -o out.glb -d`), keep low-poly for headless render speed.
|
||||
|
||||
## AI-generated assets — when it's right
|
||||
- **Use when:** the asset doesn't exist as stock (specific Persian cultural scene, branded mascot), you need consistency across a template set (reference-image control), or it beats a 5-site license hunt.
|
||||
- **Don't when:** clean CC0 already exists, you need photographic authenticity, or a free tier's **commercial license is unclear** (watermarks / non-commercial = legal landmine for a paid product).
|
||||
- **Iran-pragmatic:** self-host open models — **HunyuanVideo 1.5** (~RTX 4090, no geo-block/payment/watermark) for video; **FLUX/SDXL** locally for image/texture/illustration. Hosted SaaS (Runway, Kling) only when local quality falls short and a VPN+foreign-account path exists. **Always record prompt + tool + plan-tier + date** in the asset's `.license.txt` sidecar.
|
||||
|
||||
## Preparing footage in Remotion (composite, grade, mask, loop)
|
||||
**Primitives:** `<OffthreadVideo>` = default for **all** video in a render (FFmpeg extraction, deterministic, no seek drift). `<Video>` = preview only. `<Img>` over raw `<img>` (waits for load → no half-loaded frames). `staticFile()` for every vendored asset.
|
||||
|
||||
```tsx
|
||||
import { OffthreadVideo, Img, staticFile, useCurrentFrame, interpolate, Easing } from "remotion";
|
||||
import { useLayout } from "./lib/aspect";
|
||||
|
||||
const frame = useCurrentFrame();
|
||||
const L = useLayout();
|
||||
|
||||
// Ken-Burns: overscan ≥1 so no edges reveal; cover + center crops cleanly in all 3 aspects.
|
||||
const scale = interpolate(frame, [0, 150], [1.08, 1.2], { extrapolateRight: "clamp" });
|
||||
const ty = interpolate(frame, [0, 150], [0, L.vmin(-30)], { easing: Easing.out(Easing.cubic), extrapolateRight: "clamp" });
|
||||
|
||||
<OffthreadVideo
|
||||
src={staticFile("footage/nature/forest-loop.mp4")}
|
||||
style={{ width: "100%", height: "100%", objectFit: "cover",
|
||||
transform: `scale(${scale}) translateY(${ty}px)`,
|
||||
filter: "contrast(1.08) saturate(1.15) brightness(0.96)" }} // grade
|
||||
/>
|
||||
```
|
||||
|
||||
| Job | Pattern |
|
||||
|---|---|
|
||||
| **Color grade** | per-layer CSS `filter` (`contrast/saturate/brightness/hue-rotate`); build a shared `lib/grades.ts` (`warm`, `teal-orange`, `mono`, `filmic`) so palette can drive `hue-rotate`/`saturate`. Heavy grade → pre-grade in DaVinci Resolve (free), then commit. |
|
||||
| **Masking / keying** | no native keyer — pre-key in Resolve/AE, export **alpha** (ProRes 4444 or WebM/VP9 alpha), then `<OffthreadVideo>`. Shape masks via CSS `maskImage`/`clipPath` + `hexToRgba` gradients, or SVG `<mask>`. |
|
||||
| **Seamless loop** | source loop-designed clips (Coverr/Mixkit) or mirror-pingpong; `<OffthreadVideo loop>` once first/last frames match; crossfade-to-self with overlapping `<Sequence>` for imperfect footage. |
|
||||
| **Overlays (cheap "authentic" layer)** | stack grayscale-on-black/white clips: **screen** for light-leaks/bokeh/dust, **overlay/soft-light** for grain, **multiply** for vignettes/paper. Keep palette-independent. **Animated grain must move** — offset `background-position` per frame or jitter SVG `feTurbulence` `seed`. |
|
||||
| **Per-aspect crop** | `objectFit:"cover"` + center-safe framing; branch focal point on `L.isWide/isSquare/isTall` (or the proposed `L.pick(wide,square,tall)`) so the subject never crops out. |
|
||||
|
||||
HDRIs/GLBs: feed `staticFile("hdri/…")` into `three-kit`'s `StudioEnv`; load models with `useGLTF(staticFile("models/…glb"))`, idle-bob with `Math.sin(frame/fps)` (driven by `useCurrentFrame`, **not** `useFrame`).
|
||||
|
||||
## Library structure + attribution firewall
|
||||
Create under `public/`: `footage/{nature,business,abstract}/`, `overlays/`, `images/`, `textures/`, `hdri/`, `models/`, `icons/`, `illustrations/`, plus **`assets.json`** + **`ASSETS.md`**. Lowercase-kebab names, no spaces. Every asset gets one `assets.json` row **at download time**:
|
||||
|
||||
```json
|
||||
{ "file": "footage/nature/forest-loop.mp4", "source": "Pexels",
|
||||
"url": "https://www.pexels.com/video/...", "author": "Name",
|
||||
"license": "Pexels", "attribution_required": false, "commercial_ok": true,
|
||||
"acquired": "2026-06-21", "notes": "1080p H.264, loops clean" }
|
||||
```
|
||||
Sidecar `.license.txt` next to AI assets (prompt + tool + date) and paid receipts. A **CI validation script** asserts every file in the media folders has a matching row with `commercial_ok:true`, else fails the build — this is the firewall. `ASSETS.md` is the generated human/legal-readable table. `attribution_required:true` must surface a credit on a shippable surface (end-card/footer). If the repo bloats, move large media to MinIO (already in stack) with a `predeploy` sync into `public/` — but present at render time.
|
||||
|
||||
## Checklist (before committing an asset / shipping a template)
|
||||
- [ ] Vendored in `public/…` and referenced via `staticFile()` — **no external URL** anywhere in the template.
|
||||
- [ ] `assets.json` row added with `commercial_ok:true`; `.license.txt`/receipt for AI/paid; CC-BY credits surfaced.
|
||||
- [ ] Right-sized (don't ship 4K into a 1080p comp); video is H.264 MP4 played via `<OffthreadVideo>`; images via `<Img>`.
|
||||
- [ ] GLB (not glTF+loose textures), Draco-compressed, low-poly; HDRI 1k–2k.
|
||||
- [ ] Footage graded through `lib/grades.ts`; overlay grain/light-leak **moves** per frame; loops are seamless.
|
||||
- [ ] Ken-Burns overscans (start scale ≥ 1.05) and `objectFit:cover` crops cleanly in 16:9 / 1:1 / 9:16 with subject in frame.
|
||||
- [ ] Re-render twice → identical (deterministic; nothing pulled from network/random/date).
|
||||
|
||||
Related: `../remotion-design-styles/SKILL.md`, `../remotion-template-composition/SKILL.md`, `../remotion-aspect-ratios/SKILL.md`, `../remotion-character-design/SKILL.md`, `../remotion-svg-colors/SKILL.md`, `../remotion-music-picker/SKILL.md`, `../remotion-sound-effects/SKILL.md`, `../persian-fonts/SKILL.md`, `../flatrender-template-seo/SKILL.md`.
|
||||
Reference in New Issue
Block a user