UNPKG

@snahrup/notion-hero-image-mcp

Version:

AI-powered animated hero banner generator for Notion pages. Integrates DALL-E 3, Google Veo 3, Cloudinary CDN, and Notion API.

116 lines (112 loc) 3.97 kB
import { VertexAI } from '@google-cloud/vertexai'; import { join } from 'path'; import { tmpdir } from 'os'; const vertexAI = new VertexAI({ project: process.env.GOOGLE_PROJECT, location: process.env.GOOGLE_REGION || 'us-central1', }); const definition = { name: 'generate_video', description: 'Animate a still image using Google Veo 3 with detailed animation script', inputSchema: { type: 'object', properties: { image_url: { type: 'string', description: 'URL of the still image to animate' }, title: { type: 'string', description: 'Title for the animation' }, scene_description: { type: 'string', description: 'Detailed scene description' }, animation_beats: { type: 'array', description: 'Timestamped animation sequences', items: { type: 'object', properties: { timeRange: { type: 'string' }, description: { type: 'string' } } } }, style_tags: { type: 'string', description: 'Style descriptors for the animation' }, duration: { type: 'number', description: 'Duration in seconds (max 8)', default: 8, maximum: 8 } }, required: ['image_url', 'title', 'scene_description'] } }; const formatVeoPrompt = (params) => { const { title, scene_description, animation_beats = [], style_tags = '', duration = 8 } = params; // Format animation beats with timestamps const beatsFormatted = animation_beats.map((beat) => `${beat.timeRange} ${beat.description}`).join('\n'); return ` TITLE: "${title}" REFERENCE_IMAGE: [provided] DURATION: ${duration} seconds, 30 fps, seamless loop ASPECT_RATIO: 16 × 9 (banner-safe center band 1280 × 480) AUDIO: none SCENE DESCRIPTION: ${scene_description} ANIMATION BEATS: ${beatsFormatted} STYLE TAGS: ${style_tags} NOTES: - First and last frames must be identical for seamless loop - Maintain consistent lighting and atmosphere - Use smooth ease curves for all transitions - Keep motion subtle and elegant for Notion banner use `; }; const handler = { 'tools/call': async (request) => { if (request.params.name !== 'generate_video') return null; const params = request.params.arguments; const veoPrompt = formatVeoPrompt(params); const generativeModel = vertexAI.getGenerativeModel({ model: 'veo-003', }); // Generate video using Veo 3 const result = await generativeModel.generateContent({ contents: [{ role: 'user', parts: [{ text: veoPrompt }, { inlineData: { mimeType: 'image/png', data: params.image_url // This would need proper base64 encoding in production } }] }] }); // In production, this would return the actual video URL from Vertex AI const videoPath = join(tmpdir(), `video-${Date.now()}.mp4`); return { content: [{ type: 'text', text: JSON.stringify({ mp4_url: `file://${videoPath}`, local_path: videoPath, duration: params.duration || 8, animation_script: veoPrompt }) }] }; } }; export default { definition, handler }; //# sourceMappingURL=generate-video.js.map