mcpField
Y
youtube-intro-outro

youtube-intro-outro

github.com/iart-ai创意与媒体6797 次安装18 周前更新
代码仓库

关于 youtube-intro-outro

youtube-intro-outro 是用于 Remotion 的 skill,可制作可复用的品牌化 YouTube 片头和片尾视频。它帮助创作者制作符合平台时长和布局限制、由帧驱动的动画。

主要功能

  1. 01品牌化片头与片尾作品
  2. 02Logo 动效与音频冲击帧同步
  3. 03符合结束画面安全区域的布局
  4. 04基于 brand 属性的可复用模板
  5. 05静帧与 MP4 验证

适用场景

  1. 01制作简短的频道 Logo 片头
  2. 02围绕 YouTube 结束画面元素设计片尾
  3. 03为多个频道渲染风格一致的片头片尾

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/iart-ai/youtube-video-skills --skill youtube-intro-outro

安装后在 Claude Code 中输入/youtube-intro-outro确认已加载。

附带文件README.mdreferences/intro-outro.md

详细介绍

YouTube 片头与片尾

为频道的每个视频打造前后呼应的两段动态效果:3-5s 的品牌片头(用 Logo 动效告诉观众“这是我的频道”),以及片尾,最后约 20s 用于承载 YouTube 可点击的结束画面元素(订阅按钮 + 下一个视频)。两者都必须遵守平台的硬性限制——片头时长会影响观众留存率;片尾布局必须避开 YouTube 叠加的界面元素——并且都应做成可复用模板,只需更换品牌即可。

适用场景

  • 频道片头 / 开场短片 / Logo 动效(在内容开始前,用 3-5s 展示频道标识)。
  • 片尾 / 结束画面 / 片尾卡片(最后约 20s,包含订阅按钮 + 下一个视频卡片)。
  • 可复用的品牌模板:替换名称、Logo、颜色、音效,并重新导出。

两条硬性规则(平台要求,非个人偏好)

  1. 片头控制在 3-5s,Logo 展示 1-2s。 时长超过 5s 会导致可量化的观众流失,进而影响视频在算法中的表现。片头用于确认频道身份,然后迅速让位给内容。
  2. 片尾必须包含 ≥20s 的静止、安静布局,且视频总时长 ≥25s。 YouTube 只允许在最后 5-20s 显示结束画面元素,而且视频必须至少 25s。设计片尾底板时要考虑这些元素的位置——不要在它们下方放置自己的内容。

片头:Logo 动效

Logo 动效在约 3.5s 内分为三个节拍:蓄势(通过动态营造张力)、冲击(Logo 随音效重击瞬间显现为完整形态)和收稳(轻微过冲后平稳停下)。品牌标志必须恰好落在声音的冲击帧上,而不是接近该帧。

节拍时间范围作用
蓄势0-0.8s呼啸 / 渐强;Logo 尚不可辨认
冲击~0.8sLogo 随音效重击瞬间完整显现 + 白色闪光
收稳0.8-1.2s过冲后平稳停下;标语渐显
停留1.2-3.5s品牌清晰可见,然后切入内容
import {useCurrentFrame, useVideoConfig, spring, interpolate, Img, Audio, staticFile} from "remotion";

export const LogoSting = ({brand}) => {
  const frame = useCurrentFrame();
  const {fps} = useVideoConfig();
  const IMPACT = Math.round(0.8 * fps);            // logo lands here, on the sting hit

  // overshoot scale: springs up past 1, settles to 1 (the "snap")
  const scale = spring({frame: frame - IMPACT, fps, config: {damping: 9, mass: 0.5}, from: 1.18, to: 1});
  const logoOpacity = frame < IMPACT ? 0 : 1;
  const flash = interpolate(frame - IMPACT, [0, 6], [0.9, 0], {extrapolateLeft: "clamp", extrapolateRight: "clamp"});

  return (
    <div style={{flex: 1, background: brand.bg, display: "flex", alignItems: "center", justifyContent: "center"}}>
      <Audio src={staticFile(brand.sting)} />        {/* impact of this file must sit at 0.8s */}
      <Img src={staticFile(brand.logo)} style={{width: 420, opacity: logoOpacity, transform: `scale(${scale})`}} />
      <div style={{position: "absolute", inset: 0, background: "#fff", opacity: flash}} />
    </div>
  );
};

spring 从 1.18→1 的过冲本身就是那一下显现;白色 flash 在 6 帧内淡出,强化冲击感。调整音频,让音量最大的瞬态落在第 IMPACT 帧。完整构图、CSS/GSAP 变体,以及如何在任何音效中找到冲击帧,请参阅 references/intro-outro.md。

片尾:遵循 YouTube 元素区域限制的结束画面布局

大多数片尾的问题都出在这里:创作者把 Logo 或文字放在 YouTube 将要显示订阅按钮的位置。将画面视为三等分。YouTube 的可点击元素位于右侧三分之二;自己的品牌标识、频道名称和任何人像摄像头画面都应放在左侧三分之一。避开角落和底部——移动端进度条和界面会覆盖这些区域。

元素原生尺寸预留位置(1920×1080)
订阅 / 频道圆形头像294×294右侧、垂直方向大致居中,超出画面边缘
下一个视频卡片(缩略图)615×345右上方或右侧中央
播放列表 / 链接卡片294×294与视频卡片并排
自有品牌元素(Logo、名称)—仅限左侧三分之一,靠上对齐

在片尾底板上绘制占位框,标出动态元素将出现的位置,以便围绕它们进行构图;然后在 YouTube Studio 中将真实元素覆盖上去(使用其网格和“吸附到元素”功能)。

import {useCurrentFrame, interpolate, Img, staticFile} from "remotion";

// 1920×1080 outro plate. Left third = brand; right two-thirds = YouTube element zones (drawn as guides).
export const EndScreen = ({brand}) => {
  const frame = useCurrentFrame();
  const fade = interpolate(frame, [0, 18], [0, 1], {extrapolateRight: "clamp"});
  const zone = {position: "absolute", border: "2px dashed rgba(255,255,255,.25)", borderRadius: 12};

  return (
    <div style={{flex: 1, background: brand.bg, opacity: fade}}>
      {/* LEFT THIRD: your brand — safe from YouTube's overlays */}
      <div style={{position: "absolute", left: 80, top: 90, width: 560}}>
        <Img src={staticFile(brand.logo)} style={{width: 220}} />
        <div style={{color: brand.fg, font: "700 56px Inter", marginTop: 24}}>{brand.name}</div>
        <div style={{color: brand.accent, font: "500 30px Inter", marginTop: 8}}>Subscribe for more →</div>
      </div>

      {/* RIGHT TWO-THIRDS: leave these empty; YouTube draws the live elements here */}
      <div style={{...zone, width: 615, height: 345, right: 90, top: 110}} />        {/* next-video card */}
      <div style={{...zone, width: 294, height: 294, right: 250, bottom: 150, borderRadius: 999}} /> {/* subscribe circle */}
    </div>
  );
};

仅在预览版本中显示虚线参考线;最终渲染时移除参考线,让底板保持干净,并有意让右侧保持安静。片尾可以静止展示品牌,也可以在完整的 20s 内循环播放细微动效,但不能让任何内容与卡片争夺注意力。

可复用的品牌模板

两种构图都读取同一个 brand 属性——不硬编码名称、颜色、Logo 或音频。替换对象(或传入 --props),即可通过同一套代码为不同频道重新设计片头和片尾。

// brand.json — the only thing that changes per channel
{ "name": "PixelForge", "logo": "logo.png", "sting": "sting.mp3",
  "bg": "#0B0B14", "fg": "#FFFFFF", "accent": "#7C5CFF" }
# render intro + outro for every brand file in /brands
for f in brands/*.json; do
  name=$(basename "$f" .json)
  npx remotion render Intro  "out/${name}-intro.mp4"  --props="$f"
  npx remotion render Outro  "out/${name}-outro.mp4"  --props="$f"
done

在模板中固定字体、布局和时长,让 20 个频道在结构上保持一致,只呈现不同的品牌标识。

输出检查清单

  • 片头 ≤5 秒;约 2 秒时 logo 清晰可读;logo 出现时刻与音频冲击帧精确对齐。
  • 片尾保持布局 ≥20 秒;视频总时长 ≥25 秒,以便允许添加结束画面元素。
  • 片尾右侧三分之二保持留白,供 YouTube 放置元素;自有品牌内容仅放在左侧三分之一。
  • 距离任一边缘约 10% 范围内以及底部 UI 区域内都不要放置重要内容。
  • 规划的结束画面元素最多 4 个(1 个视频 + 订阅是点击率最高的布局)。
  • 所有文字/颜色/logo/音频均来自 brand prop——一个模板,适用于多个频道。

交付与验证(渲染静帧 → MP4)

打包的辅助脚本(scripts/):使用 scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png 拼接静帧,然后使用 scripts/probe-mp4.sh out.mp4 [WxH] [fps] 检查编码结果。参见 scripts/README.md。

这是重型工作:交付物是实际的 MP4 片段(片头 + 片尾)。编码前,先以静帧形式验证 logo 出现时刻和结束画面的安全区域——如果音效落后或提前一帧,或 logo 被盖在 YouTube 绘制订阅按钮的位置,要等完整渲染后才发现,代价会很高。

输出要求:

  • 一个 Remotion 项目,注册了两个合成(<Composition> + zod schema + defaultProps),所有动画均由帧驱动——不使用 Date.now() / Math.random() / 定时器。
  • 将音效冲击预先烘焙到帧中(IMPACT = Math.round(0.8 * fps)),不在运行时检测;音频通过 <Audio src={staticFile()}> 添加,确保导出文件包含音效。
  • 交付物 = 渲染后的 out/*-intro.mp4 + out/*-outro.mp4 以及项目,方便用户通过 brand prop 更换品牌样式并重新导出。

验证流程——渲染静帧 → 检查 → 编码。

# 1. Frame-exact stills WITH SHIPPED brand props (not just defaultProps).
#    Intro: windup / impact / settle.  Outro: fade-in / held end-screen plate.
npx remotion still Intro out/i-windup.png --frame=12 --props=./brand.json
npx remotion still Intro out/i-impact.png --frame=24 --props=./brand.json   # = round(0.8*fps)
npx remotion still Intro out/i-settle.png --frame=40 --props=./brand.json
npx remotion still Outro out/o-end.png    --frame=N  --props=./brand.json

# 2. Inspect each PNG — fidelity (logo readable + captions/tagline correct; on the impact
#    frame the logo is full-scale and the flash fires) AND artifacts (end-screen elements
#    inside YouTube safe zones — branding in the LEFT third only, right two-thirds quiet,
#    nothing within ~10% of any edge or in the bottom UI band; no off-canvas text/overflow).

# 3. Only once the stills check out, encode both plates:
npx remotion render Intro out/intro.mp4 --props=./brand.json
npx remotion render Outro out/outro.mp4 --props=./brand.json
  • 明确验证冲击帧(logo 突然放大至完整尺寸,白色闪光逐渐消退)——音效必须与该帧同步,而非出现在附近。
  • 最终渲染时移除虚线结束画面参考线;确认右侧三分之二有意留白。
  • README 演示:npx remotion render Intro out/demo.gif --codec=gif。

完成前:

  1. npx remotion still 在片头的蓄势/冲击/稳定阶段以及片尾的保持画面均可正常渲染——无错误、无缺失的 logo/音效素材。
  2. 冲击帧上的 logo 为完整尺寸且清晰可读;片头 ≤5 秒,片尾保持 ≥20 秒(视频总时长 ≥25 秒)。
  3. 仅使用帧驱动——音效冲击预先烘焙到帧中;不使用 Date.now() / Math.random() / 定时器。
  4. 结束画面元素均位于 YouTube 安全区域内——品牌内容放在左侧三分之一,右侧三分之二留白;底部 UI 区域内或距离边缘约 10% 范围内均无内容。
  5. 两个 MP4 均已编码并混入音效,且可正常播放;所有文字/颜色/logo/音频均来自 brand prop;(可选)为 README 渲染 GIF。

参考文件

  • references/intro-outro.md — 片头和片尾的完整可运行 Remotion 合成、CSS/GSAP logo 音效变体、适用于 16:9 的精确结束画面坐标图及 1080×1920 的说明、查找音效冲击帧并使揭示效果与之同步的方法,以及包含批量渲染流程的 brand prop 架构。

评论

支持 Markdown