Spaces:
Running
Running
document.addEventListener('DOMContentLoaded', () => { | |
const urlInput = document.getElementById('youtube-url'); | |
const summaryLengthInput = document.getElementById('summary-length'); | |
const summarizeBtn = document.getElementById('summarize-btn'); | |
const transcriptOutput = document.getElementById('transcript-output'); | |
const summaryOutput = document.getElementById('summary-output'); | |
const loadingDiv = document.getElementById('loading'); | |
const errorDiv = document.getElementById('error-message'); | |
// Liste de mots vides (français, à étendre) | |
// Source simple, pour une meilleure qualité, utiliser une liste plus complète | |
const STOP_WORDS_FR = new Set([ | |
"a", "afin", "ah", "ai", "aie", "aient", "aies", "ailleurs", "ainsi", "ait", | |
"alors", "au", "aucun", "aucune", "aujourd", "aujourd'hui", "auquel", "aura", | |
"aurai", "auraient", "aurais", "aurait", "auras", "aurez", "auriez", "aurions", | |
"aurons", "auront", "aussi", "autre", "autres", "autrui", "aux", "auxquelles", | |
"auxquels", "avaient", "avais", "avait", "avant", "avec", "avez", "aviez", | |
"avions", "avoir", "avons", "ayant", "ayez", "ayons", "b", "bah", "beaucoup", | |
"bien", "bon", "c", "ça", "car", "ce", "ceci", "cela", "celle", "celle-ci", | |
"celle-là", "celles", "celles-ci", "celles-là", "celui", "celui-ci", "celui-là", | |
"cent", "cents", "cependant", "certain", "certaine", "certaines", "certains", | |
"ces", "cet", "cette", "ceux", "ceux-ci", "ceux-là", "chacun", "chacune", | |
"chaque", "cher", "chère", "chères", "chers", "chez", "ci", "cinq", "cinquante", | |
"cinquième", "comme", "comment", "d", "dans", "de", "debout", "dedans", "dehors", | |
"delà", "depuis", "dernier", "dernière", "dernières", "derniers", "des", "dès", | |
"deux", "deuxième", "devant", "devers", "devra", "devrai", "devraient", "devrais", | |
"devrait", "devras", "devrez", "devriez", "devrions", "devrons", "devront", " διαφορετικα ", | |
"dix", "dix-huit", "dix-neuf", "dix-sept", "dixième", "donc", "dont", "douze", | |
"douzième", "du", "dû", "duquel", "durant", "e", "eh", "elle", "elle-même", | |
"elles", "elles-mêmes", "en", "encore", "enfin", "entre", "envers", "environ", | |
"es", "ès", "est", "et", "etant", "étaient", "étais", "était", "étant", "etc", | |
"été", "êtes", "être", "eu", "eue", "eues", "eurent", "eus", "eusse", "eussent", | |
"eusses", "eussiez", "eussions", "eut", "eût", "eûmes", "eûtes", "eux", "eux-mêmes", | |
"f", "faire", "fais", "faisaient", "faisais", "faisait", "faisant", "faisons", | |
"fait", "faites", "faudra", "faudrait", "faut", "fi", "flac", "floc", "fois", | |
"font", "force", "fors", "g", "gens", "h", "ha", "hé", "hein", "hélas", "hem", | |
"hep", "hi", "ho", "holà", "hop", "hormis", "hors", "hou", "houp", "hue", "hui", | |
"huit", "huitième", "hum", "hurrah", "i", "ici", "il", "ils", "j", "j'", "je", | |
"jusqu'", "jusqu'au", "jusqu'aux", "jusqu'à", "jusque", "k", "l", "la", "là", | |
"laquelle", "le", "lequel", "les", "lès", "lesquelles", "lesquels", "leur", | |
"leurs", "lez", "loin", "longtemps", "lors", "lorsque", "lui", "lui-même", "m", | |
"ma", "maint", "maintenant", "mais", "malgré", "me", "même", "mêmes", "merci", | |
"mes", "mien", "mienne", "miennes", "miens", "mille", "mince", "mine", "moi", | |
"moi-même", "moins", "mon", "mot", "moyennant", "n", "na", "ne", "néanmoins", | |
"neuf", "neuvième", "ni", "nombreuses", "nombreux", "non", "nos", "notre", | |
"nôtre", "nôtres", "nous", "nous-mêmes", "nul", "o", "ô", "où", "oui", "on", | |
"ont", "onze", "onzième", "or", "ou", "où", "outre", "p", "par", "parce", "parmi", | |
"partant", "particulièrement", "pas", "passé", "pendant", "personne", "peu", | |
"peut", "peuvent", "peux", "pf", "pff", "pfi", "pfu", "pif", "plein", "plus", | |
"plusieurs", "plutôt", "pour", "pourquoi", "pourra", "pourrai", "pourraient", | |
"pourrais", "pourrait", "pourras", "pourrez", "pourriez", "pourrions", "pourrons", | |
"pourront", "pouvait", "pouvez", " pouvions ", "pouvons", "premier", "première", | |
"premièrement", "près", "presque", "prouf", "psitt", "pu", "puis", "puisque", | |
"q", "qu'", "quand", "quant", "quanta", "quant-à-soi", "quarante", "quatorze", | |
"quatre", "quatre-vingt", "quatre-vingt-dix", "quatre-vingt-onze", "quatre-vingt-un", | |
"quatrième", "quatrièmement", "que", "quel", "quelconque", "quelle", "quelles", | |
"quelqu'un", "quelque", "quelques", "quels", "qui", "quiconque", "quinze", | |
"quoi", "quoique", "r", "revoici", "revoilà", "rien", "s", "sa", "sacrebleu", | |
"sans", "sapristi", "sauf", "se", "seize", "selon", "sept", "septième", "sera", | |
"serai", "seraient", "serais", "serait", "seras", "serez", "seriez", "serions", | |
"serons", "seront", "ses", "seulement", "si", "sien", "sienne", "siennes", | |
"siens", "sinon", "six", "sixième", "soi", "soi-même", "soient", "sois", "soit", | |
"soixante", "sommes", "son", "sont", "sous", "stop", "suis", "suite", "sur", | |
"surtout", "t", "ta", "tac", "tandis", "tant", "tardivement", "te", "tel", | |
"telle", "telles", "tels", "tenant", "tes", "tic", "tien", "tienne", "tiennes", | |
"tiens", "toc", "toi", "toi-même", "ton", "tos", "tôt", "toute", "toutefois", | |
"toutes", "tous", "tout", "treize", "trente", "très", "trois", "troisième", | |
"troisièmement", "trop", "tu", "u", "un", "une", "unes", "uns", "v", "va", "vais", | |
"valeur", "vas", "vé", "vers", "via", "vif", "vifs", "vingt", "vivat", "vive", | |
"vives", "voici", "voilà", "vont", "vos", "votre", "vôtre", "vôtres", "vous", | |
"vous-mêmes", "vs", "vu", "w", "x", "y", "z", "zut", "alors", "au", "aucuns", "aussi", | |
"autre", "avant", "avec", "avoir", "bon", "car", "ce", "cela", "ces", "ceux", | |
"chaque", "ci", "comme", "comment", "dans", "des", "du", "dedans", "dehors", | |
"depuis", "deux", "devrait", "doit", "donc", "dos", "droite", "début", "elle", | |
"elles", "en", "encore", "essai", "est", "et", "eu", "fait", "faites", "fois", | |
"font", "force", "haut", "hors", "ici", "il", "ils", "je", "juste", "la", "le", | |
"les", "leur", "là", "ma", "maintenant", "mais", "mes", "mine", "moins", "mon", | |
"mot", "même", "ni", "nommés", "notre", "nous", "nouveaux", "ou", "où", "par", | |
"parce", "parole", "pas", "personnes", "peut", "peu", "pièce", "plupart", "pour", | |
"pourquoi", "quand", "que", "quel", "quelle", "quelles", "quels", "qui", "sa", | |
"sans", "ses", "seulement", "si", "sien", "son", "sont", "sous", "soyez", "sujet", | |
"sur", "ta", "tandis", "tellement", "tels", "tes", "ton", "tous", "tout", "trop", | |
"très", "tu", "valeur", "voie", "voient", "vont", "vos", "votre", "vous", "vu", | |
"ça", "étaient", "état", "étions", "été", "être", "pour", "que", "qui", "il", "elle", "on", "y" | |
]); | |
summarizeBtn.addEventListener('click', async () => { | |
const url = urlInput.value.trim(); | |
const numSentences = parseInt(summaryLengthInput.value, 10); | |
if (!url) { | |
showError("Veuillez entrer une URL YouTube."); | |
return; | |
} | |
if (isNaN(numSentences) || numSentences < 1) { | |
showError("Veuillez entrer un nombre de phrases valide pour le résumé."); | |
return; | |
} | |
showLoading(true); | |
hideError(); | |
transcriptOutput.innerHTML = "<p>Récupération de la transcription...</p>"; | |
summaryOutput.innerHTML = "<p>En attente de la transcription...</p>"; | |
try { | |
const response = await fetch(`/get-transcript?url=${encodeURIComponent(url)}`); | |
const data = await response.json(); | |
if (!response.ok) { | |
// Afficher l'erreur détaillée si disponible avec la solution si fournie | |
let errorMessage = data.error || `Erreur HTTP: ${response.status}`; | |
if (data.details) { | |
errorMessage += ` Détails: ${data.details}`; | |
} | |
if (data.solution) { | |
errorMessage += `\n💡 Solution: ${data.solution}`; | |
} | |
throw new Error(errorMessage); | |
} | |
const fullTranscript = data.transcript; | |
if (!fullTranscript || fullTranscript.trim() === "") { | |
showError("La transcription est vide ou n'a pas pu être récupérée."); | |
transcriptOutput.innerHTML = "<p>Aucune transcription reçue.</p>"; | |
summaryOutput.innerHTML = "<p>Impossible de résumer sans transcription.</p>"; | |
showLoading(false); | |
return; | |
} | |
transcriptOutput.textContent = fullTranscript; | |
// "IA" locale : résumé | |
const summary = await summarizeText(fullTranscript, numSentences); | |
summaryOutput.textContent = summary; | |
} catch (err) { | |
console.error("Erreur détaillée dans le processus :", err); | |
showError(`Erreur: ${err.message}`); | |
transcriptOutput.innerHTML = "<p>Échec de la récupération.</p>"; | |
summaryOutput.innerHTML = "<p>Échec du résumé.</p>"; | |
} finally { | |
showLoading(false); | |
} | |
}); | |
function showLoading(isLoading) { | |
loadingDiv.style.display = isLoading ? 'block' : 'none'; | |
} | |
function showError(message) { | |
errorDiv.innerHTML = message.replace(/\n/g, '<br>'); | |
errorDiv.style.display = 'block'; | |
} | |
function hideError() { | |
errorDiv.style.display = 'none'; | |
} | |
// --- Fonctions de résumé (l'"IA" locale) --- | |
function tokenize(text) { | |
// Simpliste : enlève la ponctuation basique et met en minuscule | |
return text.toLowerCase().replace(/[^\w\s'-]|_/g, "").replace(/\s+/g, " ").trim().split(' '); | |
} | |
function getSentences(text) { | |
// Segmentation basique par point, point d'interrogation, point d'exclamation. | |
// Peut être amélioré avec des expressions régulières plus complexes. | |
// Nettoie les timestamps typiques comme [00:00:00] ou (00:00:00) | |
const cleanedText = text.replace(/\[\d{2}:\d{2}:\d{2}\]/g, '') | |
.replace(/\(\d{2}:\d{2}:\d{2}\)/g, ''); | |
return cleanedText.split(/[.!?]+\s*/).filter(s => s.trim().length > 0).map(s => s.trim()); | |
} | |
function calculateWordFrequencies(words) { | |
const freq = {}; | |
words.forEach(word => { | |
if (!STOP_WORDS_FR.has(word) && word.length > 2) { // Ignore les mots vides et très courts | |
freq[word] = (freq[word] || 0) + 1; | |
} | |
}); | |
return freq; | |
} | |
function scoreSentences(sentences, wordFrequencies) { | |
const sentenceScores = []; | |
sentences.forEach((sentence, index) => { | |
const wordsInSentence = tokenize(sentence); | |
let score = 0; | |
wordsInSentence.forEach(word => { | |
if (wordFrequencies[word]) { | |
score += wordFrequencies[word]; | |
} | |
}); | |
// On pourrait ajouter un bonus pour la position (ex: premières phrases) | |
// if (index < 3) score *= 1.2; // Bonus pour les 3 premières phrases | |
sentenceScores.push({ sentence: sentence, score: score, index: index }); | |
}); | |
return sentenceScores; | |
} | |
async function summarizeText(text, numSentences) { | |
if (!text || text.trim() === "") return "Le texte fourni est vide."; | |
try { | |
// 1. Découper le texte en phrases | |
const sentences = getSentences(text); | |
if (sentences.length <= numSentences) { | |
return text; // Si le texte est déjà plus court que le résumé demandé, retourner tout | |
} | |
// 2. Tokeniser le texte pour l'analyse des fréquences | |
const words = tokenize(text); | |
// 3. Calculer les fréquences des mots (sauf mots vides) | |
const wordFrequencies = calculateWordFrequencies(words); | |
// 4. Calculer un score pour chaque phrase basé sur les mots importants | |
const sentenceScores = scoreSentences(sentences, wordFrequencies); | |
// 5. Trier les phrases par score (importance) décroissant | |
sentenceScores.sort((a, b) => b.score - a.score); | |
// 6. Prendre les N phrases les plus importantes | |
const topSentences = sentenceScores.slice(0, numSentences); | |
// 7. Retrier les phrases selon leur position originale dans le texte | |
topSentences.sort((a, b) => a.index - b.index); | |
// 8. Former le résumé final | |
const summary = topSentences.map(item => item.sentence).join('. '); | |
return summary + '.'; | |
} catch (error) { | |
console.error("Erreur lors de la création du résumé:", error); | |
return "Une erreur s'est produite lors de la création du résumé."; | |
} | |
} | |
}); |