{
  "schemaVersion": "1.0",
  "item": {
    "slug": "remotion-video-generator",
    "name": "Remotion Video Generator",
    "source": "tencent",
    "type": "skill",
    "category": "AI 智能",
    "sourceUrl": "https://clawhub.ai/zendenho7/remotion-video-generator",
    "canonicalUrl": "https://clawhub.ai/zendenho7/remotion-video-generator",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/remotion-video-generator",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=remotion-video-generator",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "references/components.md",
      "references/composition-patterns.md",
      "scripts/remotion.sh",
      "scripts/scrapling.sh"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/remotion-video-generator"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/remotion-video-generator",
    "agentPageUrl": "https://openagent3.xyz/skills/remotion-video-generator/agent",
    "manifestUrl": "https://openagent3.xyz/skills/remotion-video-generator/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/remotion-video-generator/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Remotion Video Generator",
        "body": "\"Create professional motion graphics videos programmatically with React and Remotion.\""
      },
      {
        "title": "Original Skill",
        "body": "Source: Superskills - Video Generator (Remotion)\nAuthor: Riley Brown / VibeCode Community"
      },
      {
        "title": "Modifications",
        "body": "Firecrawl replaced with Scrapling for brand data extraction\nUses Python scrapling library instead of Firecrawl API\nAdded comprehensive troubleshooting for Remotion v4 API"
      },
      {
        "title": "Core Technologies",
        "body": "Remotion: https://www.remotion.dev/\nScrapling: https://github.com/D4Vinci/Scrapling\nReact: https://react.dev/"
      },
      {
        "title": "Tested With",
        "body": "OpenClaw promotional video - successfully rendered! 🎉"
      },
      {
        "title": "Step 1: Scrape Brand Data",
        "body": "# Run the scrapling script to get brand colors, logo, tagline\nbash skills/remotion-video-generator/scripts/scrapling.sh \"https://brand-website.com\"\n\nThis extracts: brandName, tagline, logoUrl, faviconUrl, primaryColors, ogImageUrl, screenshotUrl"
      },
      {
        "title": "Step 2: Download Brand Assets",
        "body": "mkdir -p public/images/brand\ncurl -sL \"https://brand.com/logo.svg\" -o public/images/brand/logo.svg\ncurl -sL \"https://brand.com/og-image.png\" -o public/images/brand/og-image.png\ncurl -sL \"https://image.thum.io/get/width/1200/crop/800/https://brand.com\" -o screenshot.png"
      },
      {
        "title": "Step 3: Create Project Structure",
        "body": "mkdir -p my-video/src my-video/public/images/brand my-video/public/audio"
      },
      {
        "title": "Step 4: Create package.json",
        "body": "{\n  \"name\": \"my-video\",\n  \"scripts\": {\n    \"dev\": \"npx remotion studio\",\n    \"build\": \"npx remotion bundle\"\n  },\n  \"dependencies\": {\n    \"@remotion/cli\": \"^4.0.0\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"remotion\": \"^4.0.0\",\n    \"lucide-react\": \"^0.300.0\"\n  }\n}"
      },
      {
        "title": "Step 5: Install Dependencies",
        "body": "cd my-video && npm install"
      },
      {
        "title": "Step 6: Create Video Component",
        "body": "Create src/MyVideo.tsx with:\n\nAbsoluteFill for full-screen layout\nSequence components for scene timing\nuseCurrentFrame, useVideoConfig, interpolate, spring for animations"
      },
      {
        "title": "Step 7: Create Entry Point (Remotion v4 API)",
        "body": "Create src/index.tsx - MUST use .tsx extension:\n\nimport { registerRoot, Composition } from \"remotion\";\nimport { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate, spring } from \"remotion\";\n\nconst MyVideo = () => {\n  const frame = useCurrentFrame();\n  const { fps } = useVideoConfig();\n\n  // Animations - ALWAYS pass fps to spring()\n  const scale = spring({ frame, fps, from: 0.8, to: 1 });\n\n  return (\n    <AbsoluteFill style={{ backgroundColor: \"#000\" }}>\n      <Sequence from={0} durationInFrames={90}>\n        <h1>Hello World</h1>\n      </Sequence>\n    </AbsoluteFill>\n  );\n};\n\nregisterRoot(() => {\n  return (\n    <Composition\n      id=\"MyVideo\"\n      component={MyVideo}\n      durationInFrames={240}\n      fps={30}\n      width={1920}\n      height={1080}\n    />\n  );\n});\n\n⚠️ CRITICAL Remotion v4 Rules:\n\nUse .tsx extension (NOT .ts) for files with JSX\nMUST use registerRoot + Composition API\nALWAYS pass fps to spring(): spring({ frame, fps, from: 0.8, to: 1 })\nUse useVideoConfig() to get fps: const { fps } = useVideoConfig()\nRender with composition name: npx remotion render MyVideo out/video.mp4"
      },
      {
        "title": "Step 8: Start Dev Server",
        "body": "cd my-video && npm run dev\n\nServer runs on http://localhost:3000"
      },
      {
        "title": "Step 9: Preview & Iterate",
        "body": "Open browser to preview\nEdit source files - hot-reloads automatically\nUser reviews and requests changes"
      },
      {
        "title": "Step 10: Render Final Video (when user asks)",
        "body": "npx remotion render index out/final-video.mp4"
      },
      {
        "title": "Credits",
        "body": "Original Skill: https://superskills.vibecode.run/\nModified: Firecrawl replaced with Scrapling for brand data extraction\nRemotion: https://www.remotion.dev/"
      },
      {
        "title": "Installation",
        "body": "# Install Remotion globally\nnpm install -g remotion\n\n# Install dependencies for video projects\nnpm install lucide-react\n\n# Install Scrapling (already in workspace skills)\npip install scrapling"
      },
      {
        "title": "When to Use Video Generator",
        "body": "Use this skill when:\n\nCreating promotional videos\nMaking product demos\nSocial media video content\nAnimated explainers\nCommercials\nAny programmatic video content\n\nDo NOT use for:\n\nSimple slideshows (use other tools)\nVideo editing of existing footage\nLive streaming"
      },
      {
        "title": "Default Workflow (ALWAYS follow this)",
        "body": "Scrape brand data (if featuring a product) using Scrapling (NOT Firecrawl)\nCreate the project in output/<project-name>/\nBuild all scenes with proper motion graphics\nInstall dependencies with npm install\nFix package.json scripts to use npx remotion (not bun):\n\"scripts\": {\n  \"dev\": \"npx remotion studio\",\n  \"build\": \"npx remotion bundle\"\n}\n\n\nStart Remotion Studio as a background process:\ncd output/<project-name> && npm run dev\n\n\nExpose via Cloudflare tunnel so user can access:\nbash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000\n\n\nSend the user the public URL (e.g. https://xxx.trycloudflare.com)\n\nThe user will preview in their browser, request changes, and you edit the source files. Remotion hot-reloads automatically."
      },
      {
        "title": "Rendering (only when user explicitly asks to export)",
        "body": "cd output/<project-name>\nnpx remotion render CompositionName out/video.mp4"
      },
      {
        "title": "Quick Start",
        "body": "# Scaffold project\ncd output && npx --yes create-video@latest my-video --template blank\ncd my-video && npm install\n\n# Add motion libraries\nnpm install lucide-react\n\n# Fix scripts in package.json (replace any \"bun\" references with \"npx remotion\")\n\n# Start dev server\nnpm run dev\n\n# Expose publicly\nbash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000"
      },
      {
        "title": "Fetching Brand Data with Scrapling",
        "body": "MANDATORY: When a video mentions or features any product/company, use Scrapling to scrape the product's website for brand data, colors, screenshots, and copy BEFORE designing the video. This ensures visual accuracy and brand consistency."
      },
      {
        "title": "Using the Scrapling Script",
        "body": "# Run the brand data extraction script\nbash skills/remotion-video-generator/scripts/scrapling.sh \"https://example.com\"\n\nThis returns structured brand data: brandName, tagline, headline, description, features, logoUrl, faviconUrl, primaryColors, ctaText, socialLinks, plus screenshot URL and OG image URL."
      },
      {
        "title": "Manual Scrapling Extraction",
        "body": "If the script isn't available, use Python directly:\n\nimport json\nfrom scrapling.fetchers import StealthyFetcher\nfrom urllib.parse import urljoin\nimport re\n\nurl = 'https://brand.com'\npage = StealthyFetcher.fetch(url, headless=True)\nhtml = page.text\n\ndef resolve(u):\n    return urljoin(url, u) if u and not u.startswith('http') else u\n\ncolors = list(set(re.findall(r'#(?:[0-9a-fA-F]{3}){1,2}', html)))[:5]\n\ndata = {\n    'brandName': page.css('[property=\"og:site_name\"]::text').get() or page.title(),\n    'tagline': page.css('[property=\"og:description\"]::text').get(),\n    'headline': page.css('h1::text').get(),\n    'description': page.css('[property=\"og:description\"]::text').get(),\n    'logoUrl': resolve(page.css('[rel=\"icon\"]::attr(href)').get()),\n    'faviconUrl': resolve(page.css('[rel=\"icon\"]::attr(href)').get()),\n    'primaryColors': colors,\n    'ctaText': page.css('a[href*=\"signup\"]::text').get(),\n    'ogImageUrl': resolve(page.css('[property=\"og:image\"]::attr(content)').get()),\n    'screenshotUrl': f\"https://image.thum.io/get/width/1200/crop/800/{url}\"\n}\n\nprint(json.dumps(data, indent=2))"
      },
      {
        "title": "Download Assets After Scraping",
        "body": "mkdir -p public/images/brand\ncurl -s \"https://example.com/favicon.ico\" -o public/images/brand/favicon.ico\ncurl -s \"${OG_IMAGE_URL}\" -o public/images/brand/og-image.png\ncurl -sL \"${SCREENSHOT_URL}\" -o public/images/brand/screenshot.png\n\nNote: Some S3 buckets block direct access. Use thum.io screenshot service as fallback."
      },
      {
        "title": "Scene Management",
        "body": "Use scene-based architecture with proper transitions:\n\nconst SCENE_DURATIONS: Record<string, number> = {\n  intro: 3000,      // 3s hook\n  problem: 4000,    // 4s dramatic\n  solution: 3500,   // 3.5s reveal\n  features: 5000,  // 5s showcase\n  cta: 3000,        // 3s close\n};"
      },
      {
        "title": "Video Structure Pattern",
        "body": "import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate, spring, Img, staticFile, Audio } from \"remotion\";\n\nexport const MyVideo = () => {\n  const frame = useCurrentFrame();\n  const { fps, durationInFrames } = useVideoConfig();\n\n  return (\n    <AbsoluteFill>\n      {/* Background music */}\n      <Audio src={staticFile(\"audio/bg-music.mp3\")} volume={0.35} />\n\n      {/* Persistent background layer - OUTSIDE sequences */}\n      <AnimatedBackground frame={frame} />\n\n      {/* Scene sequences */}\n      <Sequence from={0} durationInFrames={90}>\n        <IntroScene />\n      </Sequence>\n      <Sequence from={90} durationInFrames={120}>\n        <FeatureScene />\n      </Sequence>\n    </AbsoluteFill>\n  );\n};"
      },
      {
        "title": "AVOID (Slideshow patterns)",
        "body": "Fading to black between scenes\nCentered text on solid backgrounds\nSame transition for everything\nLinear/robotic animations\nStatic screens\nEmoji icons — NEVER use emoji, always use Lucide React icons"
      },
      {
        "title": "PURSUE (Motion graphics)",
        "body": "Overlapping transitions (next starts BEFORE current ends)\nLayered compositions (background/midground/foreground)\nSpring physics for organic motion\nVaried timing (2-5s scenes, mixed rhythms)\nContinuous visual elements across scenes\nCustom transitions with clipPath, 3D transforms, morphs\nLucide React for ALL icons (npm install lucide-react) — never emoji"
      },
      {
        "title": "Transition Techniques",
        "body": "TechniqueDescriptionMorph/ScaleElement scales up to fill screen, becomes next scene's backgroundWipeColored shape sweeps across, revealing next sceneZoom-throughCamera pushes into element, emerges into new sceneClip-path revealCircle/polygon grows from point to revealPersistent anchorOne element stays while surroundings changeDirectional flowScene 1 exits right, Scene 2 enters from rightSplit/unfoldScreen divides, panels slide apartPerspective flipScene rotates on Y-axis in 3D"
      },
      {
        "title": "Animation Timing Reference",
        "body": "// Timing values (in seconds)\nconst timing = {\n  micro: 0.1-0.2,     // Small shifts, subtle feedback\n  snappy: 0.2-0.4,    // Element entrances, position changes\n  standard: 0.5-0.8,   // Scene transitions, major reveals\n  dramatic: 1.0-1.5,  // Hero moments, cinematic reveals\n};\n\n// Spring configs\nconst springs = {\n  snappy: { stiffness: 400, damping: 30 },\n  bouncy: { stiffness: 300, damping: 15 },\n  smooth: { stiffness: 120, damping: 25 },\n};"
      },
      {
        "title": "Typography",
        "body": "One display font + one body font max\nMassive headlines, tight tracking\nMix weights for hierarchy\nKeep text SHORT (viewers can't pause)"
      },
      {
        "title": "Colors",
        "body": "Use brand colors from Scrapling scrape as the primary palette — match the product's actual look\nAvoid purple/indigo gradients unless the brand uses them or the user explicitly requests them\nSimple, clean backgrounds are generally best — a single dark tone or subtle gradient beats layered textures\nIntentional accent colors pulled from the brand"
      },
      {
        "title": "Layout",
        "body": "Use asymmetric layouts, off-center type\nEdge-aligned elements create visual tension\nGenerous whitespace as design element\nUse depth sparingly — a subtle backdrop blur or single gradient, not stacked textures"
      },
      {
        "title": "Interpolation",
        "body": "const opacity = interpolate(frame, [0, 30], [0, 1], {\n  extrapolateLeft: \"clamp\",\n  extrapolateRight: \"clamp\"\n});\n\nconst scale = spring({\n  frame,\n  fps,\n  from: 0.8,\n  to: 1,\n  durationInFrames: 30,\n  config: { damping: 12 }\n});"
      },
      {
        "title": "Sequences with Overlap",
        "body": "<Sequence from={0} durationInFrames={100}>\n  <Scene1 />\n</Sequence>\n<Sequence from={80} durationInFrames={100}>\n  <Scene2 />\n</Sequence>"
      },
      {
        "title": "Cross-Scene Continuity",
        "body": "Place persistent elements OUTSIDE Sequence blocks:\n\nconst PersistentShape = ({ currentScene }: { currentScene: number }) => {\n  const positions = {\n    0: { x: 100, y: 100, scale: 1, opacity: 0.3 },\n    1: { x: 800, y: 200, scale: 2, opacity: 0.5 },\n    2: { x: 400, y: 600, scale: 0.5, opacity: 1 },\n  };\n\n  return (\n    <motion.div\n      animate={positions[currentScene]}\n      transition={{ duration: 0.8, ease: \"easeInOut\" }}\n      className=\"absolute w-32 h-32 rounded-full bg-gradient-to-r from-coral to-orange\"\n    />\n  );\n};"
      },
      {
        "title": "Quality Tests",
        "body": "Before delivering, verify:\n\nMute test: Story follows visually without sound?\nSquint test: Hierarchy visible when squinting?\nTiming test: Motion feels natural, not robotic?\nConsistency test: Similar elements behave similarly?\nSlideshow test: Does NOT look like PowerPoint?\nLoop test: Video loops smoothly back to start?"
      },
      {
        "title": "Implementation Steps",
        "body": "Scrapling brand scrape — If featuring a product, scrape its site first\nDirector's treatment — Write vibe, camera style, emotional arc\nVisual direction — Colors, fonts, brand feel, animation style\nScene breakdown — List every scene with description, duration, text, transitions\nPlan assets — User assets + generated images/videos + brand scrape assets\nDefine durations — Vary pacing (2-3s punchy, 4-5s dramatic)\nBuild persistent layer — Animated background outside scenes\nBuild scenes — Each with enter/exit animations, 3-5 timed moments\nOpen with hook — High-impact first scene\nDevelop narrative — Content-driven middle scenes\nStrong ending — Intentional, resolved close\nStart Remotion Studio — npm run dev on port 3000\nExpose via tunnel — bash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000\nSend user the public URL — They preview and request changes live\nIterate — Edit source, hot-reload, repeat\nRender — Only when user says to export final video"
      },
      {
        "title": "File Structure",
        "body": "my-video/\n├── src/\n│   ├── Root.tsx          # Composition definitions\n│   ├── index.ts          # Entry point\n│   ├── index.css         # Global styles\n│   ├── MyVideo.tsx       # Main video component\n│   └── scenes/           # Scene components (optional)\n├── public/\n│   ├── images/\n│   │   └── brand/        # Scrapling-scraped assets\n│   └── audio/            # Background music\n├── remotion.config.ts\n└── package.json"
      },
      {
        "title": "Common Components",
        "body": "See references/components.md for reusable:\n\nAnimated backgrounds\nTerminal windows\nFeature cards\nStats displays\nCTA buttons\nText reveal animations"
      },
      {
        "title": "Tunnel Management",
        "body": "# Start tunnel (exposes port 3000 publicly)\nbash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000\n\n# Check status\nbash skills/cloudflare-tunnel/scripts/tunnel.sh status 3000\n\n# List all tunnels\nbash skills/cloudflare-tunnel/scripts/tunnel.sh list\n\n# Stop tunnel\nbash skills/cloudflare-tunnel/scripts/tunnel.sh stop 3000"
      },
      {
        "title": "Common Issues & Fixes",
        "body": "IssueSolutionExpected \">\" but found \"schema\"Use .tsx extension for files with JSX, not .tsuseCurrentFrame() can only be called inside a componentUse registerRoot + Composition API (see Step 7)\"fps\" must be a number, but you passed undefined to spring()Pass fps to spring: spring({ frame, fps, from: 0.8, to: 1 })Could not find composition with ID indexUse composition name: npx remotion render MyVideo out.mp4Module build failedEnsure react and react-dom are in dependenciesRemotion not foundRun npm install in project directoryHot reload not workingEnsure running npm run dev, not npx remotion directlyBrand colors not extractingSome sites use CSS variables - check page source manually"
      },
      {
        "title": "File Extension Rules",
        "body": "Use .tsx for files with JSX (components with < tags >)\nUse .ts for pure TypeScript files\nEntry point MUST be .tsx if it uses JSX"
      },
      {
        "title": "Testing Your Video",
        "body": "Start dev server: npm run dev\nOpen http://localhost:3000\nMake changes - auto-refreshes\nCheck composition in browser"
      },
      {
        "title": "v1.0.0 (2026-02-25)",
        "body": "Initial release (adapted from superskills)\nFirecrawl replaced with Scrapling for brand data extraction\nUses StealthyFetcher for JS-heavy sites\nFull brand data extraction: brandName, tagline, headline, description, features, logoUrl, faviconUrl, primaryColors, ctaText, socialLinks, screenshotUrl, ogImageUrl"
      },
      {
        "title": "v1.1.0 (2026-02-25)",
        "body": "Added Quick Usage Guide with step-by-step instructions\nAdded troubleshooting section for common issues\nTested with OpenClaw promotional video - working! 🎉\nDocumented file extension requirements (.tsx vs .ts)\nFixed Remotion v4 API: registerRoot + Composition pattern\nFixed spring() must receive fps parameter\nFixed composition name in render command"
      },
      {
        "title": "Practical Example: OpenClaw Promo Video",
        "body": "Here's the actual project created during testing:\n\nLocation: skills/remotion-video-generator/openclaw-promo/\n\nBrand Data Extracted:\n\nTagline: \"The AI that actually does things.\"\nLogo: favicon.svg from openclaw.ai\nPrimary Color: #FF6B35 (extracted from design)\nScreenshot: Generated via thum.io\n\nProject Structure:\n\nopenclaw-promo/\n├── src/\n│   ├── index.tsx        # Entry point\n│   └── OpenClawPromo.tsx # Video component\n├── public/\n│   └── images/\n│       └── brand/\n│           ├── logo.svg\n│           ├── og-image.png\n│           └── screenshot.png\n├── package.json\n└── tsconfig.json\n\nCommands:\n\ncd skills/remotion-video-generator/openclaw-promo\nnpm run dev    # Start studio at localhost:3000\nnpm run build  # Bundle for production\n\nLast updated: 2026-02-25"
      }
    ],
    "body": "Remotion Video Generator\n\n\"Create professional motion graphics videos programmatically with React and Remotion.\"\n\nCredits & References\nOriginal Skill\nSource: Superskills - Video Generator (Remotion)\nAuthor: Riley Brown / VibeCode Community\nModifications\nFirecrawl replaced with Scrapling for brand data extraction\nUses Python scrapling library instead of Firecrawl API\nAdded comprehensive troubleshooting for Remotion v4 API\nCore Technologies\nRemotion: https://www.remotion.dev/\nScrapling: https://github.com/D4Vinci/Scrapling\nReact: https://react.dev/\nTested With\nOpenClaw promotional video - successfully rendered! 🎉\nQuick Usage Guide (Step-by-Step)\nStep 1: Scrape Brand Data\n# Run the scrapling script to get brand colors, logo, tagline\nbash skills/remotion-video-generator/scripts/scrapling.sh \"https://brand-website.com\"\n\n\nThis extracts: brandName, tagline, logoUrl, faviconUrl, primaryColors, ogImageUrl, screenshotUrl\n\nStep 2: Download Brand Assets\nmkdir -p public/images/brand\ncurl -sL \"https://brand.com/logo.svg\" -o public/images/brand/logo.svg\ncurl -sL \"https://brand.com/og-image.png\" -o public/images/brand/og-image.png\ncurl -sL \"https://image.thum.io/get/width/1200/crop/800/https://brand.com\" -o screenshot.png\n\nStep 3: Create Project Structure\nmkdir -p my-video/src my-video/public/images/brand my-video/public/audio\n\nStep 4: Create package.json\n{\n  \"name\": \"my-video\",\n  \"scripts\": {\n    \"dev\": \"npx remotion studio\",\n    \"build\": \"npx remotion bundle\"\n  },\n  \"dependencies\": {\n    \"@remotion/cli\": \"^4.0.0\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"remotion\": \"^4.0.0\",\n    \"lucide-react\": \"^0.300.0\"\n  }\n}\n\nStep 5: Install Dependencies\ncd my-video && npm install\n\nStep 6: Create Video Component\n\nCreate src/MyVideo.tsx with:\n\nAbsoluteFill for full-screen layout\nSequence components for scene timing\nuseCurrentFrame, useVideoConfig, interpolate, spring for animations\nStep 7: Create Entry Point (Remotion v4 API)\n\nCreate src/index.tsx - MUST use .tsx extension:\n\nimport { registerRoot, Composition } from \"remotion\";\nimport { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate, spring } from \"remotion\";\n\nconst MyVideo = () => {\n  const frame = useCurrentFrame();\n  const { fps } = useVideoConfig();\n\n  // Animations - ALWAYS pass fps to spring()\n  const scale = spring({ frame, fps, from: 0.8, to: 1 });\n\n  return (\n    <AbsoluteFill style={{ backgroundColor: \"#000\" }}>\n      <Sequence from={0} durationInFrames={90}>\n        <h1>Hello World</h1>\n      </Sequence>\n    </AbsoluteFill>\n  );\n};\n\nregisterRoot(() => {\n  return (\n    <Composition\n      id=\"MyVideo\"\n      component={MyVideo}\n      durationInFrames={240}\n      fps={30}\n      width={1920}\n      height={1080}\n    />\n  );\n});\n\n\n⚠️ CRITICAL Remotion v4 Rules:\n\nUse .tsx extension (NOT .ts) for files with JSX\nMUST use registerRoot + Composition API\nALWAYS pass fps to spring(): spring({ frame, fps, from: 0.8, to: 1 })\nUse useVideoConfig() to get fps: const { fps } = useVideoConfig()\nRender with composition name: npx remotion render MyVideo out/video.mp4\nStep 8: Start Dev Server\ncd my-video && npm run dev\n\n\nServer runs on http://localhost:3000\n\nStep 9: Preview & Iterate\nOpen browser to preview\nEdit source files - hot-reloads automatically\nUser reviews and requests changes\nStep 10: Render Final Video (when user asks)\nnpx remotion render index out/final-video.mp4\n\nCredits\nOriginal Skill: https://superskills.vibecode.run/\nModified: Firecrawl replaced with Scrapling for brand data extraction\nRemotion: https://www.remotion.dev/\nInstallation\n# Install Remotion globally\nnpm install -g remotion\n\n# Install dependencies for video projects\nnpm install lucide-react\n\n# Install Scrapling (already in workspace skills)\npip install scrapling\n\nAgent Instructions\nWhen to Use Video Generator\n\nUse this skill when:\n\nCreating promotional videos\nMaking product demos\nSocial media video content\nAnimated explainers\nCommercials\nAny programmatic video content\n\nDo NOT use for:\n\nSimple slideshows (use other tools)\nVideo editing of existing footage\nLive streaming\nDefault Workflow (ALWAYS follow this)\nScrape brand data (if featuring a product) using Scrapling (NOT Firecrawl)\nCreate the project in output/<project-name>/\nBuild all scenes with proper motion graphics\nInstall dependencies with npm install\nFix package.json scripts to use npx remotion (not bun):\n\"scripts\": {\n  \"dev\": \"npx remotion studio\",\n  \"build\": \"npx remotion bundle\"\n}\n\nStart Remotion Studio as a background process:\ncd output/<project-name> && npm run dev\n\nExpose via Cloudflare tunnel so user can access:\nbash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000\n\nSend the user the public URL (e.g. https://xxx.trycloudflare.com)\n\nThe user will preview in their browser, request changes, and you edit the source files. Remotion hot-reloads automatically.\n\nRendering (only when user explicitly asks to export)\ncd output/<project-name>\nnpx remotion render CompositionName out/video.mp4\n\nQuick Start\n# Scaffold project\ncd output && npx --yes create-video@latest my-video --template blank\ncd my-video && npm install\n\n# Add motion libraries\nnpm install lucide-react\n\n# Fix scripts in package.json (replace any \"bun\" references with \"npx remotion\")\n\n# Start dev server\nnpm run dev\n\n# Expose publicly\nbash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000\n\nFetching Brand Data with Scrapling\n\nMANDATORY: When a video mentions or features any product/company, use Scrapling to scrape the product's website for brand data, colors, screenshots, and copy BEFORE designing the video. This ensures visual accuracy and brand consistency.\n\nUsing the Scrapling Script\n# Run the brand data extraction script\nbash skills/remotion-video-generator/scripts/scrapling.sh \"https://example.com\"\n\n\nThis returns structured brand data: brandName, tagline, headline, description, features, logoUrl, faviconUrl, primaryColors, ctaText, socialLinks, plus screenshot URL and OG image URL.\n\nManual Scrapling Extraction\n\nIf the script isn't available, use Python directly:\n\nimport json\nfrom scrapling.fetchers import StealthyFetcher\nfrom urllib.parse import urljoin\nimport re\n\nurl = 'https://brand.com'\npage = StealthyFetcher.fetch(url, headless=True)\nhtml = page.text\n\ndef resolve(u):\n    return urljoin(url, u) if u and not u.startswith('http') else u\n\ncolors = list(set(re.findall(r'#(?:[0-9a-fA-F]{3}){1,2}', html)))[:5]\n\ndata = {\n    'brandName': page.css('[property=\"og:site_name\"]::text').get() or page.title(),\n    'tagline': page.css('[property=\"og:description\"]::text').get(),\n    'headline': page.css('h1::text').get(),\n    'description': page.css('[property=\"og:description\"]::text').get(),\n    'logoUrl': resolve(page.css('[rel=\"icon\"]::attr(href)').get()),\n    'faviconUrl': resolve(page.css('[rel=\"icon\"]::attr(href)').get()),\n    'primaryColors': colors,\n    'ctaText': page.css('a[href*=\"signup\"]::text').get(),\n    'ogImageUrl': resolve(page.css('[property=\"og:image\"]::attr(content)').get()),\n    'screenshotUrl': f\"https://image.thum.io/get/width/1200/crop/800/{url}\"\n}\n\nprint(json.dumps(data, indent=2))\n\nDownload Assets After Scraping\nmkdir -p public/images/brand\ncurl -s \"https://example.com/favicon.ico\" -o public/images/brand/favicon.ico\ncurl -s \"${OG_IMAGE_URL}\" -o public/images/brand/og-image.png\ncurl -sL \"${SCREENSHOT_URL}\" -o public/images/brand/screenshot.png\n\n\nNote: Some S3 buckets block direct access. Use thum.io screenshot service as fallback.\n\nCore Architecture\nScene Management\n\nUse scene-based architecture with proper transitions:\n\nconst SCENE_DURATIONS: Record<string, number> = {\n  intro: 3000,      // 3s hook\n  problem: 4000,    // 4s dramatic\n  solution: 3500,   // 3.5s reveal\n  features: 5000,  // 5s showcase\n  cta: 3000,        // 3s close\n};\n\nVideo Structure Pattern\nimport { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig, interpolate, spring, Img, staticFile, Audio } from \"remotion\";\n\nexport const MyVideo = () => {\n  const frame = useCurrentFrame();\n  const { fps, durationInFrames } = useVideoConfig();\n\n  return (\n    <AbsoluteFill>\n      {/* Background music */}\n      <Audio src={staticFile(\"audio/bg-music.mp3\")} volume={0.35} />\n\n      {/* Persistent background layer - OUTSIDE sequences */}\n      <AnimatedBackground frame={frame} />\n\n      {/* Scene sequences */}\n      <Sequence from={0} durationInFrames={90}>\n        <IntroScene />\n      </Sequence>\n      <Sequence from={90} durationInFrames={120}>\n        <FeatureScene />\n      </Sequence>\n    </AbsoluteFill>\n  );\n};\n\nMotion Graphics Principles\nAVOID (Slideshow patterns)\nFading to black between scenes\nCentered text on solid backgrounds\nSame transition for everything\nLinear/robotic animations\nStatic screens\nEmoji icons — NEVER use emoji, always use Lucide React icons\nPURSUE (Motion graphics)\nOverlapping transitions (next starts BEFORE current ends)\nLayered compositions (background/midground/foreground)\nSpring physics for organic motion\nVaried timing (2-5s scenes, mixed rhythms)\nContinuous visual elements across scenes\nCustom transitions with clipPath, 3D transforms, morphs\nLucide React for ALL icons (npm install lucide-react) — never emoji\nTransition Techniques\nTechnique\tDescription\nMorph/Scale\tElement scales up to fill screen, becomes next scene's background\nWipe\tColored shape sweeps across, revealing next scene\nZoom-through\tCamera pushes into element, emerges into new scene\nClip-path reveal\tCircle/polygon grows from point to reveal\nPersistent anchor\tOne element stays while surroundings change\nDirectional flow\tScene 1 exits right, Scene 2 enters from right\nSplit/unfold\tScreen divides, panels slide apart\nPerspective flip\tScene rotates on Y-axis in 3D\nAnimation Timing Reference\n// Timing values (in seconds)\nconst timing = {\n  micro: 0.1-0.2,     // Small shifts, subtle feedback\n  snappy: 0.2-0.4,    // Element entrances, position changes\n  standard: 0.5-0.8,   // Scene transitions, major reveals\n  dramatic: 1.0-1.5,  // Hero moments, cinematic reveals\n};\n\n// Spring configs\nconst springs = {\n  snappy: { stiffness: 400, damping: 30 },\n  bouncy: { stiffness: 300, damping: 15 },\n  smooth: { stiffness: 120, damping: 25 },\n};\n\nVisual Style Guidelines\nTypography\nOne display font + one body font max\nMassive headlines, tight tracking\nMix weights for hierarchy\nKeep text SHORT (viewers can't pause)\nColors\nUse brand colors from Scrapling scrape as the primary palette — match the product's actual look\nAvoid purple/indigo gradients unless the brand uses them or the user explicitly requests them\nSimple, clean backgrounds are generally best — a single dark tone or subtle gradient beats layered textures\nIntentional accent colors pulled from the brand\nLayout\nUse asymmetric layouts, off-center type\nEdge-aligned elements create visual tension\nGenerous whitespace as design element\nUse depth sparingly — a subtle backdrop blur or single gradient, not stacked textures\nRemotion Essentials\nInterpolation\nconst opacity = interpolate(frame, [0, 30], [0, 1], {\n  extrapolateLeft: \"clamp\",\n  extrapolateRight: \"clamp\"\n});\n\nconst scale = spring({\n  frame,\n  fps,\n  from: 0.8,\n  to: 1,\n  durationInFrames: 30,\n  config: { damping: 12 }\n});\n\nSequences with Overlap\n<Sequence from={0} durationInFrames={100}>\n  <Scene1 />\n</Sequence>\n<Sequence from={80} durationInFrames={100}>\n  <Scene2 />\n</Sequence>\n\nCross-Scene Continuity\n\nPlace persistent elements OUTSIDE Sequence blocks:\n\nconst PersistentShape = ({ currentScene }: { currentScene: number }) => {\n  const positions = {\n    0: { x: 100, y: 100, scale: 1, opacity: 0.3 },\n    1: { x: 800, y: 200, scale: 2, opacity: 0.5 },\n    2: { x: 400, y: 600, scale: 0.5, opacity: 1 },\n  };\n\n  return (\n    <motion.div\n      animate={positions[currentScene]}\n      transition={{ duration: 0.8, ease: \"easeInOut\" }}\n      className=\"absolute w-32 h-32 rounded-full bg-gradient-to-r from-coral to-orange\"\n    />\n  );\n};\n\nQuality Tests\n\nBefore delivering, verify:\n\nMute test: Story follows visually without sound?\nSquint test: Hierarchy visible when squinting?\nTiming test: Motion feels natural, not robotic?\nConsistency test: Similar elements behave similarly?\nSlideshow test: Does NOT look like PowerPoint?\nLoop test: Video loops smoothly back to start?\nImplementation Steps\nScrapling brand scrape — If featuring a product, scrape its site first\nDirector's treatment — Write vibe, camera style, emotional arc\nVisual direction — Colors, fonts, brand feel, animation style\nScene breakdown — List every scene with description, duration, text, transitions\nPlan assets — User assets + generated images/videos + brand scrape assets\nDefine durations — Vary pacing (2-3s punchy, 4-5s dramatic)\nBuild persistent layer — Animated background outside scenes\nBuild scenes — Each with enter/exit animations, 3-5 timed moments\nOpen with hook — High-impact first scene\nDevelop narrative — Content-driven middle scenes\nStrong ending — Intentional, resolved close\nStart Remotion Studio — npm run dev on port 3000\nExpose via tunnel — bash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000\nSend user the public URL — They preview and request changes live\nIterate — Edit source, hot-reload, repeat\nRender — Only when user says to export final video\nFile Structure\nmy-video/\n├── src/\n│   ├── Root.tsx          # Composition definitions\n│   ├── index.ts          # Entry point\n│   ├── index.css         # Global styles\n│   ├── MyVideo.tsx       # Main video component\n│   └── scenes/           # Scene components (optional)\n├── public/\n│   ├── images/\n│   │   └── brand/        # Scrapling-scraped assets\n│   └── audio/            # Background music\n├── remotion.config.ts\n└── package.json\n\nCommon Components\n\nSee references/components.md for reusable:\n\nAnimated backgrounds\nTerminal windows\nFeature cards\nStats displays\nCTA buttons\nText reveal animations\nTunnel Management\n# Start tunnel (exposes port 3000 publicly)\nbash skills/cloudflare-tunnel/scripts/tunnel.sh start 3000\n\n# Check status\nbash skills/cloudflare-tunnel/scripts/tunnel.sh status 3000\n\n# List all tunnels\nbash skills/cloudflare-tunnel/scripts/tunnel.sh list\n\n# Stop tunnel\nbash skills/cloudflare-tunnel/scripts/tunnel.sh stop 3000\n\nTroubleshooting\nCommon Issues & Fixes\nIssue\tSolution\nExpected \">\" but found \"schema\"\tUse .tsx extension for files with JSX, not .ts\nuseCurrentFrame() can only be called inside a component\tUse registerRoot + Composition API (see Step 7)\n\"fps\" must be a number, but you passed undefined to spring()\tPass fps to spring: spring({ frame, fps, from: 0.8, to: 1 })\nCould not find composition with ID index\tUse composition name: npx remotion render MyVideo out.mp4\nModule build failed\tEnsure react and react-dom are in dependencies\nRemotion not found\tRun npm install in project directory\nHot reload not working\tEnsure running npm run dev, not npx remotion directly\nBrand colors not extracting\tSome sites use CSS variables - check page source manually\nFile Extension Rules\nUse .tsx for files with JSX (components with < tags >)\nUse .ts for pure TypeScript files\nEntry point MUST be .tsx if it uses JSX\nTesting Your Video\nStart dev server: npm run dev\nOpen http://localhost:3000\nMake changes - auto-refreshes\nCheck composition in browser\nChangelog\nv1.0.0 (2026-02-25)\nInitial release (adapted from superskills)\nFirecrawl replaced with Scrapling for brand data extraction\nUses StealthyFetcher for JS-heavy sites\nFull brand data extraction: brandName, tagline, headline, description, features, logoUrl, faviconUrl, primaryColors, ctaText, socialLinks, screenshotUrl, ogImageUrl\nv1.1.0 (2026-02-25)\nAdded Quick Usage Guide with step-by-step instructions\nAdded troubleshooting section for common issues\nTested with OpenClaw promotional video - working! 🎉\nDocumented file extension requirements (.tsx vs .ts)\nFixed Remotion v4 API: registerRoot + Composition pattern\nFixed spring() must receive fps parameter\nFixed composition name in render command\nPractical Example: OpenClaw Promo Video\n\nHere's the actual project created during testing:\n\nLocation: skills/remotion-video-generator/openclaw-promo/\n\nBrand Data Extracted:\n\nTagline: \"The AI that actually does things.\"\nLogo: favicon.svg from openclaw.ai\nPrimary Color: #FF6B35 (extracted from design)\nScreenshot: Generated via thum.io\n\nProject Structure:\n\nopenclaw-promo/\n├── src/\n│   ├── index.tsx        # Entry point\n│   └── OpenClawPromo.tsx # Video component\n├── public/\n│   └── images/\n│       └── brand/\n│           ├── logo.svg\n│           ├── og-image.png\n│           └── screenshot.png\n├── package.json\n└── tsconfig.json\n\n\nCommands:\n\ncd skills/remotion-video-generator/openclaw-promo\nnpm run dev    # Start studio at localhost:3000\nnpm run build  # Bundle for production\n\n\nLast updated: 2026-02-25"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/zendenho7/remotion-video-generator",
    "publisherUrl": "https://clawhub.ai/zendenho7/remotion-video-generator",
    "owner": "zendenho7",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/remotion-video-generator",
    "downloadUrl": "https://openagent3.xyz/downloads/remotion-video-generator",
    "agentUrl": "https://openagent3.xyz/skills/remotion-video-generator/agent",
    "manifestUrl": "https://openagent3.xyz/skills/remotion-video-generator/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/remotion-video-generator/agent.md"
  }
}