Skip to main content

Pla d'Importació de Balls des de YouTube

Estat: ✅ Implementat (v1)
Data última actualització: 2025-01-28
Prioritat: Alta

Progrés

ComponentEstat
Backend DTOs✅ Completat
YouTubeService✅ Completat
DanceDescriptionParser✅ Completat
DanceImportService✅ Completat
DanceImportController✅ Completat
Frontend YouTubeImportPage✅ Completat
Ruta i menú✅ Completat
Tests unitaris✅ Completat
Tests d'integració⏳ Pendent

Objectiu

Permetre a un admin importar un ball a partir d'un vídeo de YouTube, extraient automàticament les dades de la descripció i facilitant la creació del ball amb les seves relacions (cançó, coreògrafs, vídeo tutorial).

Flux General

┌─────────────────────────────────────────────────────────────────────┐
│ IMPORTACIÓ BALL DES DE YOUTUBE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. ENTRADA │
│ • URL YouTube │
│ • Títol del vídeo │
│ • Descripció (enganxada manualment / API futur) │
│ │
│ 2. ANÀLISI (backend) │
│ • Parseja descripció → extreu camps │
│ • Cerca duplicats per nom │
│ • Cerca coreògraf existent │
│ │
│ 3. DETECCIÓ DUPLICATS │
│ ├─ Si duplicat ALTA probabilitat: │
│ │ → Mostra ball existent │
│ │ → Opcions: [Afegir vídeo] [Crear nou] [Cancel·lar] │
│ │ │
│ └─ Si no duplicat o baixa probabilitat: │
│ → Mostra draft editable │
│ │
│ 4. DRAFT EDITABLE │
│ • Nom ball (detectat) │
│ • Counts, Walls, Level (manual o detectat) │
│ • Any origen (detectat) │
│ • Coreògraf (find-or-create) │
│ • Cançó (selector iTunes) │
│ • Tipus vídeo (Tutorial/Demo/Música) │
│ • Descripció ball (si detectada) │
│ • Especificació tècnica (Parts, Sequence...) │
│ │
│ 5. CONFIRMACIÓ → Inserts a BD │
│ • Choreographer (si nou) │
│ • Dance │
│ • DanceSong (PRIMARY) │
│ • DanceChoreographer │
│ • Link (YOUTUBE_*) │
│ • LineDanceSpec (amb sourceText) │
│ │
│ 5b. AFEGIR VÍDEO (si ball ja existeix) │
│ • Només Link (YOUTUBE_*) │
│ │
└─────────────────────────────────────────────────────────────────────┘

Control de Duplicats

Lògica de detecció

CoincidènciaProbabilitat Duplicat
Nom + Coreògraf + Cançó🔴 ALTA (95%) - Gairebé segur duplicat
Nom + Coreògraf🟠 MITJANA-ALTA (80%) - Probablement duplicat
Nom + Cançó🟡 MITJANA (60%) - Podria ser versió diferent
Només Nom🟢 BAIXA (30%) - Podria ser ball diferent

Controls implementats

ControlImplementació
Duplicat BallCerca per nom similar + comparació coreògraf/cançó
Duplicat Cançó✅ Ja controlat per iTunes import (trackViewUrl)
Duplicat Coreògraf✅ Find-or-create per nom normalitzat
Duplicat LinkComprovar si URL YouTube ja existeix

Mapeig de Camps

Camp Descripció YouTubeCamp LDPEntitatNotes
Títol vídeonameDancePrincipal
"Choreographed by X"nameChoreographerFind-or-create
"Cançó - Artista"cerca iTunesSongSelector existent
Data (YYYY-MM-DD)originYearDanceNomés any
WallswallsDanceManual si no detectat
LevellevelCodeDanceManual si no detectat
CountscountsDanceManual si no detectat
Part A=32c, Sequence...sourceTextLineDanceSpecText complet
Descripció del balldescriptionDanceSi detectada
URL YouTubeurlLinkYOUTUBE_TEACH/DANCE/MUSIC

Tipus de Vídeo (LinkKind)

  • YOUTUBE_TEACH - Tutorial / Classe
  • YOUTUBE_DANCE - Demo / Ball
  • YOUTUBE_MUSIC - Vídeo musical / Cançó oficial

Patrons de Parsing

# Coreògraf
Choreographed by (.+)

# Cançó - Artista
^(.+)\s*-\s*(.+)$ (línia amb format "Títol - Artista")

# Àlbum
Album\s*[-:]\s*(.+?)[-]?(\d{4})?

# Data
\d{4}-\d{2}-\d{2}

# Counts/Walls (si surten)
(\d+)\s*[Cc]ounts?
(\d+)\s*[Ww]alls?

# Level (si surt)
[Ll]evel[:.\s]*(\w+)

# Especificació tècnica
Part [AB]=\d+c.*
Sequence:.*

Components a Implementar

Backend

ComponentDescripció
DanceImportControllerEndpoints /api/admin/dance-import/*
DanceDescriptionParserServei per parsejar descripcions
DanceImportServiceLògica de negoci (duplicats, find-or-create)

DTOs

record DanceImportParseRequest(
String youtubeUrl,
String videoTitle,
String description
)

record DanceImportAnalysisDto(
DanceImportDraftDto draft,
List<DuplicateCandidateDto> duplicateCandidates,
DuplicateRisk duplicateRisk
)

record DanceImportConfirmRequest(
String youtubeUrl,
String videoType,
String danceTitle,
Integer counts,
Integer walls,
String levelCode,
Integer originYear,
String description,
String techSpec,
String choreographerName,
String choreographerCountry,
Long existingChoreographerId,
Long songId,
Long existingDanceId // null = crear nou
)

Frontend

ComponentDescripció
DanceImportPagePàgina principal d'importació
Integració iTunesReutilitza selector de cançons existent

Què es crea a la BD

OrdreTaulaAccióDades
1choreographersINSERT (si nou)name, country, listingStatus=INFORMATIVE
2dancesINSERTname, counts, walls, level_id, origin_year, description
3dance_choreographerINSERTdance_id, choreographer_id
4dance_songINSERTdance_id, song_id, role=PRIMARY
5linksINSERTkind=YOUTUBE_*, url, dance_id
6line_dance_specsINSERTdance_id, status=DRAFT, sourceText

API YouTube (Futur)

Quan es tingui API Key:

youtube:
api-key: ${YOUTUBE_API_KEY:}
enabled: ${YOUTUBE_API_ENABLED:false}

Endpoint: GET https://www.googleapis.com/youtube/v3/videos?part=snippet&id={videoId}&key={API_KEY}

Retorna: snippet.title, snippet.description, snippet.channelTitle, snippet.publishedAt

Fases d'Implementació

Fase 1: MVP (sense API YouTube)

  • Backend: DTOs i endpoints
  • Backend: Parser de descripcions
  • Backend: Detecció duplicats
  • Backend: Find-or-create coreògrafs
  • Frontend: Pàgina d'importació
  • Tests

Fase 2: Millores

  • API YouTube per fetch automàtic
  • Millora del parser (més patrons)
  • Historial d'importacions
  • Importació en lot