re choose cover and new prompt
This commit is contained in:
+243
-49
@@ -1,3 +1,192 @@
|
||||
const STYLE_PRESET_MAP = {
|
||||
'Réaliste (style cinématographique)': {
|
||||
style: 'Cinematic realism, film still, anamorphic lens, shallow depth of field',
|
||||
palettes: [
|
||||
'cool teal and amber highlights, muted neutrals',
|
||||
'stormy blues with soft gold accents',
|
||||
'charcoal, steel blue, and warm tungsten glows',
|
||||
],
|
||||
lighting: [
|
||||
'dramatic key light with soft fill and deep shadows',
|
||||
'low-key cinematic lighting with subtle haze',
|
||||
],
|
||||
textures: ['subtle film grain and crisp detail', 'matte finish with fine grain'],
|
||||
typography: ['clean cinematic title card, subtle embossing'],
|
||||
compositions: ['cinematic framing with a strong subject focus'],
|
||||
},
|
||||
'Artistique (style peinture moderne)': {
|
||||
style: 'Modern painting, expressive brushstrokes, gallery-ready composition',
|
||||
palettes: [
|
||||
'rich pigments with bold contrast',
|
||||
'muted pastels with a sharp accent color',
|
||||
'deep jewel tones and warm highlights',
|
||||
],
|
||||
lighting: ['soft gallery lighting with gentle gradients'],
|
||||
textures: ['visible canvas texture and layered paint', 'acrylic strokes with matte finish'],
|
||||
typography: ['refined serif lettering integrated into the paint'],
|
||||
compositions: ['balanced composition with painterly focal point'],
|
||||
},
|
||||
'Style Dessins': {
|
||||
style: 'Hand-drawn illustration, clean linework, ink and colored pencil',
|
||||
palettes: [
|
||||
'warm paper tones with soft color fills',
|
||||
'limited palette with bold accent color',
|
||||
],
|
||||
lighting: ['soft diffused light with minimal shadows'],
|
||||
textures: ['paper texture with visible grain'],
|
||||
typography: ['hand-lettered title with slight texture'],
|
||||
compositions: ['centered illustration with clear silhouette'],
|
||||
},
|
||||
'Style rétros': {
|
||||
style: 'Retro poster art, vintage print, halftone patterns, aged paper',
|
||||
palettes: [
|
||||
'sun-faded oranges, teal, and cream',
|
||||
'muted reds, mustard, and dark green',
|
||||
],
|
||||
lighting: ['flat poster lighting with strong contrast'],
|
||||
textures: ['distressed print texture and subtle scratches'],
|
||||
typography: ['vintage serif lettering with screen print texture'],
|
||||
compositions: ['poster-style layout with bold hierarchy'],
|
||||
},
|
||||
'Style cyberpunk': {
|
||||
style: 'Cyberpunk aesthetic, futuristic city glow, reflective surfaces',
|
||||
palettes: [
|
||||
'neon magenta and electric blue on dark backgrounds',
|
||||
'cyan, violet, and deep black with sharp highlights',
|
||||
],
|
||||
lighting: ['neon rim light and high-contrast highlights'],
|
||||
textures: ['glossy surfaces with subtle rain speckles'],
|
||||
typography: ['neon tube lettering embedded in the scene'],
|
||||
compositions: ['dynamic perspective with strong depth'],
|
||||
},
|
||||
'Style Afro': {
|
||||
style: 'Afrofuturist motifs, bold patterns, textile-inspired geometry',
|
||||
palettes: [
|
||||
'warm earth tones with vibrant accents',
|
||||
'gold, terracotta, deep blue, and emerald',
|
||||
],
|
||||
lighting: ['warm directional light with rich contrast'],
|
||||
textures: ['woven fabric texture and layered patterns'],
|
||||
typography: ['bold lettering with subtle pattern fills'],
|
||||
compositions: ['symmetrical layout with iconic central motif'],
|
||||
},
|
||||
'Style grunge': {
|
||||
style: 'Grunge collage, distressed textures, gritty mixed media',
|
||||
palettes: [
|
||||
'smoky blacks with muted reds and greys',
|
||||
'dirty neutrals with high-contrast highlights',
|
||||
],
|
||||
lighting: ['moody low-key lighting with harsh shadows'],
|
||||
textures: ['torn paper, scratches, and distressed overlays'],
|
||||
typography: ['distressed lettering with rough edges'],
|
||||
compositions: ['layered collage with imperfect alignment'],
|
||||
},
|
||||
'Style pop art': {
|
||||
style: 'Pop art illustration, bold outlines, Ben-Day dots, screen print',
|
||||
palettes: [
|
||||
'bold primary colors with black and white',
|
||||
'bright yellow, red, and cyan with clean contrast',
|
||||
],
|
||||
lighting: ['flat graphic lighting with crisp separation'],
|
||||
textures: ['screen print texture with halftone dots'],
|
||||
typography: ['bold outlined letters with halftone texture'],
|
||||
compositions: ['graphic layout with strong shapes and punchy hierarchy'],
|
||||
},
|
||||
}
|
||||
|
||||
const DEFAULT_STYLE_VARIANTS = [
|
||||
'Conceptual album art, abstract surrealism, high fidelity',
|
||||
'Graphic collage, mixed media, layered textures',
|
||||
'Minimalist design, bold shapes, strong negative space',
|
||||
'Dreamlike photography, cinematic framing, subtle grain',
|
||||
'Geometric abstraction, clean gradients, modern design',
|
||||
'Stylized illustration, crisp edges, bold composition',
|
||||
]
|
||||
|
||||
const COMPOSITION_VARIANTS = [
|
||||
'centered focal subject with balanced symmetry',
|
||||
'asymmetrical layout with dynamic diagonal flow',
|
||||
'minimal composition with strong negative space',
|
||||
'collage-like layout with layered elements',
|
||||
'close-up framing for intimacy and impact',
|
||||
'wide cinematic framing with a distant focal point',
|
||||
]
|
||||
|
||||
const LIGHTING_VARIANTS = [
|
||||
'dramatic chiaroscuro with deep shadows',
|
||||
'soft diffused light with gentle gradients',
|
||||
'high-contrast lighting with sharp highlights',
|
||||
'backlit silhouette with glowing edges',
|
||||
'moody low-key lighting with selective highlights',
|
||||
]
|
||||
|
||||
const PALETTE_VARIANTS = [
|
||||
'deep navy with warm amber accents',
|
||||
'muted earth tones with copper highlights',
|
||||
'cool blues with silver accents',
|
||||
'bold primary colors with black and white',
|
||||
'monochrome with a single accent color',
|
||||
'pastel gradients with a sharp contrasting highlight',
|
||||
'electric blue and magenta on dark tones',
|
||||
]
|
||||
|
||||
const TEXTURE_VARIANTS = [
|
||||
'subtle film grain with a matte finish',
|
||||
'canvas texture with visible brushwork',
|
||||
'paper cutout layers with rough edges',
|
||||
'glossy highlights with clean edges',
|
||||
'distressed print texture with scratches',
|
||||
]
|
||||
|
||||
const TYPOGRAPHY_VARIANTS = [
|
||||
'embossed metallic lettering integrated into the art',
|
||||
'minimalist sans-serif with generous tracking',
|
||||
'hand-drawn lettering with slight texture',
|
||||
'neon-style lettering embedded in the scene',
|
||||
'classic serif with elegant spacing',
|
||||
]
|
||||
|
||||
const SUBJECT_VARIANTS = [
|
||||
'a single strong symbol or scene that represents the song',
|
||||
'an abstract motif with a clear focal point',
|
||||
'a cinematic moment captured mid-action',
|
||||
'a minimalist icon or silhouette with strong presence',
|
||||
'a surreal object or landscape that feels iconic',
|
||||
]
|
||||
|
||||
const ATMOSPHERE_DARK = [
|
||||
'cinematic and moody with deep contrast',
|
||||
'noir ambience with subtle haze and high contrast',
|
||||
'tense and dramatic with low-key depth',
|
||||
]
|
||||
|
||||
const ATMOSPHERE_ENERGETIC = [
|
||||
'dynamic and high energy with punchy contrast',
|
||||
'electric and fast-paced with vivid saturation',
|
||||
'bold and kinetic with sharp highlights',
|
||||
]
|
||||
|
||||
const ATMOSPHERE_SOFT = [
|
||||
'calm and spacious with balanced mood',
|
||||
'introspective and gentle with airy depth',
|
||||
'dreamlike and serene with soft transitions',
|
||||
]
|
||||
|
||||
const hashSeed = (value) => {
|
||||
const str = String(value || '')
|
||||
let hash = 0
|
||||
for (let i = 0; i < str.length; i += 1) {
|
||||
hash = (hash * 31 + str.charCodeAt(i)) >>> 0
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
const pickVariant = (list, seed, salt = 0) => {
|
||||
if (!Array.isArray(list) || list.length === 0) return ''
|
||||
const idx = (seed + salt) % list.length
|
||||
return list[idx]
|
||||
}
|
||||
|
||||
exports.generatePicturePrompt = (project = {}) => {
|
||||
const {
|
||||
title = '',
|
||||
@@ -5,6 +194,7 @@ exports.generatePicturePrompt = (project = {}) => {
|
||||
musicConfig = {},
|
||||
coverStyle: coverStyleRaw = '',
|
||||
artistName: artistNameRaw = '',
|
||||
variantSeed = '',
|
||||
} = project || {}
|
||||
|
||||
// --- 1. Nettoyage et Normalisation ---
|
||||
@@ -20,10 +210,38 @@ exports.generatePicturePrompt = (project = {}) => {
|
||||
const artistName = sanitizeInline(artistNameRaw) || sanitizeInline(project?.userName || '')
|
||||
const hasArtistName = artistName.length > 0
|
||||
|
||||
const { genres = [], tempo = '', mood = '', instruments = [] } = musicConfig || {}
|
||||
const { genres = [], tempo = '', mood = '' } = musicConfig || {}
|
||||
const userStyle = sanitizeInline(coverStyleRaw)
|
||||
|
||||
// --- 2. Intelligence Visuelle (Mapping) ---
|
||||
const seedInput = [titleForPrompt, artistName, userStyle, String(variantSeed || '')].join('|')
|
||||
const baseSeed = hashSeed(seedInput)
|
||||
const seed = baseSeed || Math.floor(Math.random() * 1_000_000_000)
|
||||
|
||||
// --- 2. Intelligence Visuelle (Mapping & Variations) ---
|
||||
const preset = STYLE_PRESET_MAP[userStyle] || null
|
||||
const styleDescriptor = preset?.style || userStyle || pickVariant(DEFAULT_STYLE_VARIANTS, seed, 7)
|
||||
const renderingStyle = `Art Style: ${styleDescriptor}.`
|
||||
|
||||
const compositionChoice =
|
||||
preset?.compositions?.length > 0
|
||||
? pickVariant(preset.compositions, seed, 1)
|
||||
: pickVariant(COMPOSITION_VARIANTS, seed, 1)
|
||||
const lightingChoice =
|
||||
preset?.lighting?.length > 0
|
||||
? pickVariant(preset.lighting, seed, 2)
|
||||
: pickVariant(LIGHTING_VARIANTS, seed, 2)
|
||||
const paletteChoice =
|
||||
preset?.palettes?.length > 0
|
||||
? pickVariant(preset.palettes, seed, 3)
|
||||
: pickVariant(PALETTE_VARIANTS, seed, 3)
|
||||
const textureChoice =
|
||||
preset?.textures?.length > 0
|
||||
? pickVariant(preset.textures, seed, 4)
|
||||
: pickVariant(TEXTURE_VARIANTS, seed, 4)
|
||||
const typographyChoice =
|
||||
preset?.typography?.length > 0
|
||||
? pickVariant(preset.typography, seed, 5)
|
||||
: pickVariant(TYPOGRAPHY_VARIANTS, seed, 5)
|
||||
|
||||
// Détermination de l'énergie visuelle
|
||||
const isEnergetic =
|
||||
@@ -31,47 +249,21 @@ exports.generatePicturePrompt = (project = {}) => {
|
||||
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.'
|
||||
}
|
||||
const atmosphereChoice = isDark
|
||||
? pickVariant(ATMOSPHERE_DARK, seed, 6)
|
||||
: isEnergetic
|
||||
? pickVariant(ATMOSPHERE_ENERGETIC, seed, 6)
|
||||
: pickVariant(ATMOSPHERE_SOFT, seed, 6)
|
||||
|
||||
// --- 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
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 10)
|
||||
.slice(0, 2)
|
||||
.join('. ')
|
||||
|
||||
@@ -79,36 +271,38 @@ exports.generatePicturePrompt = (project = {}) => {
|
||||
? `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 subjectChoice = pickVariant(SUBJECT_VARIANTS, seed, 8)
|
||||
|
||||
// --- 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:**`,
|
||||
'**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.',
|
||||
`Typography treatment: ${typographyChoice}.`,
|
||||
'Ensure perfect spelling. The text should be integrated into the artwork (e.g., embossed texture, neon tube, or bold cut-out), not just pasted on top.',
|
||||
|
||||
// 2. Le Visuel
|
||||
`**Visuals:**`,
|
||||
'**Visual Direction:**',
|
||||
renderingStyle,
|
||||
`Composition: ${compositionChoice}.`,
|
||||
`Surface & Texture: ${textureChoice}.`,
|
||||
`Subject: ${subjectChoice}.`,
|
||||
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,
|
||||
'**Mood & Color:**',
|
||||
`Atmosphere: ${atmosphereChoice}.`,
|
||||
`Palette: ${paletteChoice}.`,
|
||||
`Lighting: ${lightingChoice}.`,
|
||||
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.',
|
||||
'No watermarks or logos.',
|
||||
'No blurry text or messy borders.',
|
||||
'Avoid generic stock imagery and clichéd instruments unless essential to the concept.',
|
||||
]
|
||||
|
||||
return promptParts.filter(Boolean).join('\n\n')
|
||||
|
||||
Reference in New Issue
Block a user