YouTube intro
Channel opener: the channel mark, then the video's title, joined by an accent sweep.
YoutubeIntro, defaults
Installation
npx shadcn add https://www.reelcn.dev/r/youtube-intro.jsonFiles land in src/reelcn/ with the items it builds on. Dependencies: zod.
Register the composition
<Composition
id="YoutubeIntro"
component={YoutubeIntro}
schema={youtubeIntroSchema}
defaultProps={youtubeIntroDefaults}
calculateMetadata={youtubeIntroMetadata}
width={1920}
height={1080}
fps={30}
durationInFrames={1}
/>Render
npx remotion render YoutubeIntro # 16:9
npx remotion render YoutubeIntro --width=1080 --height=1920 # 9:16Props
PropTypeDescription
channel*string
title*string
theme"daylight" | "midnight" | "mono" | "ledger" | "afterglow" | "chromewave" | "neon" | "paper" | "sunset"Theme preset. Inherits the surrounding `ThemeProvider` when omitted.
brand{ accent?: string; logo?: string; font?: string; }
sfxbooleanPlays a soft whoosh as each scene starts.
musicstringBackground music file, looped under everything at 25% volume.
logostringChannel logo image. Falls back to `brand.logo`, then to the channel name alone.
Built from
Use
- The first seconds of a YouTube video or a series episode
Avoid
- End cards. Use
youtube-outro
Make it with an agent
With the reelcn agent skill installed, ask for the video in plain words, such as "make a launch video for Relay with reelcn". The skill picks a template, sets its props, reviews a contact sheet and renders.
Guides
Components take their colors from a theme, their timing from motion props and their layout from the canvas.
Source
registry/items/youtube-intro.tsx
/**
* @title YouTube Intro
* @category templates
* @description Channel opener: the channel mark, then the video's title, joined by an accent sweep.
* @duration data-driven
* @use The first seconds of a YouTube video or a series episode
* @avoid End cards. Use `youtube-outro`
* @tags youtube, intro, opener, channel, template
* @example
* <Composition
* id="YoutubeIntro"
* component={YoutubeIntro}
* schema={youtubeIntroSchema}
* defaultProps={youtubeIntroDefaults}
* calculateMetadata={youtubeIntroMetadata}
* width={1920}
* height={1080}
* fps={30}
* durationInFrames={1}
* />
*/
import { z } from "zod";
import type { Story } from "./story";
import { Storyboard, templateMetadata, templateSchema, templateStory } from "./storyboard";
export const youtubeIntroSchema = templateSchema.extend({
channel: z.string(),
title: z.string(),
/** Channel logo image. Falls back to `brand.logo`, then to the channel name alone. */
logo: z.string().optional(),
});
export type YoutubeIntroProps = z.infer<typeof youtubeIntroSchema>;
export const youtubeIntroDefaults: YoutubeIntroProps = {
channel: "Northwind Labs",
title: "Building a render farm in an afternoon",
};
export function youtubeIntroStory(props: YoutubeIntroProps): Story {
return templateStory(
props,
[
{ type: "logo", text: props.channel, src: props.logo, background: "gradient-mesh", duration: 2 },
{ type: "title", kicker: props.channel, title: props.title, background: "gradient-mesh" },
],
"brand-sweep",
);
}
export function YoutubeIntro(props: YoutubeIntroProps) {
return <Storyboard story={youtubeIntroStory(props)} />;
}
export const youtubeIntroMetadata = templateMetadata(youtubeIntroStory);