feat: try lipsinck

This commit is contained in:
2026-09-03 11:06:08 +02:00
parent 99431f9ae4
commit 7521f5939f
9 changed files with 196 additions and 88 deletions
+41 -6
View File
@@ -259,7 +259,7 @@ ${structureTags || fallbackStructureTags}
0. ${languageInstruction}
1. Génère un **Titre** percutant (moins de 6 mots).
2. Pour chaque section <SECTION>, écris le contenu adapté :
- Si c'est "Instrumental" ou "Solo" : laisse le champ 'lyrics' vide ou mets une brève indication d'ambiance entre parenthèses ex: "(Solo de guitare déchirant)".
- Si c'est "Instrumental", "Intro", "Pont" ou "Solo" : le champ 'lyrics' doit être strictement vide. N'ajoute aucune indication entre parenthèses.
- Si c'est "Couplet/Refrain" : Écris 4 à 12 vers.
3. **IMPORTANT** : Le style est "${style}". Assure-toi que le vocabulaire et le rythme collent parfaitement à ce genre.
</CONSIGNES_GENERATION>
@@ -428,15 +428,16 @@ async function getSunoTimestamps(projectId) {
const docSnap = await refList.projects.doc(projectId).get()
if (!docSnap.exists) throw new Error('Projet introuvable')
const { sunoTaskId, songIndex } = docSnap.data()
if (!sunoTaskId) throw new Error('TaskId manquant')
const { songSunoTaskId, sunoAudioId, songIndex } = docSnap.data()
if (!songSunoTaskId) throw new Error('TaskId de la piste manquant')
if (!sunoAudioId) throw new Error('AudioId Suno manquant')
if (songIndex === undefined || songIndex < 0) throw new Error('musicIndex invalide')
console.log('🔎 getSunoTimestamps', { sunoTaskId, songIndex })
console.log('🔎 getSunoTimestamps', { songSunoTaskId, sunoAudioId, songIndex })
const response = await axios.post(
`${SUNO_API_BASE}${SUNO_TIMESTAMPED_LYRICS_PATH}`,
{ taskId: sunoTaskId, musicIndex: songIndex },
{ taskId: songSunoTaskId, audioId: sunoAudioId },
{
headers: {
'Content-Type': 'application/json',
@@ -446,11 +447,32 @@ async function getSunoTimestamps(projectId) {
}
)
const dataToReturn = response.data?.data || response.data || {}
if (response.data?.code !== 200) {
throw new Error(response.data?.msg || 'Récupération des timestamps refusée par Suno')
}
const dataToReturn = response.data?.data
if (!Array.isArray(dataToReturn?.alignedWords) || dataToReturn.alignedWords.length === 0) {
throw new Error('Aucune parole synchronisée retournée par Suno')
}
const failedWordCount = dataToReturn.alignedWords.filter(
(word) => word?.success === false
).length
const hootCer = Number(dataToReturn.hootCer)
await refList.projects.doc(projectId).set(
{
musicTimestamps: { [songIndex]: dataToReturn },
lyricsSyncStatus: 'READY',
lyricsSyncError: FieldValue.delete(),
lyricsSyncDiagnostics: {
alignedWordCount: dataToReturn.alignedWords.length,
failedWordCount,
successfulWordRatio:
(dataToReturn.alignedWords.length - failedWordCount) /
dataToReturn.alignedWords.length,
hootCer: Number.isFinite(hootCer) ? hootCer : null,
},
updatedAt: FieldValue.serverTimestamp(),
},
{ merge: true }
@@ -459,6 +481,19 @@ async function getSunoTimestamps(projectId) {
return { success: true }
} catch (error) {
console.error('❌ getSunoTimestamps Error:', error.message)
if (projectId) {
await refList.projects
.doc(projectId)
.set(
{
lyricsSyncStatus: 'FAILED',
lyricsSyncError: error.message,
updatedAt: FieldValue.serverTimestamp(),
},
{ merge: true }
)
.catch(() => {})
}
return {
success: false,
error: { message: error.message, type: 'INTERNAL_ERROR' },