Files
AISkills/asset-sourcing/SKILL.md
T
Soroush Asadi 6cf6d8953f feat: design+motion R&D report and 6 professional craft skills
R&D brief (references/design-motion-rnd.md): 2024-2026 design/motion trends,
animating-anything craft, Iran-aware asset pipeline, masterpiece + platform playbook.

New craft skills: motion-design-principles, scene-transitions, kinetic-typography,
video-hooks, particles-and-effects, asset-sourcing — grounded in the Remotion stack.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 19:09:03 +03:30

9.2 KiB
Raw Blame History

name, description
name description
asset-sourcing 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 (useLayoutisWide/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 (1k2k 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.

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:

{ "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 1k2k.
  • 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, remotion-template-composition, remotion-aspect-ratios, remotion-character-design, remotion-svg-colors, remotion-music-picker, remotion-sound-effects, persian-fonts, flatrender-template-seo.