# Kravspecifikation: Matchning av lokala videofiler mot WCX-databasen ## 1. Syfte Funktionen ska identifiera vilken post i WCX-databasen en lokal videofil sannolikt motsvarar. Databasen innehåller filmens kanoniska namn enligt siten. Namnet består alltid av ett eller flera personnamn och inga andra beskrivande ord. Lokala filnamn är däremot ofta inkonsekventa och kan innehålla: * sammanfogade namn * understreck eller andra separatorer * upprepade namn * felstavningar * extra beskrivande ord * tekniska eller innehållsrelaterade suffix * flera personnamn * inkonsekvent användning av stora och små bokstäver Exempel: ```text Alyn_Borav_AlynBorav.mp4 AngeliqueLapiedra_ScarlettLapiedra.mp4 BrendaBoop_Interwiev_Fisting.mp4 Busty_Slovakian_Ilona_On_Bed.mp4 Eden_Ivy_EdenIvy_DP.mp4 Version_AngelikaFyres_DP.mp4 ``` Dessa ska kunna matchas mot databasnamn som: ```text Alyn Borav Angelique Lapiedra + Scarlett Lapiedra Brenda Boop Ilona Eden Ivy Angelika Fyres ``` Funktionen ska prioritera korrekthet framför täckning. En fil som inte kan identifieras med tillräcklig säkerhet ska lämnas för manuell inspektion. --- ## 2. Grundprinciper Matchningen ska vara konservativ. Funktionen ska inte försöka automatcha varje fil. Den ska klassificera resultatet i tre huvudkategorier: ```text matched ambiguous unmatched ``` Betydelse: * `matched`: en kandidat är tillräckligt stark och tydligt bättre än övriga kandidater * `ambiguous`: en eller flera rimliga kandidater finns, men säkerheten är inte tillräcklig * `unmatched`: ingen rimlig kandidat kunde identifieras En felaktig automatisk match är allvarligare än att en fil lämnas omatchad. --- ## 3. Datakällor Funktionen ska använda följande datakällor. ### 3.1 Aktuella filmposter Från tabellen `movie`: ```text id name duration_seconds ``` Övriga fält kan senare användas, men krävs inte för den första versionen. ### 3.2 Historiska filmposter Från tabellen `movie_history`: ```text movie_id name duration_seconds archived_at change_summary ``` Historiska längder kan användas för att identifiera att en lokal fil motsvarar en äldre version av samma film. ### 3.3 Lokala videofiler För varje fil ska minst följande information läsas: ```text path filename file extension actual duration ``` Den faktiska längden hämtas med `ffprobe`. --- ## 4. Namnmodell Databasfältet `movie.name` innehåller alltid ett eller flera personnamn. Exempel med en person: ```text Alyn Borav Ilona Eden Ivy ``` Exempel med flera personer: ```text Angelique Lapiedra + Scarlett Lapiedra Susanna Melo + Cherry Sweet ``` Plustecknet ska betraktas som separator mellan personer. Varje databaspost ska därför kunna representeras som: ```text movie name list of person names normalized full name normalized person names ``` Exempel: ```text Movie name: Angelique Lapiedra + Scarlett Lapiedra Persons: - Angelique Lapiedra - Scarlett Lapiedra Normalized persons: - angeliquelapiedra - scarlettlapiedra Normalized full name: angeliquelapiedrascarlettlapiedra ``` --- ## 5. Normalisering av namn Filnamn och databasnamn ska normaliseras innan jämförelse. Normaliseringen ska minst: 1. ta bort filändelsen 2. konvertera till gemener 3. ta bort mellanslag 4. ta bort understreck 5. ta bort bindestreck 6. ta bort plustecken 7. ta bort punkter och annan interpunktion 8. normalisera diakritiska tecken 9. behålla bokstäver och siffror Exempel: ```text Alyn_Borav_AlynBorav.mp4 → alynboravalynborav ``` ```text Angelique Lapiedra + Scarlett Lapiedra → angeliquelapiedrascarlettlapiedra ``` ```text CatherineBoss.mp4 → catherineboss ``` ```text Catherine Boss → catherineboss ``` --- ## 6. Matchning av filnamn ### 6.1 Exakt normaliserad delsträng Om ett normaliserat databasnamn förekommer exakt i det normaliserade filnamnet ska detta räknas som en stark signal. Exempel: ```text Fil: Eden_Ivy_EdenIvy_DP.mp4 Normaliserad fil: edenivyedenivydp Databasnamn: Eden Ivy Normaliserat namn: edenivy ``` `edenivy` förekommer två gånger och ska ge en stark matchning. ### 6.2 Upprepade namn Upprepade personnamn i filnamnet ska inte tolkas som flera personer. Exempel: ```text Vanessa_Rodriguez_VanessaRodriguez.mp4 ``` ska fortfarande motsvara personen: ```text Vanessa Rodriguez ``` Upprepning kan däremot stärka matchningen. ### 6.3 Extra ord i filnamnet Extra ord behöver inte tas bort för att exakt delsträngsmatchning ska fungera. Exempel: ```text BrendaBoop_Interwiev_Fisting.mp4 ``` kan matchas mot: ```text Brenda Boop ``` eftersom det normaliserade namnet förekommer intakt i filnamnet. Exempel på vanliga extra ord: ```text DP Group Interview Fisting OralSex TruFun67 Version OnBed PissingInMouth ``` Dessa ska initialt behandlas som okänd extrainformation och inte som del av databasnamnet. ### 6.4 Korta namn Korta namn som exempelvis: ```text Ilona Mia Eva Ana ``` kräver större försiktighet eftersom de kan förekomma som delar av andra ord. För korta namn ska tokenbaserad matchning väga tyngre än ren delsträngsmatchning. ### 6.5 Flera personer Om en databaspost innehåller flera personer ska samtliga namn kunna sökas oberoende av ordning. Exempel: ```text Angelique Lapiedra + Scarlett Lapiedra ``` ska kunna matcha både: ```text AngeliqueLapiedra_ScarlettLapiedra.mp4 ``` och: ```text ScarlettLapiedra_AngeliqueLapiedra.mp4 ``` Matchningen ska därför inte kräva att personerna förekommer i samma ordning som i databasen. ### 6.6 Längsta och mest specifika kandidat Om flera databasnamn matchar ska den mest specifika kandidaten prioriteras. Exempel: ```text Scarlett Knight Scarlett Knight + Anya Shidlerova ``` Fil: ```text ScarlettKnight_AnyaShidlerova.mp4 ``` Posten med båda personerna ska rankas högre. ### 6.7 Exakt personmängd När flera kända personer identifieras i filnamnet ska databaskandidater med exakt samma personmängd prioriteras. Exempel: ```text Filnamn: Susanna_Melo_Cherry_Sweet.mp4 Identifierade personer: - Susanna Melo - Cherry Sweet ``` Följande kandidat ska rankas högre: ```text Susanna Melo + Cherry Sweet ``` än: ```text Susanna Melo ``` --- ## 7. Stavfel och fuzzy matching Filnamn kan innehålla stavfel. Exempel: ```text SusannaMello Susamma_Melo ``` kan sannolikt motsvara: ```text Susanna Melo ``` Fuzzy matching får användas för att skapa kandidater, men ska vara konservativt. I den första versionen gäller: * fuzzy matching får inte ensam leda till automatisk match * fuzzy-resultat ska normalt klassificeras som `ambiguous` * kandidat och orsak ska visas för manuell bedömning Exempel: ```text Filename: SusannaMello.mp4 Candidate: Susanna Melo Status: ambiguous Reason: fuzzy name match ``` Verifierade stavningsvarianter kan senare sparas som alias. Ett alias ska endast registreras efter manuell bekräftelse. --- ## 8. Längd som sekundär signal Videons faktiska längd ska användas för att stärka eller försvaga redan rimliga namnkandidater. Längden ska inte ensam kunna identifiera en film. Exempel: ```text File: Alyn_Borav_AlynBorav.mp4 File duration: 43:00 ``` Kandidater: ```text Alyn Borav Site duration: 43:05 Difference: 5 seconds ``` ```text Alyn Borav + Cherry Sweet Site duration: 1:54:00 Difference: 71 minutes ``` Den första kandidaten ska då få betydligt högre poäng. ### 8.1 Absolut och relativ skillnad Både absolut skillnad och procentuell skillnad ska beräknas. ```text absolute difference = abs(file duration - site duration) relative difference = absolute difference / site duration ``` ### 8.2 Initial poängmodell för längd En första approximation kan vara: ```text ≤ 15 sekunder eller ≤ 1 % mycket stark signal ≤ 60 sekunder eller ≤ 2 % stark signal ≤ 3 minuter eller ≤ 5 % rimlig signal ≤ 10 minuter eller ≤ 10 % svag signal > 10 minuter och > 10 % negativ signal ``` Exakt poängsättning ska kunna justeras efter testning mot verkliga filer. ### 8.3 Längd får inte rädda en dålig namnmatch Exempel: ```text unknown_video.mp4 ``` ska inte automatchas till en film bara för att längden råkar vara nästan identisk. Längd används endast för att diskriminera mellan kandidater som redan har en rimlig namnmatchning. ### 8.4 Klippta och förlängda versioner En större längdskillnad ska inte automatiskt innebära att kandidaten är fel. Filen kan vara: ```text truncated extended edited missing intro missing ending ``` En stark namnmatchning kombinerad med tydlig längdavvikelse ska normalt ge: ```text ambiguous ``` eller en särskild versionsklassificering, inte automatiskt `unmatched`. --- ## 9. Historiska längder Matchningen ska kunna jämföra filens längd mot både aktuell och historisk sitelängd. Exempel: ```text Current site duration: 63:05 Historical duration: 43:05 Local file duration: 43:00 ``` Möjlig slutsats: ```text Filmen matchar sannolikt rätt databaspost men motsvarar en äldre version. ``` Möjliga versionsklassificeringar: ```text current_version_match historical_version_match possible_truncated_version possible_extended_version duration_mismatch unknown_version ``` Historisk längd ska vara en stödjande signal och inte ensam avgöra filmidentiteten. --- ## 10. Kandidatpoäng Varje databaspost ska kunna få en sammanlagd poäng baserad på flera signaler. Exempel på positiva signaler: ```text exakt normaliserat fullständigt namn samtliga personnamn hittade exakt personmängd namnet förekommer flera gånger längden ligger mycket nära aktuell sitelängd längden ligger mycket nära historisk sitelängd stor marginal till kandidat nummer två ``` Exempel på negativa signaler: ```text bara en del av namnet hittades fuzzy matching krävdes filnamnet innehåller ytterligare kända personer databasposten förväntar flera personer men endast en hittas stor skillnad i längd kort och osäker namnträff flera kandidater har nästan samma poäng ``` Poängmodellen ska vara förklarbar. Resultatet ska visa vilka signaler som påverkade poängen. --- ## 11. Säkerhetskrav för automatisk matchning En fil får klassificeras som `matched` endast om: 1. bästa kandidaten uppnår ett fastställt minimikrav 2. kandidaten bygger på en tillräckligt stark namnmatchning 3. kandidaten ligger tydligt före näst bästa kandidat 4. inga motstridiga personsignaler finns 5. eventuell fuzzy matching inte är den enda avgörande signalen Exempel på säker match: ```text Candidate 1: 170 Candidate 2: 45 Margin: 125 ``` Exempel på osäker match: ```text Candidate 1: 92 Candidate 2: 87 Margin: 5 ``` Det senare ska klassificeras som: ```text ambiguous ``` även om förstaplatsen har relativt hög poäng. --- ## 12. Manuell inspektion Filer som klassificeras som `ambiguous` eller `unmatched` ska kunna granskas manuellt. För `ambiguous` ska rapporten visa de bästa kandidaterna. Exempel: ```text Filename: SusannaMello_Cherry.mp4 Status: ambiguous Candidate 1: Susanna Melo + Cherry Sweet Score: 91 Candidate 2: Susanna Melo Score: 86 Reasons: - fuzzy match for Susanna Melo - partial match for Cherry Sweet - candidates have similar scores ``` Manuell granskning ska kunna resultera i: ```text confirmed match rejected candidates verified alias ignored file ``` Manuella beslut ska kunna sparas senare, men första versionen behöver endast rapportera kandidater. --- ## 13. Första versionens omfattning Den första versionen ska vara helt skrivskyddad. Den får: * läsa filer från en katalog * läsa poster från SQLite-databasen * läsa historiska längder * köra `ffprobe` * normalisera filnamn * rangordna kandidater * skriva rapporter Den får inte: * byta namn på filer * flytta filer * radera filer * ändra databasen * automatiskt registrera alias * permanent koppla filer till filmer --- ## 14. Förväntat kommando Scriptet finns i WCX-collection som `scripts/match_filenames.py` och kräver alltid ett explicit `--database`-argument. Exempel: ```bash scripts/match_filenames.py /path/to/video/files \ --database /storage/disk1/WCX/database/wcx.db ``` Alternativt stöd för en textfil med filnamn: ```bash scripts/match_filenames.py \ --database /storage/disk1/WCX/database/wcx.db \ --file-list filenames.txt ``` Möjliga framtida argument: ```text --recursive --limit --output-directory --min-score --min-margin --debug --no-ffprobe ``` --- ## 15. Rapportformat Resultatet bör delas upp i minst tre rapporter: ```text matched.csv ambiguous.csv unmatched.csv ``` ### 15.1 matched.csv Föreslagna kolumner: ```text path filename file_duration_seconds movie_id movie_name site_duration_seconds matched_duration_seconds version_classification score score_margin match_reason ``` ### 15.2 ambiguous.csv Föreslagna kolumner: ```text path filename file_duration_seconds candidate_1_id candidate_1_name candidate_1_score candidate_2_id candidate_2_name candidate_2_score reason ``` ### 15.3 unmatched.csv Föreslagna kolumner: ```text path filename file_duration_seconds best_candidate best_score reason ``` --- ## 16. Konsolutskrift En läsbar konsolrapport ska också kunna visas. Exempel: ```text Alyn_Borav_AlynBorav.mp4 File duration: 43:00 1. Alyn Borav Name score: 120 Duration score: 50 Total: 170 Duration diff: 5 sec 2. Alyn Borav + Cherry Sweet Name score: 65 Duration score: -30 Total: 35 Duration diff: 71 min Result: matched Version: current_version_match ``` Exempel på osäker fil: ```text SusannaMello_Cherry.mp4 File duration: 42:58 1. Susanna Melo + Cherry Sweet Total: 91 2. Susanna Melo Total: 86 Result: ambiguous Reason: fuzzy match and insufficient score margin ``` --- ## 17. Prestanda Filnamnsmatchningen ska kunna genomföras utan att läsa videofilernas innehåll. `ffprobe` ska endast läsa metadata och ska inte omkoda eller spela upp videon. Första versionen behöver inte använda: * fullständiga filhashar * perceptuella videofingeravtryck * bildextraktion * maskininlärning * OCR från videobilder Sådana funktioner kan utvärderas senare för svåra fall. --- ## 18. Framtida utökningar Möjliga senare förbättringar: ### 18.1 Alias Verifierade stavningsvarianter kan sparas: ```text susannamello → Susanna Melo susammamelo → Susanna Melo ``` Alias ska endast skapas efter manuell bekräftelse. ### 18.2 Filtabell Lokala filer kan senare lagras i en tabell, exempelvis: ```text media_file ``` En film ska kunna ha flera lokala filer eftersom olika omkodningar och versioner kan förekomma. ### 18.3 Manuella beslut Manuellt bekräftade matchningar ska inte behöva lösas igen. ### 18.4 Visuella fingeravtryck För svåra fall kan ett perceptuellt videofingeravtryck skapas genom att: * extrahera bilder med intervall * skala ned bilderna * beräkna perceptuella hashvärden * jämföra sekvenser av hashvärden Detta ligger utanför den första versionen. --- ## 19. Acceptanskriterier för första versionen Den första versionen är godkänd när den kan: 1. läsa alla namn och längder från databasen 2. dela flerpersonsnamn på `+` 3. normalisera databasnamn och filnamn 4. hitta exakta normaliserade namn i smutsiga filnamn 5. hantera upprepade namn 6. hantera namn utan separatorer 7. prioritera den mest specifika flerpersonsposten 8. läsa faktisk videolängd med `ffprobe` 9. jämföra mot aktuell sitelängd 10. jämföra mot historiska sitelängder 11. rangordna kandidater 12. klassificera filer som `matched`, `ambiguous` eller `unmatched` 13. lämna osäkra filer för manuell inspektion 14. skriva separata rapporter 15. inte ändra filer eller databas Det viktigaste kvalitetsmåttet är: ```text precision bland automatiskt matchade filer ``` Målet är nära noll felaktiga automatiska matchningar, även om det innebär att en betydande andel filer lämnas för manuell granskning.