exports.generatePicturePrompt = (project = {}) => { const { title = '', lyrics: lyricsRaw, musicConfig = {}, coverStyle: coverStyleRaw = '', artistName: artistNameRaw = '', } = project || {} // --- 1. Nettoyage et Normalisation --- const sanitizeInline = (value = '') => { if (typeof value !== 'string') return '' return value .replace(/[\r\n]+/g, ' ') .replace(/[<>]/g, '') .trim() } const titleForPrompt = sanitizeInline(title) || 'Sans titre' const artistName = sanitizeInline(artistNameRaw) || sanitizeInline(project?.userName || '') const hasArtistName = artistName.length > 0 const { genres = [], tempo = '', mood = '', instruments = [] } = musicConfig || {} const userStyle = sanitizeInline(coverStyleRaw) // --- 2. Intelligence Visuelle (Mapping) --- // Détermination de l'énergie visuelle const isEnergetic = tempo && /\b(rapid|fast|vite|agité|upbeat|energ|dance|rock|metal)\b/i.test(String(tempo)) const isDark = mood && /\b(sombre|triste|dark|sad|mélancoli|nuit|night|eerie)\b/i.test(String(mood)) // Construction de la Palette & Lumière let visualAtmosphere = '' if (isDark) { visualAtmosphere = 'Atmosphere: Cinematic atmosphere, moody shadows, deep contrast. Palette: Midnight blue, obsidian, deep purple, metallic accents.' } else if (isEnergetic) { visualAtmosphere = 'Atmosphere: Dynamic atmosphere, high energy, vibrant saturation. Palette: Neon colors, electric blue, magenta, bright yellow, high contrast.' } else { visualAtmosphere = 'Atmosphere: Soft atmosphere, harmonious and ethereal. Palette: Pastel tones, warm gold, soft coral, balanced and elegant colors.' } // Définition du Style de Rendu (Si l'utilisateur est vague, on renforce) let renderingStyle = userStyle ? `Art Style: ${userStyle}` : 'Art Style: Digital Art, Mixed Media' if (userStyle.toLowerCase().includes('realist') || userStyle.toLowerCase().includes('photo')) { renderingStyle += ', 8k resolution, highly detailed texture, photorealistic, cinematic depth of field, raytracing.' } else if ( userStyle.toLowerCase().includes('illu') || userStyle.toLowerCase().includes('dessin') ) { renderingStyle += ', vector art, clean lines, professional illustration, flat design or detailed painting.' } else { // Style par défaut "Album Cover" qui marche bien renderingStyle += ', abstract surrealism, conceptual album art, high fidelity, masterpiece.' } // --- 3. Extraction de l'Inspiration (Lyrics) --- // On cherche le REFRAIN en priorité pour l'image, car c'est le cœur visuel const sections = Array.isArray(lyricsRaw) ? lyricsRaw : [] const chorus = sections.find((s) => s.type === 'refrain' || s.type === 'chorus') const verse = sections.find((s) => s.type === 'couplet' || s.type === 'verse') // On prend 2 lignes max du refrain, ou du premier couplet const visualHook = (chorus?.lyrics || verse?.lyrics || '') .split('\n') .filter((l) => l.length > 10) // On évite les lignes trop courtes .slice(0, 2) .join('. ') const imageryPrompt = visualHook ? `Visual Inspiration: An interpretation of these lyrics: "${visualHook}".` : "Visual Inspiration: Abstract visual representation of the song's mood." // --- 4. Construction du Prompt Final (Structure Optimisée Imagen 3) --- const promptParts = [ // Rôle 'Design a professional, high-quality music album cover.', // 1. Le Texte (Crucial pour Imagen 3 - Doit être au début ou très clair) `**Typography & Text:**`, `The song title "${titleForPrompt}" must be the CENTERPIECE. Write it in a distinct font that matches the mood.`, hasArtistName ? `The artist name "${artistName}" must appear smaller, elegant, and legible near the bottom or top.` : '', 'Ensure perfect spelling. The text should be integrated into the artwork (e.g., metallic texture, neon glow, or bold cut-out), not just pasted on top.', // 2. Le Visuel `**Visuals:**`, renderingStyle, imageryPrompt, `Subject: A central visual element that represents the song. ${isEnergetic ? 'Dynamic composition.' : 'Balanced, centered composition.'}`, // 3. L'Atmosphère (Context from music config) `**Mood & Color:**`, visualAtmosphere, genres.length > 0 ? `Musical Vibe Reference: ${genres.join(', ')}.` : '', // 4. Contraintes Négatives (Phrasées positivement pour l'IA) '**Constraints:**', 'Use a square 1:1 aspect ratio.', 'Do NOT depict literal musical instruments (like guitars or microphones) unless they are part of a surreal abstract composition.', 'No blurry text. No messy borders. No watermarks.', ] return promptParts.filter(Boolean).join('\n\n') }