This commit is contained in:
2026-07-18 16:33:23 +02:00
parent 6dd492b660
commit c0d629443a
2 changed files with 1336 additions and 0 deletions

View File

@ -0,0 +1,444 @@
Jag vill implementera en första, skrivskyddad version av funktionaliteten som beskrivs i:
```text
docs/filename-matching-requirements.md
```
Läs hela kravspecifikationen innan du föreslår eller skriver kod.
## Projektets nuvarande struktur
Projektrot:
```text
/storage/disk1/WCX
```
SQLite-databas:
```text
/storage/disk1/WCX/database/wcx.db
```
Databasschema:
```text
/storage/disk1/WCX/scripts/schema.sql
```
Nya script ska placeras i:
```text
/storage/disk1/WCX/scripts
```
Databasen innehåller tabellen `movie` med bland annat:
```text
id
name
duration_seconds
```
Den innehåller även `movie_history` med historiska snapshots och bland annat:
```text
movie_id
name
duration_seconds
archived_at
change_summary
```
Fältet `movie.name` är filmens kanoniska namn från siten. Det består alltid av ett eller flera personnamn. Flera personer separeras med `+`.
Exempel:
```text
Alyn Borav
Ilona
Angelique Lapiedra + Scarlett Lapiedra
```
Lokala videofiler kan däremot ha kraftigt nedsmutsade filnamn, exempelvis:
```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
```
## Uppgift
Implementera den första versionen av:
```text
scripts/match_filenames.py
```
Scriptet ska analysera lokala videofiler och försöka matcha dem mot poster i `movie`.
Det ska vara konservativt. Korrekthet är viktigare än hur många filer som matchas automatiskt.
Resultatet ska klassificeras som:
```text
matched
ambiguous
unmatched
```
Osäkra filer ska lämnas för manuell inspektion.
## Omfattning för första versionen
Första versionen ska:
1. Läsa videofiler från en angiven katalog.
2. Ha stöd för rekursiv sökning.
3. Läsa `id`, `name` och `duration_seconds` från `movie`.
4. Läsa historiska längder från `movie_history`.
5. Normalisera filnamn och databasnamn.
6. Dela flerpersonsnamn på `+`.
7. Hitta exakta normaliserade namn i nedsmutsade filnamn.
8. Hantera namn som skrivits utan separatorer.
9. Hantera upprepade namn i filnamnet.
10. Prioritera den mest specifika flerpersonsposten.
11. Identifiera när filnamnet innehåller flera kända personer.
12. Läsa videons faktiska längd med `ffprobe`.
13. Använda längd som en sekundär signal.
14. Jämföra längden mot både aktuell och historisk sitelängd.
15. Rangordna kandidater med en förklarbar poängmodell.
16. Kräva både en tillräckligt hög poäng och en tydlig marginal till kandidat nummer två för `matched`.
17. Klassificera osäkra resultat som `ambiguous`.
18. Skriva rapporter för `matched`, `ambiguous` och `unmatched`.
19. Inte ändra databasen eller några videofiler.
## Viktiga säkerhetsregler
Scriptet får inte:
* ändra databasen
* flytta filer
* döpa om filer
* radera filer
* registrera alias
* permanent koppla en fil till en databaspost
* automatcha en fil enbart på grund av liknande längd
* automatcha en fil enbart på grund av fuzzy matching
Fuzzy matching får gärna förberedas eller användas för kandidatförslag, men ett resultat som är beroende av fuzzy matching ska i första versionen klassificeras som `ambiguous`.
En felaktig automatisk match är värre än en omatchad fil.
## Namnnormalisering
Normaliseringen ska minst:
* ta bort filändelsen
* göra texten gemen
* normalisera diakritiska tecken
* ta bort mellanslag
* ta bort `_`
* ta bort `-`
* ta bort `+`
* ta bort punkter och annan interpunktion
* behålla bokstäver och siffror
Exempel:
```text
Alyn_Borav_AlynBorav.mp4
→ alynboravalynborav
Alyn Borav
→ alynborav
```
Exakta normaliserade delsträngsträffar ska väga tungt.
Extra ord i filnamnet behöver inte tas bort om databasnamnet ändå kan identifieras som en exakt normaliserad delsträng.
## Flerpersonsfilmer
För:
```text
Angelique Lapiedra + Scarlett Lapiedra
```
ska personerna behandlas separat:
```text
Angelique Lapiedra
Scarlett Lapiedra
```
Båda dessa filnamn ska kunna matcha posten:
```text
AngeliqueLapiedra_ScarlettLapiedra.mp4
ScarlettLapiedra_AngeliqueLapiedra.mp4
```
Ordningen ska alltså inte vara avgörande.
Om databasen innehåller både:
```text
Scarlett Knight
Scarlett Knight + Anya Shidlerova
```
och filen heter:
```text
ScarlettKnight_AnyaShidlerova.mp4
```
ska flerpersonsposten rankas högre.
## Videolängd
Använd `ffprobe` för att läsa faktisk längd utan omkodning.
Längd ska endast användas för att stärka eller diskriminera mellan redan rimliga namnkandidater.
Beräkna både:
```text
absolut skillnad i sekunder
procentuell skillnad
```
En första längdmodell kan ungefär 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
```
Dessa värden ska definieras som tydliga konstanter så att de senare kan justeras.
En större längdskillnad ska inte automatiskt ge `unmatched`, eftersom filer kan vara klippta, förlängda eller motsvara en äldre version.
Historiska längder från `movie_history` ska kunna ge klassificeringen:
```text
historical_version_match
```
Andra möjliga versionsklassificeringar:
```text
current_version_match
historical_version_match
possible_truncated_version
possible_extended_version
duration_mismatch
unknown_version
```
## Automatisk matchning
`matched` ska kräva:
1. en tillräckligt stark namnmatchning
2. en totalpoäng över ett tydligt tröskelvärde
3. en tydlig marginal till kandidat nummer två
4. inga starka motstridiga namnsignaler
5. att fuzzy matching inte är den enda avgörande signalen
Alla tröskelvärden ska ligga som namngivna konstanter nära början av scriptet.
Poängen ska vara förklarbar. Varje kandidat ska innehålla en lista över skäl, exempelvis:
```text
exact normalized full-name match
all participants matched
exact participant set
current duration differs by 5 seconds
historical duration differs by 8 seconds
extra known participant found
fuzzy match required
```
## Kommandoradsgränssnitt
Scriptet ska minst stödja:
```bash
scripts/match_filenames.py /path/to/videos
```
Följande argument ska finnas:
```text
--database
--recursive
--limit
--output-directory
--debug
--no-ffprobe
```
Standardsökväg för databasen:
```text
/storage/disk1/WCX/database/wcx.db
```
`--no-ffprobe` ska göra det möjligt att testa enbart namnmatchningen.
## Rapportering
Skapa följande CSV-filer i output-katalogen:
```text
matched.csv
ambiguous.csv
unmatched.csv
```
Rapporterna ska vara UTF-8-kodade och ha rubrikrad.
`matched.csv` ska minst innehålla:
```text
path
filename
file_duration_seconds
movie_id
movie_name
site_duration_seconds
matched_duration_seconds
version_classification
score
score_margin
match_reason
```
`ambiguous.csv` ska minst innehålla:
```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
```
`unmatched.csv` ska minst innehålla:
```text
path
filename
file_duration_seconds
best_candidate_id
best_candidate_name
best_score
reason
```
Skriv även en sammanfattning till konsolen:
```text
Files analyzed
Matched
Ambiguous
Unmatched
ffprobe failures
```
I `--debug` ska de bästa kandidaterna och deras poängkomponenter visas per fil.
## Tekniska krav
Använd Python 3.12 och endast standardbiblioteket i första versionen.
`ffprobe` får anropas via `subprocess`.
Använd:
* `argparse`
* `csv`
* `dataclasses`
* `pathlib`
* `sqlite3`
* `subprocess`
* `unicodedata`
* tydliga type hints
Använd inte externa Python-paket utan att först motivera varför de behövs.
Fel i en enskild videofil eller ett `ffprobe`-anrop får inte avbryta hela körningen.
Scriptet ska ge tydliga felmeddelanden och avsluta med felkod endast vid övergripande fel, exempelvis:
* databasen saknas
* databasschemat är inkompatibelt
* inputkatalogen saknas
* output-katalogen kan inte skapas
## Tester
Skapa även:
```text
tests/test_match_filenames.py
```
Använd `unittest` från standardbiblioteket.
Tester ska minst täcka:
1. enkel normalisering
2. namn med understreck
3. sammanfogade namn
4. upprepade namn
5. extra skräpord
6. flerpersonsnamn
7. personer i omvänd ordning
8. prioritering av flerpersonspost
9. korta namn
10. längdpoäng
11. historisk längdmatchning
12. otillräcklig marginal mellan kandidater
13. fuzzy-beroende resultat blir inte `matched`
14. fil utan kandidat blir `unmatched`
Använd temporär SQLite-databas och temporära kataloger i testerna. Testerna får inte använda produktionsdatabasen eller verkliga videofiler.
## Arbetssätt
Arbeta stegvis.
Börja med att:
1. läsa den befintliga kravspecifikationen
2. inspektera relevant databasschema
3. föreslå en kort implementationstruktur
4. implementera normalisering och kandidatmodell
5. implementera namnmatchning
6. implementera längdmatchning
7. implementera klassificering
8. implementera CSV-rapportering
9. lägga till tester
10. uppdatera README med användning och begränsningar
Gör inga förändringar utanför den här funktionaliteten.
När du levererar kod ska du ge hela innehållet för nya eller ändrade filer, inte små kodfragment som kräver besvärlig manuell infogning.
När något är osäkert ska du välja den konservativa matchningen och tydligt dokumentera antagandet.

View File

@ -0,0 +1,892 @@
# 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
Exempel:
```bash
scripts/match_filenames.py /path/to/video/files
```
Alternativt stöd för en textfil med filnamn:
```bash
scripts/match_filenames.py \
--file-list filenames.txt
```
Möjliga framtida argument:
```text
--database
--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.