Caption Pill Karaoke
framecn/caption-pill-karaokeFreeComponent
Karaoke-style captions where each word sits inside a pill-shaped background.
Install it
npx shadcn@latest add https://framecn.dev/r/caption-pill-karaoke.jsonSource
1"use client";23import { Timegroup } from "@editframe/react";4import type { CSSProperties } from "react";56export interface CaptionWord {7 text: string;8 start: number;9 end: number;10}1112export interface CaptionPillKaraokeProps {13 words?: CaptionWord[];14 wordsPerSegment?: number;15 activeColor?: string;16 dimColor?: string;17 pillColor?: string;18 fontSize?: number;19 fontWeight?: number | string;20 background?: string;21 speed?: number;22 fps?: number;23 durationInFrames?: number;24 width?: number;25 height?: number;26 className?: string;27}2829const DEFAULT_WORDS: CaptionWord[] = [30 { end: 0.35, start: 0, text: "Every" },31 { end: 0.65, start: 0.35, text: "great" },32 { end: 1, start: 0.65, text: "video" },33 { end: 1.45, start: 1.1, text: "starts" },34 { end: 1.65, start: 1.45, text: "with" },35 { end: 1.8, start: 1.65, text: "a" },36 { end: 2.15, start: 1.8, text: "single" },37 { end: 2.7, start: 2.15, text: "frame." },38 { end: 3.2, start: 3, text: "No" },39 { end: 3.9, start: 3.2, text: "timelines." },40 { end: 4.2, start: 4, text: "No" },41 { end: 4.5, start: 4.2, text: "drag" },42 { end: 4.65, start: 4.5, text: "and" },43 { end: 5.1, start: 4.65, text: "drop." },44 { end: 5.55, start: 5.3, text: "Just" },45 { end: 6, start: 5.55, text: "code." },46];4748export const CaptionPillKaraoke = ({49 words = DEFAULT_WORDS,50 wordsPerSegment = 6,51 activeColor = "#1a1a1a",52 dimColor = "#a6a6a6",53 pillColor = "#e7e5e7",54 fontSize = 60,55 fontWeight = 700,56 background = "#0a0a0a",57 speed = 1,58 fps = 30,59 durationInFrames = 180,60 width = 1280,61 height = 720,62 className,63}: CaptionPillKaraokeProps) => {64 const safeSpeed = Math.max(0.01, speed);65 const durationMs = (durationInFrames / fps) * 1000;6667 const segments = [];68 for (let i = 0; i < words.length; i += wordsPerSegment) {69 const segWords = words.slice(i, i + wordsPerSegment);70 segments.push({71 endMs: ((segWords.at(-1)?.end ?? 0) * 1000) / safeSpeed + 180,72 startMs: (segWords[0].start * 1000) / safeSpeed,73 words: segWords,74 });75 }7677 const containerStyle: CSSProperties = {78 background,79 height,80 overflow: "hidden",81 position: "relative",82 width,83 };8485 return (86 <Timegroup87 className={className}88 duration={`${durationMs}ms`}89 mode="fixed"90 style={containerStyle}91 >92 <>93 <style>{`94 @keyframes framecn-pk-seg-in {95 from { opacity: 0; transform: translateY(10px) scale(0.97); }96// … truncated
What it pulls in
npm packages
Files it writes
More from framecn
All 101 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| AI Generate Overlayai-generate-overlay | framecn | Components | Free | 1 dep | |
| AI Generation Canvasai-generation-canvas | framecn | Components | Free | 1 dep | |
| Animated Bar Chartanimated-bar-chart | framecn | Components | Free | 1 dep | |
| Animated Line Chartanimated-line-chart | framecn | Components | Free | 1 dep | |
| Backdropbackdrop | framecn | Components | Free | 1 dep | |
| Blur Out Upblur-out-up | framecn | Components | Free | 1 dep | |
| Blur Revealblur-reveal | framecn | Components | Free | 1 dep | |
| Bounding Box Selectorbounding-box-selector | framecn | Components | Free | 1 dep |
