From 66b41e8b7396caade920da9cb912669b37fd605a Mon Sep 17 00:00:00 2001 From: Thomas Demirdjian Date: Wed, 1 Oct 2025 15:48:23 +0200 Subject: [PATCH] fix prompt and thumbnail path --- functions/src/lyrics.js | 79 ++++++++++------- functions/src/thumbnail.js | 4 +- src/screens/Production/DownloadSongs.js | 109 +++++++++++++----------- 3 files changed, 109 insertions(+), 83 deletions(-) diff --git a/functions/src/lyrics.js b/functions/src/lyrics.js index 9001001..a268958 100644 --- a/functions/src/lyrics.js +++ b/functions/src/lyrics.js @@ -24,40 +24,59 @@ exports.generateLyrics = onCall({}, async ({ auth = {}, data = {} }) => { console.log("Function generate lyrics start with data", data); - const system = - ` + const system = ` Tu es un parolier expert en chanson française moderne et populaire. -Tu écris des chansons marquantes, accessibles, sur des thématiques ` + - `d'innovation, d'esprit d'équipe et de créativité digitale. -Ton ` + - `écriture doit toucher à la fois l'humain, le collectif et la ` + - `passion d'entreprendre. -Tu dois générer un titre accrocheur et ` + - `mémorable pour la chanson en plus des paroles. -Respecte ` + - `précisément la structure demandée et fournis le résultat dans un ` + - `format JSON clair, respectant strictement le schéma demandé. +Tu écris des chansons marquantes, accessibles, sur des thématiques d'innovation, d'esprit d'équipe et de créativité digitale. +Ton écriture doit toucher à la fois l'humain, le collectif et la passion d'entreprendre. +Analyse attentivement les informations placées entre balises XML-like. +Génère un titre accrocheur et mémorable en plus des paroles, tout en respectant strictement la structure demandée. +Retourne uniquement un JSON conforme au schéma fourni, sans ajouter d'autres textes. `.trim(); - // Construction du prompt utilisateur - const prompt = - ` -Objectif : ${objective} -Contexte : ${context} -Émotion : ${emotion} -Style musical : ${style} -Audience cible : ${audience} -Structure de la chanson : ${structure.join(" => ")} -Schéma de rimes : ${rhymes} + const structureTags = (Array.isArray(structure) ? structure : []) + .map((part, index) => { + const content = part || ""; + return `
${content}
`; + }) + .join("\n"); -Génère un titre accrocheur et les paroles de la chanson en suivant ` + - `strictement cette structure. -Le titre doit être court, ` + - `mémorable et refléter l'esprit de la musique. -Pour chaque ` + - `partie ("couplet" ou "refrain"), écris 4 à 16 lignes adaptées, ` + - `expressives et cohérentes avec le style et l'émotion souhaitée. -`.trim(); + const fallbackStructureTags = [ + '
couplet
', + '
refrain
', + ].join("\n"); + + // Construction du prompt utilisateur avec des balises explicites + const prompt = ` + + ${objective || ""} + ${context || ""} + ${emotion || ""} + ${style || ""} + ${audience || ""} + ${rhymes || ""} + + + +${structureTags || fallbackStructureTags} + + + + + Génère un titre court, mémorable et aligné avec l'esprit de la musique. + + + Pour chaque section demandée, rédige entre 4 et 16 lignes expressives. + Respecte strictement l'ordre et le type de chaque section (couplet, refrain, etc.). + + + + Retourne uniquement un objet JSON valide selon le schéma. + Utilise les retours à la ligne (\n) pour séparer les phrases afin de conserver le découpage. + + + `.trim(); // Définition du schéma zod/genkit pour la validation du retour const lyricsSchema = z.object({ diff --git a/functions/src/thumbnail.js b/functions/src/thumbnail.js index f55d812..6aa6327 100644 --- a/functions/src/thumbnail.js +++ b/functions/src/thumbnail.js @@ -29,7 +29,9 @@ exports.generateVideoThumbnail = onObjectFinalized( if (/_thumb9x16\.jpg$/i.test(objectName)) return; const bucket = admin.storage().bucket(bucketName); - const playbackMatch = objectName.match(/^musics\/([^/]+)\/playback\.mp4$/i); + const playbackMatch = objectName.match( + /^users\/[^/]+\/projects\/([^/]+)\/playback\.mp4$/i, + ); const projectId = playbackMatch ? playbackMatch[1] : null; // Use unique folder under /tmp to avoid name collisions diff --git a/src/screens/Production/DownloadSongs.js b/src/screens/Production/DownloadSongs.js index adebc85..fcf103f 100644 --- a/src/screens/Production/DownloadSongs.js +++ b/src/screens/Production/DownloadSongs.js @@ -1,5 +1,5 @@ -import { BlurView } from 'expo-blur'; -import React from 'react'; +import { BlurView } from "expo-blur"; +import React from "react"; import { Image, Platform, @@ -7,38 +7,39 @@ import { StyleSheet, Text, View, -} from 'react-native'; -import useMinuit from 'react-native-minuit/src/hooks/useMinuit.js'; -import { responsiveHeight } from 'react-native-responsive-dimensions'; -import { background, img } from '../../assets'; -import MusicLandHeader from '../../components/MusicLandHeader'; -import { projectsRef, serverTimestamp } from '../../config/firebase'; -import { uploadFileToFirebase } from '../../helpers/uploadToFirebase'; -import Page from '../../layouts/Page'; -import { Routes } from '../../navigation'; -import { goBack, navigate } from '../../navigation/NavigationService'; -import { Palette } from '../../styles'; -import { FONT_FAMILY } from '../../styles/Fonts'; +} from "react-native"; +import useMinuit from "react-native-minuit/src/hooks/useMinuit.js"; +import { responsiveHeight } from "react-native-responsive-dimensions"; +import { background, img } from "../../assets"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import { projectsRef, serverTimestamp } from "../../config/firebase"; +import { uploadFileToFirebase } from "../../helpers/uploadToFirebase"; +import Page from "../../layouts/Page"; +import { Routes } from "../../navigation"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import { Palette } from "../../styles"; +import { FONT_FAMILY } from "../../styles/Fonts"; +import { size } from "../../styles/Style"; +import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; +import { useUserData } from "../../providers/UserDataProvider"; -import { size } from '../../styles/Style'; -import CreateLyricsHeader from '../Writing/components/CreateLyricsHeader'; const DownloadSongs = ({ route }) => { - // const params = useRoute().params; + const { currentUID } = useUserData(); const { action, uri, project } = route.params || {}; - console.log('project id', project?.id); + console.log("project id", project?.id); const { setIsLoading, setTooltip } = useMinuit(); const handleDownloadUri = async () => { - if (action === 'playback' && project?.id) { + if (action === "playback" && project?.id) { // Publication du playback - console.log('project id : ', project.id); + console.log("project id : ", project.id); try { setIsLoading(true); const { resultURI = null } = await uploadFileToFirebase({ uri: uri, - path: `musics/${project.id}/source.mp4`, + path: `users/${currentUID}/projects/${project.id}/playback.mp4`, shouldCompress: true, - fileType: 'VIDEO', + fileType: "VIDEO", }); if (!resultURI) throw new Error("Téléversement de l'image impossible"); @@ -49,23 +50,23 @@ const DownloadSongs = ({ route }) => { playbackUrl: resultURI, updatedAt: serverTimestamp(), }, - { merge: true } + { merge: true }, ); setTooltip({ - type: 'success', - text: 'Vidéo uploadée, conversion HLS en cours…', + type: "success", + text: "Vidéo uploadée, conversion HLS en cours…", }); } else { setTooltip({ - type: 'error', - text: 'Erreur lors de la publication du playback', + type: "error", + text: "Erreur lors de la publication du playback", }); } } catch (error) { - console.log('error upload playback', error); + console.log("error upload playback", error); setTooltip({ - type: 'error', - text: 'Erreur lors de la publication du playback', + type: "error", + text: "Erreur lors de la publication du playback", }); } finally { setIsLoading(false); @@ -78,37 +79,39 @@ const DownloadSongs = ({ route }) => { return ( + headerType="NONE" + > + }} + > - Prêt à télécharger{' '} - {action === 'playback' ? 'ton Playback' : 'ta chanson'} ? + Prêt à télécharger{" "} + {action === "playback" ? "ton Playback" : "ta chanson"} ? { - console.log('test'); + console.log("test"); handleDownloadUri(); } @@ -116,18 +119,19 @@ const DownloadSongs = ({ route }) => { // action, // uri, // }) - }> + } + > - Télécharger{' '} - {action === 'playback' ? 'mon Playback' : 'ma chanson'} + Télécharger{" "} + {action === "playback" ? "mon Playback" : "ma chanson"} Pour moi uniquement @@ -138,25 +142,26 @@ const DownloadSongs = ({ route }) => { navigate(Routes.StreamSong, { action, }) - }> + } + > - Diffuser{' '} - {action === 'playback' ? 'mon Playback' : 'ma chanson'} sur + Diffuser{" "} + {action === "playback" ? "mon Playback" : "ma chanson"} sur la plateforme de MusicLand (+ réseaux sociaux) et participer au concours Top 3: 1er 15% du CA ML - 2ème 10% du CA ML - 3ème 5% du CA - ML (catégorie{' '} - {action === 'playback' ? 'Playback' : 'chanson'}) + ML (catégorie{" "} + {action === "playback" ? "Playback" : "chanson"}) @@ -193,9 +198,9 @@ const styles = StyleSheet.create({ }, itemContainer: { borderRadius: 12, - overflow: 'hidden', - backgroundColor: '#FFFFFF03', - shadowColor: '#0000001A', + overflow: "hidden", + backgroundColor: "#FFFFFF03", + shadowColor: "#0000001A", shadowOffset: { width: 0, height: 2,