{
  "name": "podcast-clip",
  "type": "registry:block",
  "description": "Podcast clip composition with audio visuals and captions",
  "dependencies": [
    "remotion",
    "@remotion/transitions",
    "@remotion/media-utils",
    "@remotion/captions"
  ],
  "registryDependencies": [
    "audio-pulse",
    "waveform-line",
    "audiogram-scene",
    "auto-fit-title",
    "caption-scene",
    "end-card",
    "transition-fade",
    "fade-in",
    "layout",
    "motion-tokens"
  ],
  "composition": {
    "id": "PodcastClip",
    "component": "PodcastClip",
    "durationInFrames": 366,
    "fps": 30,
    "width": 1080,
    "height": 1920,
    "importPath": "@/compositions/podcast-clip/index"
  },
  "files": [
    {
      "path": "registry/bases/default/compositions/podcast-clip/index.tsx",
      "type": "registry:block",
      "content": "import type { Caption } from \"@remotion/captions\";\nimport { loadFont } from \"@remotion/google-fonts/Inter\";\nimport {\n  AbsoluteFill,\n  useCurrentFrame,\n  useVideoConfig,\n} from \"remotion\";\nimport { TransitionSeries } from \"@remotion/transitions\";\nimport { transitionFade } from \"@/remotion/primitives/transition-fade\";\nimport { AudioPulse } from \"@/remotion/primitives/audio-pulse\";\nimport { FadeIn } from \"@/remotion/primitives/fade-in\";\nimport { WaveformLine } from \"@/remotion/primitives/waveform-line\";\nimport { getSafeAreaPadding, scaleFont } from \"@/remotion/lib/layout\";\nimport { DURATION } from \"@/remotion/lib/motion-tokens\";\nimport { CaptionScene } from \"@/remotion/scenes/caption-scene\";\nimport { EndCard } from \"@/remotion/scenes/end-card\";\n\nconst { fontFamily } = loadFont(\"normal\", {\n  weights: [\"400\", \"700\", \"800\"],\n  subsets: [\"latin\"],\n});\n\nconst COLORS = {\n  bg: \"#080810\",\n  introBg: \"#0c0c14\",\n  accent: \"#e8b86d\",\n  accentSoft: \"#f5d08a\",\n  studioBg: \"#0a1014\",\n  studioGlow: \"rgba(232,184,109,0.14)\",\n  waveform: \"#f59e0b\",\n  quoteBg: \"#080810\",\n  endBg: \"#080810\",\n  endAccent: \"#2dd4bf\",\n  muted: \"#71717a\",\n} as const;\n\nconst fade = transitionFade({ durationInFrames: DURATION.fast });\n\n/** Matches the caption slot's own `TransitionSeries.Sequence` below. */\nconst CAPTION_SLOT_DURATION = 90;\n\nexport type PodcastClipProps = {\n  audioSrc: string;\n  captions: Caption[];\n  title?: string;\n  subtitle?: string;\n  showName?: string;\n  ctaTitle?: string;\n  ctaLabel?: string;\n};\n\nconst PodcastIntro: React.FC<{\n  title: string;\n  subtitle: string;\n  audioSrc: string;\n}> = ({ title, subtitle, audioSrc }) => {\n  const { width, height } = useVideoConfig();\n  const safeArea = getSafeAreaPadding({ width, height });\n  const pulseSize = scaleFont(280, width);\n\n  return (\n    <AbsoluteFill\n      style={{\n        backgroundColor: COLORS.introBg,\n        backgroundImage: `radial-gradient(ellipse 80% 60% at 50% 30%, ${COLORS.studioGlow}, transparent)`,\n        ...safeArea,\n        fontFamily,\n        display: \"flex\",\n        flexDirection: \"column\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        gap: scaleFont(36, width),\n      }}\n    >\n      <FadeIn durationInFrames={DURATION.fast}>\n        <AudioPulse src={audioSrc} size={pulseSize} color={COLORS.accent} ringCount={4} />\n      </FadeIn>\n      <FadeIn delayInFrames={DURATION.fast} durationInFrames={DURATION.fast}>\n        <div style={{ textAlign: \"center\", maxWidth: width * 0.72 }}>\n          <p\n            style={{\n              margin: 0,\n              color: COLORS.accentSoft,\n              fontSize: scaleFont(28, width),\n              fontWeight: 700,\n            }}\n          >\n            Podcast clip\n          </p>\n          <h1\n            style={{\n              margin: `${scaleFont(16, width)}px 0 0`,\n              color: \"#fafafa\",\n              fontSize: scaleFont(72, width),\n              fontWeight: 800,\n              lineHeight: 1.05,\n              letterSpacing: \"-0.02em\",\n            }}\n          >\n            {title}\n          </h1>\n          <p\n            style={{\n              margin: `${scaleFont(18, width)}px 0 0`,\n              color: COLORS.muted,\n              fontSize: scaleFont(34, width),\n              lineHeight: 1.35,\n            }}\n          >\n            {subtitle}\n          </p>\n        </div>\n      </FadeIn>\n    </AbsoluteFill>\n  );\n};\n\nconst PodcastStudio: React.FC<{\n  audioSrc: string;\n  showName: string;\n  episodeTitle: string;\n}> = ({ audioSrc, showName, episodeTitle }) => {\n  const frame = useCurrentFrame();\n  const { width, height } = useVideoConfig();\n  const safeArea = getSafeAreaPadding({ width, height });\n  const pulseSize = scaleFont(200, width);\n  const breathe = 1 + Math.sin(frame / 14) * 0.04;\n\n  return (\n    <AbsoluteFill\n      style={{\n        backgroundColor: COLORS.studioBg,\n        backgroundImage: `radial-gradient(circle at 50% 38%, ${COLORS.studioGlow}, transparent 55%)`,\n        ...safeArea,\n        fontFamily,\n        display: \"flex\",\n        flexDirection: \"column\",\n        justifyContent: \"space-between\",\n      }}\n    >\n      <FadeIn durationInFrames={DURATION.fast}>\n        <div style={{ paddingTop: scaleFont(12, width) }}>\n          <p\n            style={{\n              margin: 0,\n              color: COLORS.accentSoft,\n              fontSize: scaleFont(26, width),\n              fontWeight: 700,\n            }}\n          >\n            {showName}\n          </p>\n          <h2\n            style={{\n              margin: `${scaleFont(10, width)}px 0 0`,\n              color: \"#fafafa\",\n              fontSize: scaleFont(52, width),\n              fontWeight: 800,\n              lineHeight: 1.08,\n              maxWidth: width * 0.78,\n            }}\n          >\n            {episodeTitle}\n          </h2>\n        </div>\n      </FadeIn>\n\n      <div\n        style={{\n          flex: 1,\n          display: \"flex\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n          transform: `scale(${breathe})`,\n        }}\n      >\n        <AudioPulse src={audioSrc} size={pulseSize} color={COLORS.accent} ringCount={3} />\n      </div>\n\n      <div style={{ paddingBottom: scaleFont(8, width) }}>\n        <WaveformLine\n          src={audioSrc}\n          width={width - safeArea.paddingLeft - safeArea.paddingRight}\n          height={scaleFont(120, height)}\n          strokeColor={COLORS.waveform}\n          strokeWidth={3}\n          mirror\n        />\n      </div>\n    </AbsoluteFill>\n  );\n};\n\nexport const PodcastClip: React.FC<PodcastClipProps> = ({\n  audioSrc,\n  captions,\n  title = \"The moment worth sharing\",\n  subtitle = \"Pull one quote into a vertical clip\",\n  showName = \"Studio Sessions\",\n  ctaTitle,\n  ctaLabel,\n}) => (\n  <AbsoluteFill style={{ backgroundColor: COLORS.bg }}>\n    <TransitionSeries>\n      <TransitionSeries.Sequence durationInFrames={70}>\n        <PodcastIntro title={title} subtitle={subtitle} audioSrc={audioSrc} />\n      </TransitionSeries.Sequence>\n      <TransitionSeries.Transition {...fade} />\n      <TransitionSeries.Sequence durationInFrames={110}>\n        <PodcastStudio\n          audioSrc={audioSrc}\n          showName={showName}\n          episodeTitle={title}\n        />\n      </TransitionSeries.Sequence>\n      <TransitionSeries.Transition {...fade} />\n      <TransitionSeries.Sequence durationInFrames={CAPTION_SLOT_DURATION}>\n        <CaptionScene\n          captions={captions}\n          placement=\"center\"\n          backgroundColor={COLORS.quoteBg}\n          activeColor={COLORS.accent}\n          mode=\"karaoke-scale\"\n          durationInFrames={CAPTION_SLOT_DURATION}\n        />\n      </TransitionSeries.Sequence>\n      <TransitionSeries.Transition {...fade} />\n      <TransitionSeries.Sequence durationInFrames={60}>\n        <EndCard\n          title={ctaTitle ?? showName}\n          cta={ctaLabel}\n          backgroundColor={COLORS.endBg}\n          accentColor={COLORS.endAccent}\n        />\n      </TransitionSeries.Sequence>\n    </TransitionSeries>\n  </AbsoluteFill>\n);\n"
    }
  ],
  "atlas": {
    "lane": "reels",
    "drive": "media",
    "tier": "advanced"
  }
}