Skip to main content

clipsketch-ai-video-storyboard

Turn video moments into AI-generated hand-drawn storyboards with Gemini-powered frame analysis and social media content generation

الانتقال إلى التثبيت

معلومات المصدر

المستودع
reason-machines/devtools-skills
آخر نشاط في المصدر
١٧ مايو ٢٠٢٦ في ٢٠:٥٠
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٤
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
clipsketch-ai-video-storyboard
description
Turn video moments into AI-generated hand-drawn storyboards with Gemini-powered frame analysis and social media content generation
triggers
["how do I use ClipSketch AI to create video storyboards","extract and tag frames from Bilibili or Xiaohongshu videos","generate hand-drawn storyboards from video frames","create social media content from video moments","setup ClipSketch AI with Gemini API","export tagged video frames as storyboard","use AI to generate video cover images","batch process video frames with Gemini"]
# ClipSketch AI Video Storyboard Skill > Skill by [ara.so](https://ara.so) — Devtools Skills collection. ClipSketch AI is a TypeScript/React application that transforms video moments into hand-drawn storyboards using Google Gemini's multimodal AI. It supports importing videos from Bilibili and Xiaohongshu (Little Red Book), frame-precise tagging, and automatic generation of storyboards, social media copy, and cover images. ## Installation ```bash git clone https://github.com/RanFeng/clipsketch-ai.git cd clipsketch-ai npm install ``` ## Configuration Create `.env.local` in project root: ```env GEMINI_API_KEY=your_google_gemini_api_key_here ``` Required API access: - `gemini-3-pro-image-preview` (for storyboard generation) - `gemini-3-pro-preview` (for text/copy generation) ## Running the Application ```bash # Development mode npm run dev # Production build npm run build npm start # Docker deployment docker run -d --restart=always --name clipsketch-ai -p 3000:3000 earisty/clipsketch-ai:latest ``` Access at `http://localhost:3000` ## Core Workflow ### 1. Video Import **Supported Platforms:** - Bilibili (supports short links and mixed text) - Xiaohongshu (Little Red Book) **URL Pattern Recognition:** ```typescript // Bilibili patterns const bilibiliPatterns = [ /bilibili\.com\/video\/(BV\w+)/, /b23\.tv\/\w+/ ]; // Xiaohongshu patterns const xhsPatterns = [ /xhslink\.com\/\w+/, /xiaohongshu\.com\/.*\/(\w+)/ ]; ``` **Import Example:** ```typescript // User pastes share link (can include promotional text) const shareText = "超好看的视频!https://b23.tv/abc123 快来看看"; // App extracts and resolves to video URL ``` ### 2. Frame Tagging System **Keyboard Controls:** - `Space`: Play/Pause - `←/→`: Frame-by-frame or smart step navigation - `T`: Tag current frame (millisecond precision) **Tag Data Structure:** ```typescript interface VideoTag { id: string; timestamp: number; // milliseconds thumbnailDataUrl: string; // base64 canvas capture videoUrl: string; } // Tagging implementation pattern const captureFrame = (videoElement: HTMLVideoElement, currentTime: number): VideoTag => { const canvas = document.createElement('canvas'); canvas.width = videoElement.videoWidth; canvas.height = videoElement.videoHeight; const ctx = canvas.getContext('2d'); ctx?.drawImage(videoElement, 0, 0); return { id: `tag-${Date.now()}`, timestamp: currentTime * 1000, thumbnailDataUrl: canvas.toDataURL('image/jpeg', 0.9), videoUrl: videoElement.src }; }; ``` ### 3. AI Storyboard Generation **Multi-Step Pipeline:** #### Step 1: Creative Analysis ```typescript import { GoogleGenAI } from '@google/genai'; const analyzeFrames = async (frames: VideoTag[], apiKey: string) => { const genAI = new GoogleGenAI(apiKey); const model = genAI.getGenerativeModel({ model: 'gemini-3-pro-preview' }); const prompt = ` Analyze these video frames and extract: 1. Main narrative steps 2. Key visual elements 3. Character actions 4. Scene transitions Frames: ${frames.length} `; const imageParts = frames.map(frame => ({ inlineData: { data: frame.thumbnailDataUrl.split(',')[1], // Remove data:image/jpeg;base64, mimeType: 'image/jpeg' } })); const result = await model.generateContent([prompt, ...imageParts]); return result.response.text(); }; ``` #### Step 2: Storyboard Image Generation ```typescript const generateStoryboard = async ( frames: VideoTag[], analysis: string, apiKey: string, customCharacter?: string // Optional character image URL ) => { const genAI = new GoogleGenAI(apiKey); const model = genAI.getGenerativeModel({ model: 'gemini-3-pro-image-preview' }); const prompt = ` Create a cute hand-drawn style storyboard combining these ${frames.length} frames. Style requirements: - Cute, friendly illustration style - Coherent visual narrative - Warm color palette - Clear panel separation Narrative context: ${analysis} ${customCharacter ? `Integrate this character: ${customCharacter}` : ''} `; const imageParts = frames.map(frame => ({ inlineData: { data: frame.thumbnailDataUrl.split(',')[1], mimeType: 'image/jpeg' } })); if (customCharacter) { imageParts.push({ inlineData: { data: customCharacter.split(',')[1], mimeType: 'image/jpeg' } }); } const result = await model.generateContent([prompt, ...imageParts]); return result.response.text(); // Returns image data or URL }; ``` #### Step 3: Panel Refinement (Batch Mode) ```typescript const refinePanels = async ( storyboardImage: string, panelCount: number, apiKey: string, useBatchAPI: boolean = false ) => { const genAI = new GoogleGenAI(apiKey); const model = genAI.getGenerativeModel({ model: 'gemini-3-pro-image-preview' }); if (useBatchAPI) { // Cost-efficient batch processing const batchPromises = Array.from({ length: panelCount }, (_, i) => ({ prompt: `Enhance panel ${i + 1} from this storyboard in high resolution`, image: storyboardImage })); // Process in batches to save API costs const results = await model.batchGenerate(batchPromises); return results; } else { // Individual requests for immediate results const refinedPanels = []; for (let i = 0; i < panelCount; i++) { const result = await model.generateContent([ `Enhance and upscale panel ${i + 1} from this storyboard`, { inlineData: { data: storyboardImage.split(',')[1], mimeType: 'image/jpeg' } } ]); refinedPanels.push(result.response.text()); } return refinedPanels; } }; ``` ### 4. Social Media Copy Generation ```typescript const generateSocialCopy = async ( storyboardImage: string, videoContext: string, apiKey: string ) => { const genAI = new GoogleGenAI(apiKey); const model = genAI.getGenerativeModel({ model: 'gemini-3-pro-preview' }); const prompt = ` Generate 3 different styles of social media copy (for Xiaohongshu/Little Red Book): 1. Emotional Storytelling Style (200-300 chars) - Personal, relatable narrative - Emotional hooks - Conversational tone 2. Tutorial/Guide Style (150-250 chars) - Step-by-step breakdown - Practical tips - Clear value proposition 3. Short & Punchy Style (80-120 chars) - Attention-grabbing opener - Concise key message - Call-to-action Video context: ${videoContext} Include relevant emojis and hashtags. `; const result = await model.generateContent([ prompt, { inlineData: { data: storyboardImage.split(',')[1], mimeType: 'image/jpeg' } } ]); return parseCopyVariants(result.response.text()); }; interface CopyVariant { style: 'emotional' | 'tutorial' | 'punchy'; text: string; hashtags: string[]; } const parseCopyVariants = (aiResponse: string): CopyVariant[] => { // Parse AI response into structured copy variants // Implementation depends on AI output format return [ { style: 'emotional', text: '...', hashtags: ['#story', '#life'] }, { style: 'tutorial', text: '...', hashtags: ['#howto', '#tips'] }, { style: 'punchy', text: '...', hashtags: ['#viral', '#trending'] } ]; }; ``` ### 5. Cover Image Generation ```typescript const generateCoverImage = async ( selectedCopy: string, storyboardImage: string, originalFrames: VideoTag[], apiKey: string ) => { const genAI = new GoogleGenAI(apiKey); const model = genAI.getGenerativeModel({ model: 'gemini-3-pro-image-preview' }); const prompt = ` Create a vertical video cover (9:16 aspect ratio) that: - Incorporates key visual from the storyboard - Highlights this copy: "${selectedCopy}" - Optimized for social media thumbnail - Eye-catching, high-contrast design - Maintains hand-drawn aesthetic Cover should work as standalone promotion image. `; const imageParts = [ { inlineData: { data: storyboardImage.split(',')[1], mimeType: 'image/jpeg' } }, ...originalFrames.slice(0, 3).map(frame => ({ inlineData: { data: frame.thumbnailDataUrl.split(',')[1], mimeType: 'image/jpeg' } })) ]; const result = await model.generateContent([prompt, ...imageParts]); return result.response.text(); }; ``` ## Data Export ### Export Tagged Frames as ZIP ```typescript import JSZip from 'jszip'; const exportTagsAsZip = async (tags: VideoTag[]) => { const zip = new JSZip(); // Add timestamp index file const timestampList = tags.map((tag, idx) => `Frame ${idx + 1}: ${formatTimestamp(tag.timestamp)}` ).join('\n'); zip.file('timestamps.txt', timestampList); // Add frame images for (let i = 0; i < tags.length; i++) { const imageData = tags[i].thumbnailDataUrl.split(',')[1]; zip.file(`frame_${i + 1}.jpg`, imageData, { base64: true }); } const blob = await zip.generateAsync({ type: 'blob' }); // Trigger download const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `video-tags-${Date.now()}.zip`; a.click(); URL.revokeObjectURL(url); }; const formatTimestamp = (ms: number): string => { const totalSeconds = Math.floor(ms / 1000); const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; const milliseconds = ms % 1000; return `${minutes}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(3, '0')}`; }; ``` ### Export Timeline as TXT ```typescript const exportTimeline = (tags: VideoTag[]) => { const content = tags.map((tag, idx) => `[${formatTimestamp(tag.timestamp)}] Frame ${idx + 1}` ).join('\n'); const blob = new Blob([content], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `timeline-${Date.now()}.txt`; a.click(); URL.revokeObjectURL(url); }; ``` ## Responsive Design Patterns ```typescript // Detect mobile/tablet and adjust layout const useResponsiveLayout = () => { const [isMobile, setIsMobile] = useState(false); useEffect(() => { const checkMobile = () => { setIsMobile(window.innerWidth < 768); }; checkMobile(); window.addEventListener('resize', checkMobile); return () => window.removeEventListener('resize', checkMobile); }, []); return isMobile; }; // Layout component const VideoWorkspace: React.FC = () => { const isMobile = useResponsiveLayout(); return ( <div className={isMobile ? 'flex-col' : 'flex-row'}>
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub