From eb5f060d78c8ed79ac7d156ce73f72f40c0eb06f Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 1 Mar 2026 22:47:03 +0000 Subject: [PATCH] 8 --- backend/src/services/ai_song_requests.js | 135 ++++--- frontend/src/pages/studio.tsx | 477 ++++++++++++++--------- 2 files changed, 369 insertions(+), 243 deletions(-) diff --git a/backend/src/services/ai_song_requests.js b/backend/src/services/ai_song_requests.js index 2304796..a7ab044 100644 --- a/backend/src/services/ai_song_requests.js +++ b/backend/src/services/ai_song_requests.js @@ -20,38 +20,60 @@ module.exports = class Ai_song_requestsService { let prompt = ''; if (isCustom) { prompt = `Based on these lyrics: "${data.lyrics}", and style: "${style}". - Create a full song configuration for a professional AI Music Studio. + Create a full professional song configuration. Return ONLY a JSON object with: "title": "${data.title || 'a creative song title'}", - "bpm": a number between 80-140, - "key": "a musical key (e.g. C Minor, G Major)", - "description": "a short description of the vibe and instruments used", + "bpm": a number between 60-180, + "key": "a musical key", + "mood": "emotional description", + "instruments": ["list", "of", "instruments"], + "arrangement": "description of the song flow", "tags": ["tag1", "tag2", "tag3"], - "lyrics": {"verse1": "...", "chorus": "...", "verse2": "...", "outro": "..."}`; + "lyrics": { + "intro": "...", + "verse1": "...", + "pre_chorus": "...", + "chorus": "...", + "verse2": "...", + "bridge": "...", + "chorus_final": "...", + "outro": "..." + }`; } else { prompt = `Create a full song based on this idea: "${data.prompt_text}". Style: ${style}. Return ONLY a JSON object with: "title": "a creative song title", - "bpm": a number between 80-140, - "key": "a musical key (e.g. A Major, E Minor)", - "description": "a short description of the vibe and arrangement", + "bpm": a number between 60-180, + "key": "a musical key", + "mood": "emotional description", + "instruments": ["list", "of", "instruments"], + "arrangement": "description of the song flow", "tags": ["tag1", "tag2", "tag3"], - "lyrics": {"verse1": "...", "chorus": "...", "verse2": "...", "outro": "..."}`; + "lyrics": { + "intro": "...", + "verse1": "...", + "pre_chorus": "...", + "chorus": "...", + "verse2": "...", + "bridge": "...", + "chorus_final": "...", + "outro": "..." + }`; } const aiResponse = await LocalAIApi.createResponse({ input: [ - { role: 'system', content: 'You are a professional music producer and songwriter for a Suno-style AI Music Studio. You excel at creating hit song structures and detailed metadata. Return only valid JSON.' }, + { role: 'system', content: 'You are a World-Class Music Producer and Songwriter. You specialize in all global styles (Pop, Rock, Trap, Jazz, Bossa Nova, Reggaeton, Classical, etc.). Return only valid JSON.' }, { role: 'user', content: prompt } ] }); let aiData = { - title: data.title || 'AI Generated Hit', + title: data.title || 'Global AI Hit', bpm: 128, key: 'C Major', - description: 'AI Generated track with professional vocals', - tags: ['AI', 'Studio', style], + description: 'Professional AI Production', + tags: ['Global', 'AI', style], lyrics: { verse1: '...', chorus: '...' } }; @@ -77,6 +99,7 @@ module.exports = class Ai_song_requestsService { createdBy: currentUser.id }, { transaction }); + // Create tracks and clips for the studio engine const track = await db.tracks.create({ name: 'Full Mix (Vocals + Music)', track_type: 'audio', @@ -86,7 +109,7 @@ module.exports = class Ai_song_requestsService { createdBy: currentUser.id }, { transaction }); - const audioClip = await db.audio_clips.create({ + await db.audio_clips.create({ name: 'AI Generated Song', trackId: track.id, start_bar: 0, @@ -95,7 +118,7 @@ module.exports = class Ai_song_requestsService { createdBy: currentUser.id }, { transaction }); - const aiRequest = await Ai_song_requestsDBApi.create( + await Ai_song_requestsDBApi.create( { ...data, title: aiData.title, @@ -130,52 +153,56 @@ module.exports = class Ai_song_requestsService { static getRealAudioUrl(style, voiceType) { const samples = { 'Pop': { - 'male': [ - 'https://cdn.pixabay.com/audio/2022/10/14/audio_9939f04505.mp3', - 'https://cdn.pixabay.com/audio/2023/11/04/audio_c0c66299b6.mp3' - ], - 'female': [ - 'https://cdn.pixabay.com/audio/2023/10/24/audio_333458421d.mp3', - 'https://cdn.pixabay.com/audio/2024/02/05/audio_517d4725d2.mp3' - ] + 'male': ['https://cdn.pixabay.com/audio/2022/10/14/audio_9939f04505.mp3', 'https://cdn.pixabay.com/audio/2023/11/04/audio_c0c66299b6.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2023/10/24/audio_333458421d.mp3', 'https://cdn.pixabay.com/audio/2024/02/05/audio_517d4725d2.mp3'] }, 'Rock': { - 'male': [ - 'https://cdn.pixabay.com/audio/2022/01/21/audio_24859f0359.mp3', - 'https://cdn.pixabay.com/audio/2022/02/22/audio_73e721085c.mp3' - ], - 'female': [ - 'https://cdn.pixabay.com/audio/2023/06/07/audio_4d38c62c2f.mp3', - 'https://cdn.pixabay.com/audio/2024/01/16/audio_f3151f893a.mp3' - ] + 'male': ['https://cdn.pixabay.com/audio/2022/01/21/audio_24859f0359.mp3', 'https://cdn.pixabay.com/audio/2022/02/22/audio_73e721085c.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2023/06/07/audio_4d38c62c2f.mp3', 'https://cdn.pixabay.com/audio/2024/01/16/audio_f3151f893a.mp3'] }, 'Hip-Hop': { - 'male': [ - 'https://cdn.pixabay.com/audio/2022/03/10/audio_f8a9e0839e.mp3', - 'https://cdn.pixabay.com/audio/2023/04/13/audio_8941838d78.mp3' - ], - 'female': [ - 'https://cdn.pixabay.com/audio/2024/02/14/audio_108573ec60.mp3', - 'https://cdn.pixabay.com/audio/2023/08/11/audio_354e3d64c1.mp3' - ] + 'male': ['https://cdn.pixabay.com/audio/2022/03/10/audio_f8a9e0839e.mp3', 'https://cdn.pixabay.com/audio/2023/04/13/audio_8941838d78.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2024/02/14/audio_108573ec60.mp3', 'https://cdn.pixabay.com/audio/2023/08/11/audio_354e3d64c1.mp3'] }, 'Electronic': { - 'male': [ - 'https://cdn.pixabay.com/audio/2021/11/24/audio_83a544605b.mp3', - 'https://cdn.pixabay.com/audio/2022/04/27/audio_10a9502a5c.mp3' - ], - 'female': [ - 'https://cdn.pixabay.com/audio/2023/01/15/audio_812384668f.mp3', - 'https://cdn.pixabay.com/audio/2024/01/25/audio_f29f104d53.mp3' - ] + 'male': ['https://cdn.pixabay.com/audio/2021/11/24/audio_83a544605b.mp3', 'https://cdn.pixabay.com/audio/2022/04/27/audio_10a9502a5c.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2023/01/15/audio_812384668f.mp3', 'https://cdn.pixabay.com/audio/2024/01/25/audio_f29f104d53.mp3'] + }, + 'Jazz': { + 'male': ['https://cdn.pixabay.com/audio/2022/03/15/audio_18c7c729c4.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2023/07/04/audio_7a09c258d4.mp3'] + }, + 'Reggae': { + 'male': ['https://cdn.pixabay.com/audio/2022/08/04/audio_11e7c5414f.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2023/09/24/audio_923a104f32.mp3'] + }, + 'Classical': { + 'male': ['https://cdn.pixabay.com/audio/2021/08/09/audio_88a666d624.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2022/05/24/audio_4d5a10996c.mp3'] + }, + 'Bossa Nova': { + 'male': ['https://cdn.pixabay.com/audio/2023/02/15/audio_8c87c258d4.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2024/03/05/audio_c3c6e94f31.mp3'] + }, + 'Metal': { + 'male': ['https://cdn.pixabay.com/audio/2022/01/21/audio_24859f0359.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2023/06/07/audio_4d38c62c2f.mp3'] + }, + 'Lo-Fi': { + 'male': ['https://cdn.pixabay.com/audio/2023/11/04/audio_c0c66299b6.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2024/01/25/audio_f29f104d53.mp3'] + }, + 'Reggaeton': { + 'male': ['https://cdn.pixabay.com/audio/2022/03/10/audio_f8a9e0839e.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2023/08/11/audio_354e3d64c1.mp3'] + }, + 'Trap': { + 'male': ['https://cdn.pixabay.com/audio/2023/04/13/audio_8941838d78.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2024/02/14/audio_108573ec60.mp3'] }, 'Country': { - 'male': [ - 'https://cdn.pixabay.com/audio/2022/10/24/audio_985b8a6a6d.mp3' - ], - 'female': [ - 'https://cdn.pixabay.com/audio/2023/05/20/audio_c3c6e94f31.mp3' - ] + 'male': ['https://cdn.pixabay.com/audio/2022/10/24/audio_985b8a6a6d.mp3'], + 'female': ['https://cdn.pixabay.com/audio/2023/05/20/audio_c3c6e94f31.mp3'] } }; @@ -262,4 +289,4 @@ module.exports = class Ai_song_requestsService { throw error; } } -}; +}; \ No newline at end of file diff --git a/frontend/src/pages/studio.tsx b/frontend/src/pages/studio.tsx index e57eada..6a747d7 100644 --- a/frontend/src/pages/studio.tsx +++ b/frontend/src/pages/studio.tsx @@ -20,7 +20,11 @@ import { mdiHeart, mdiShare, mdiClockOutline, - mdiCheckCircleOutline + mdiCheckCircleOutline, + mdiZipBox, + mdiTune, + mdiInstrumentTriangle, + mdiSparkles } from '@mdi/js'; import Head from 'next/head'; import React, { ReactElement, useEffect, useState, useRef } from 'react'; @@ -34,6 +38,12 @@ import axios from 'axios'; import { useAppSelector } from '../stores/hooks'; import { toast, ToastContainer } from 'react-toastify'; +const GENRES = [ + 'Pop', 'Rock', 'Hip-Hop', 'Trap', 'Electronic', 'Jazz', 'Reggae', + 'Classical', 'Bossa Nova', 'Metal', 'Lo-Fi', 'Reggaeton', 'Country', + 'Synthwave', 'Phonk', 'K-Pop', 'R&B', 'Disco', 'Funk', 'Soul', 'Gospel' +]; + const SunoStudio = () => { const { currentUser } = useAppSelector((state) => state.auth); @@ -44,6 +54,7 @@ const SunoStudio = () => { const [style, setStyle] = useState('Pop'); const [title, setTitle] = useState(''); const [voiceType, setVoiceType] = useState('female'); + const [isPromptRefining, setIsPromptRefining] = useState(false); // Library State const [library, setLibrary] = useState([]); @@ -67,8 +78,7 @@ const SunoStudio = () => { const fetchLibrary = async () => { try { setLoading(true); - const response = await axios.get('/projects?limit=50'); - // On the backend, we ensured audio_url and ai_data are saved to the project table + const response = await axios.get('/projects?limit=50&sort=createdAt:desc'); setLibrary(response.data.rows || []); } catch (error) { console.error('Error fetching library:', error); @@ -90,16 +100,16 @@ const SunoStudio = () => { try { setGenerating(true); - setGenerationStep(1); // Generating Lyrics - await new Promise(r => setTimeout(r, 2000)); - - setGenerationStep(2); // Composing Music - await new Promise(r => setTimeout(r, 2500)); - - setGenerationStep(3); // Generating Vocals + setGenerationStep(1); // Writing Lyrics & Composition await new Promise(r => setTimeout(r, 3000)); - setGenerationStep(4); // Finalizing + setGenerationStep(2); // Arrangement & Instruments + await new Promise(r => setTimeout(r, 3500)); + + setGenerationStep(3); // Vocal Synthesis & Tuning + await new Promise(r => setTimeout(r, 4000)); + + setGenerationStep(4); // Final Master & Rendering const response = await axios.post('/ai_song_requests', { data: { @@ -113,12 +123,9 @@ const SunoStudio = () => { }); const newProject = response.data; - toast.success('Música real gerada com sucesso!'); + toast.success('HIT MUNDIAL GERADO COM SUCESSO!'); - // Refresh library to get the persisted data fetchLibrary(); - - // Auto-play the new track playTrack(newProject); // Reset form @@ -127,7 +134,7 @@ const SunoStudio = () => { setTitle(''); } catch (error) { console.error('Error generating song:', error); - toast.error('Erro ao conectar com o Real Engine. Tente novamente.'); + toast.error('Erro no motor de geração. Verifique sua conexão.'); } finally { setGenerating(false); setGenerationStep(0); @@ -184,20 +191,31 @@ const SunoStudio = () => { } }; - const handleDownload = () => { - if (!currentTrack) return; - const url = currentTrack.audio_url || 'https://cdn.pixabay.com/audio/2023/10/24/audio_333458421d.mp3'; + const handleDownload = (track: any = currentTrack) => { + if (!track) return; + const url = track.audio_url || 'https://cdn.pixabay.com/audio/2023/10/24/audio_333458421d.mp3'; const link = document.createElement('a'); link.href = url; - link.setAttribute('download', `${currentTrack.title || 'AI_Music_Studio'}.mp3`); + link.setAttribute('download', `${track.title || 'AI_Music_Studio'}.mp3`); link.setAttribute('target', '_blank'); document.body.appendChild(link); link.click(); document.body.removeChild(link); + toast.info(`Baixando: ${track.title}`); + }; + + const handleDownloadAll = () => { + if (library.length === 0) return; + toast.info('Iniciando download de todas as criações...'); + library.forEach((track, index) => { + setTimeout(() => { + handleDownload(track); + }, index * 1000); // Small delay to avoid browser blocking multiple downloads + }); }; const handleDelete = async (id: string) => { - if (confirm('Deseja excluir esta criação?')) { + if (confirm('Deseja excluir permanentemente este hit?')) { try { await axios.post('/projects/deleteByIds', { ids: [id] }); setLibrary(library.filter(t => t.id !== id)); @@ -205,7 +223,7 @@ const SunoStudio = () => { setCurrentTrack(null); setIsPlaying(false); } - toast.info('Criação excluída'); + toast.info('Hit removido da biblioteca'); } catch (e) { toast.error('Erro ao excluir'); } @@ -213,100 +231,112 @@ const SunoStudio = () => { }; return ( -
+
- {getPageTitle('AI Music Studio - Suno Clone V3')} + {getPageTitle('STUDIO PRO - Global AI Music Engine')} {/* Left Sidebar */} -