Ce document fait office de référence technique et de tutoriel pour comprendre l'architecture, le fonctionnement et la structure du projet YoutubeParty. Il s'adresse aux développeurs ainsi qu'aux agents d'IA pour faciliter la maintenance et l'évolution de la base de code.
YoutubeParty est un système de jukebox vidéo / karaoké collaboratif conçu pour les soirées.
- Un Écran Principal (généralement un PC branché à une TV ou un vidéoprojecteur) diffuse les vidéos.
- Des Télécommandes Mobiles (accessibles sur smartphone via un QR Code affiché sur l'écran principal) permettent aux invités d'ajouter des musiques à la file d'attente, de réagir en temps réel ou de voter.
graph TD
subgraph Clients
TV[Écran TV Principal / screen.html]
M1[Mobile Invité 1 / mobile.html]
M2[Mobile Invité 2 / mobile.html]
MM[Mobile Master / mobile.html]
end
subgraph Serveur Node.js
S_Express[Serveur Express API & Fichiers Statics]
S_SIO[Socket.io Realtime Sync]
YT_Scraping[YouTube Search & API Resolution]
SB_Proxy[Proxy SponsorBlock Resilient]
end
M1 -- HTTP / API Search --> S_Express
M2 -- HTTP / API Search --> S_Express
TV -- WebSockets events --> S_SIO
M1 -- WebSockets events --> S_SIO
M2 -- WebSockets events --> S_SIO
MM -- WebSockets events --> S_SIO
S_Express -- Request Proxy --> SB_Proxy
S_Express -- HTML Scraping --> YT_Scraping
YoutubeParty/
├── .gitignore # Règles d'exclusion Git (exclut node_modules, masters.json, history.json, etc.)
├── masters.json # Sauvegarde persistante des User IDs disposant du rôle Master
├── history.json # Sauvegarde persistante de l'historique global de lecture et des statistiques veto
├── package.json # Dépendances Node.js (express, socket.io, qrcode)
├── server.js # Serveur principal Node.js (gestion d'état, WebSockets et API)
├── start.bat # Script Windows de lancement rapide (serveur + ouverture TV)
└── public/ # Ressources frontend (HTML, JS, CSS)
├── mobile.html # Interface télécommande pour smartphones
├── mobile.js # Logique applicative de la télécommande
├── screen.html # Interface de l'écran TV (lecteur YouTube incrusté)
├── screen.js # Logique applicative de l'écran TV
└── style.css # Système de design global (Glassmorphism & Neon)
Développé avec Express et Socket.io, il gère l'état de l'application en mémoire vive et sur disque :
- Playlist / File d'attente (
queue) : Tableau des pistes à suivre. - Historique de session (
history) : Les 30 dernières vidéos jouées pour permettre un retour arrière. - Historique global persistant (
history.json) : Sauvegarde continue de toutes les chansons jouées (y compris le marquage des vetos) pour alimenter le podium de soirée et les classements. - Clients connectés (
clients) : Liste des sockets connectées, enrichie de leur pseudo, avatar émoji, rôle, et liste de favoris synchronisée. - Cache de recherche (
searchCache) : Stockage en mémoire (Map, max 200 entrées, TTL de 24h) des requêtes de recherche YouTube pour accélérer les chargements et éviter d'être banni par YouTube. - Veto (
vetoVotes) : Ensemble d'identifiants uniques d'utilisateurs ayant voté pour zapper la chanson en cours.
- Intègre l'API YouTube Iframe Player pour contrôler la lecture, le volume et le statut (lecture/pause/fin).
- Débloque le son de manière invisible au premier clic utilisateur (bypass des règles d'Autoplay des navigateurs modernes).
- Gère l'affichage dynamique de la veille (Lobby vide sans connecté vs. Lobby actif avec grille d'invités connectés sous forme d'avatars flottants).
- Affiche un menu d'administration permettant de promouvoir un utilisateur au rôle de Master ou d'activer le mode Fair-Play.
- Processus de connexion nécessitant la saisie d'un pseudo et le choix d'un avatar émoji (pré-sélectionné au hasard et modifiable à tout moment).
- Raccourci d'auto-connexion : si des identifiants existent dans le stockage local (
localStorage), l'écran d'enregistrement est masqué et la connexion socket est établie instantanément. Le profil reste éditable en cliquant sur le badge utilisateur. - Trois sections dans l'onglet Suggestions : suggestions personnalisées (selon votre artiste préféré), classiques de la soirée (histoire globale) et mix des favoris des autres invités connectés.
- Une interface dynamique adaptant ses boutons en fonction du rôle de l'utilisateur (les boutons administrateur/master ne sont visibles et interactifs que pour le rôle
Master).
Pour éviter l'obligation d'avoir une clé API YouTube v3 (sujette à des quotas stricts), le serveur implémente une stratégie de recherche à deux niveaux :
- Recherche par scraping natif : Le serveur effectue une requête HTTP sur YouTube, simulant un navigateur, et extrait les données de
ytInitialDatavia une expression rationnelle multi-lignes. Un cookie de consentement (CONSENT=YES...) est transmis pour contourner les popups de RGPD. - Résolution directe d'URL : Si l'utilisateur colle un lien ou un ID vidéo direct, le serveur utilise l'API publique OEmbed de YouTube (
https://www.youtube.com/oembed) pour récupérer le titre et la miniature instantanément. - Clé API optionnelle : Si
YOUTUBE_API_KEYest configurée dans le fichier, elle est interrogée en priorité.
Pour éliminer les intros parlées ou les publicités intégrées aux clips, l'écran TV interroge un endpoint proxy local /api/sponsorblock/:videoId.
Le serveur Node.js interroge en cascade plusieurs miroirs SponsorBlock (sponsor.ajay.app, sponsorblock.kavin.rocks, etc.) pour assurer une haute disponibilité. Si des segments de type music_offtopic ou sponsor sont détectés, l'écran TV effectue un saut (seekTo) automatique à la fin du segment concerné en affichant une notification discrète.
- Guest : Rôle par défaut de tout nouvel invité. Peut ajouter des vidéos, envoyer des réactions et voter pour le veto.
- Master : Rôle d'administration de la soirée. Peut zapper (skip/previous), réordonner la file d'attente, ajuster le volume, activer le mode Fair-Play et supprimer n'importe quel clip.
- Persistance : Lorsqu'un mobile est promu Master depuis le panneau d'administration de l'écran principal, son
userId(généré aléatoirement et stocké dans lelocalStoragedu smartphone) est enregistré dans le fichiermasters.jsonpour conserver ses droits même s'il actualise sa page ou se déconnecte temporairement.
Pour éviter qu'un seul invité ne monopolise la soirée en ajoutant 15 chansons à la suite, le mode Fair-Play (reorderFairPlay dans le serveur) réorganise dynamiquement la file d'attente à chaque nouvel ajout.
L'algorithme regroupe les chansons par utilisateur (addedById) et reconstruit la file d'attente en alternant les tours de table (Chanson 1 de User A, puis Chanson 1 de User B, puis Chanson 2 de User A, etc.).
Si aucun Master n'est disponible ou si la majorité n'aime pas le morceau actuel :
- Les invités peuvent cliquer sur "VETO".
- Le seuil de validation est calculé de manière dynamique :
Math.ceil(Nombre_d_invités_actifs / 2). - Dès que le nombre de votes veto atteint ce seuil, la vidéo en cours est immédiatement coupée et la suivante démarre.
L'interface TV a été optimisée pour réduire les distractions visuelles et offrir une immersion totale :
- Cartes repliables : Les blocs "À suivre" et "QR Code" démarrent repliés (pastilles compactes). Ils peuvent être dépliés d'un simple clic.
- Persistance du QR Code : Si le QR code est déplié, il reste visible en permanence à l'écran, même lorsque l'overlay de contrôle principal et le pointeur de la souris s'estompent. S'il est plié, il disparaît proprement avec l'overlay.
- Silencing des commandes distantes : Les commandes envoyées depuis les mobiles (seek, volume, play/pause, skip) ne font plus clignoter ni apparaître l'overlay complet sur la TV. Seules les notifications importantes (toasts) s'affichent temporairement.
Dans les 30 dernières secondes d'une chanson, un toast élégant apparaît en bas à droite de la TV pour annoncer le prochain morceau (miniature, titre et compte à rebours).
- Positionnement dynamique : Il est ancré au coin inférieur droit de l'écran (
bottom: 3rem). Si les contrôles de la TV s'affichent, il remonte fluidement àbottom: 12rempour laisser place au bandeau de contrôle sans aucune collision.
- Clic dans le vide : Cliquer n'importe où dans le vide sur la TV met en pause ou relance la vidéo (comportement identique au lecteur YouTube officiel).
- Raccourcis clavier : La touche
Espacecontrôle Play/Pause, tandis que les touchesFlèche DroiteetFlèche Gauchepermettent de zapper au morceau suivant ou précédent. - Masquage du curseur : Le pointeur de la souris disparaît automatiquement après 3 secondes d'inactivité pour une expérience visuelle épurée (style cinéma / TV connectée).
- Lors de sa connexion, chaque invité choisit un émoji en guise d'avatar (pré-sélectionné au hasard).
- L'avatar est persisté localement sur le smartphone et synchronisé avec le serveur.
- Il s'affiche sur la TV (liste d'administration, chat marquee, toast de lancement de chanson, cartes lobby) et sur le mobile (badge utilisateur cliquable pour l'éditer, playlist, chat, podium).
- Lobby Vide (0 connecté) : Grand QR Code au centre avec 3 étapes explicatives de connexion.
- Lobby Actif (1+ connecté, pas de musique) : Le QR Code est réduit sur le côté. Une grille d'invités connectés sous forme d'avatars flottants est générée dynamiquement avec des micro-animations en apesanteur (
float-guest). Les cartes distinguent visuellement les administrateurs (👑 Master) des invités (👤 Guest).
- Recommandé pour vous : Le mobile analyse vos favoris locaux pour extraire votre artiste préféré et interroge YouTube pour vous proposer une sélection sur-mesure.
- Les Classiques de la soirée : Listes de titres réels les plus écoutés, extraits de l'historique de lecture sans aucune chanson factice.
- Le Mix des Invités : Les favoris des invités connectés dans la pièce sont envoyés via l'événement
sync_favoriteset fusionnés pour que chacun puisse piocher dans les coups de cœur des autres.
connection_established: Transmet lesocketIdaffecté au client mobile lors de sa connexion.role_updated: Notifie un client mobile de son rôle actuel (GuestouMaster).state_update: Transmet l'état complet du serveur (liste des clients connectés, file d'attente, état de lecture, paramètres veto et fair-play).queue_updated: Diffuse uniquement la playlist mise à jour et la vidéo active.tv_command: Transmet des commandes d'exécution à l'Écran TV (load_video,play,pause,volume,show_idle).emoji_reaction: Transmet un émoji réaction à afficher sur la TV.progress_update: Relaye la progression temporelle de la vidéo en cours vers les smartphones.
join: Enregistre le client ({ type: 'screen' }ou{ type: 'mobile', nickname, userId }).add_to_queue/add_to_queue_first: Demande d'ajout d'une vidéo (en fin ou en tête de file).role_change: Demande de modification de rôle (émis par la TV).player_command: Envoie une instruction de contrôle (play,pause,skip,previous,volume,remove,seek).reorder_queue: Modifie l'ordre de la file d'attente.vote_veto: Soumet ou retire un vote de veto.toggle_fairplay: Active ou désactive le mode Fair-Play.emoji_reaction: Envoie une réaction.sync_favorites: Transmet la liste des favoris personnels de l'invité connectés au serveur.progress_update: Transmet la position actuelle du lecteur (émis par la TV).video_started/video_ended: Confirme le statut de lecture de la vidéo en cours (émis par la TV).
- Node.js (version 16 ou supérieure recommandé)
- Clonez ou copiez le répertoire du projet.
- Installez les dépendances requises :
npm install
- Le plus simple (Windows) : Double-cliquez sur le raccourci
YoutubeParty.lnkà la racine du projet pour lancer le serveur et ouvrir automatiquement l'application dans votre navigateur. - Via Script (Windows) : Double-cliquez sur
start.bat. Ce script lance le serveur et ouvrehttp://localhost:3000/screen.htmlaprès 2 secondes. - Via Terminal :
Accédez ensuite manuellement à :
npm start
- Écran TV :
http://localhost:3000/screen.html - Mobile :
http://<IP_LOCALE>:3000/mobile.html(ou via le QR Code affiché sur l'écran TV)
- Écran TV :
L'application arbore une identité moderne conçue pour une ambiance de fête nocturne :
- Thème : Dark-mode premium avec des accents néons dynamiques (dégradé violet/cyan via
--gradient-neon). - Effets visuels : Utilisation intensive du glassmorphism (panneaux semi-transparents floutés via
backdrop-filter: blur(24px)et bordures subtiles). - Animations : Transitions douces lors des interactions, effets de pulsation lumineuse sur les alertes (veto) et envolées d'émojis flottants (
@keyframes floatEmoji). - Polices : Sans-serif moderne (inter/system) avec des indicateurs de temps à chasse fixe (monospace) pour éviter les sauts visuels sur les timers.