[2026-09-27] eagle: personal/plans/music-artist-albumartist-repair.md personal/tech/id3-tag-repair.md personal/tech/scripts/find_va_author.py
This commit is contained in:
1 parent
85b682701a
commit
c4e44ac277
3 files changed
+302
-8
No files matched your search
@@ -302,13 +302,34 @@ Alex), `ДДТ/2008 L'Echoppe` (сборник ДДТ, 10 файлов = дуэ
|
||||
!Retro/Муслим Магомаев 7 → Муслим Магомаев
|
||||
Infected Mushroom (2 папки) 5 → Infected Mushroom
|
||||
Тест Сабвуфера 4 → Тест Сабвуфера
|
||||
!Рэп/Птаха - Красивые, богатые (2009) 8 → Птаха (альбом с фитами)
|
||||
!Рэп/Трофим/11 Следующая остановка 14 → Трофим (8 гостей на альбоме Трофима)
|
||||
z Другое…/C.Шнуров - Бумер (2003) 19 → Сергей Шнуров (саундтрек, автор музыки)
|
||||
```
|
||||
|
||||
**Правило:** `Various Artists` ставить ТОЛЬКО когда исполнители **действительно разные**.
|
||||
Один артист (в т.ч. с вариациями написания) → ставить **его**.
|
||||
**Правило:** `Various Artists` ставить ТОЛЬКО когда исполнители **действительно разные**
|
||||
и **нет владельца альбома**. Один артист (в т.ч. с вариациями написания) → ставить **его**.
|
||||
Сборник песен одного автора с гостевыми фитами → **имя автора**.
|
||||
|
||||
Детектор: `personal/tech/scripts/find_va_misuse.py` — папки с `aa='Various Artists'`, где
|
||||
>50% файлов имеют одного `artist`. Итог: `ПАПОК-КАНДИДАТОВ: 0` (класс вычищен).
|
||||
🔴 **Alex дважды ловил меня на этом в сессии 10:**
|
||||
> «**`albumartist` птаха блядь! artist — реальные исполнители! ты поебанулся и забыл что че значит??**»
|
||||
> «**Трофим блядь albumartist!**» — про `Следующая остановка`, где 8 разных гостей (Маршал, Овсиенко, Азиза…)
|
||||
|
||||
**Формулировка, которую нельзя забывать:**
|
||||
|
||||
| Поле | Значение |
|
||||
|---|---|
|
||||
| `albumartist` | **владелец альбома/проекта** — чей это релиз |
|
||||
| `artist` | исполнитель конкретного трека (фиты — реальные имена) |
|
||||
| `Various Artists` | только сборники **разных** авторов без единого владельца |
|
||||
|
||||
Детекторы: `personal/tech/scripts/find_va_misuse.py` (папки с `aa='Various Artists'`, где
|
||||
>50% файлов — один `artist`; итог `ПАПОК-КАНДИДАТОВ: 0`) и
|
||||
`personal/tech/scripts/find_va_author.py` (папка названа по автору, `aa='Various Artists'`;
|
||||
остались только 2 защитимые: `Блестящие, Фриске`, `Eminem,50cent`).
|
||||
|
||||
**Защитимые ложные:** 47 папок с настоящими сборниками (`Sbornik_Novij_Rok` 200, `!Retro` 158,
|
||||
`!Radio/*`, `Final Fantasy VI`, трибьюты, `Gazgolder`) — `Various Artists` ВЕРЕН.
|
||||
|
||||
### 🔴 A3 — имя подпапки уезжает в `album`/`albumartist` склейкой
|
||||
|
||||
@@ -338,6 +359,34 @@ Infected Mushroom (2 папки) 5 → Infected Mushroom
|
||||
Реакция Alex (со «стоп»): «**красную плесень в красную плесень - виа меа в виа меа -
|
||||
не объединять корень Другого в альбом**».
|
||||
|
||||
### 🔴 A6 — разнобой написания серии + технические суффиксы в `album`
|
||||
|
||||
Один релиз жил в четырёх написаниях, плюс `(CD1)`/`(CD2)` в значении:
|
||||
|
||||
```
|
||||
'Нечетный Воин' (22 файла, без ё)
|
||||
'Нечетный Воин (CD1)' (11) ← технический суффикс диска
|
||||
'Нечетный Воин (CD2)' (11)
|
||||
'Нечетный воин 2' (4)
|
||||
'Нечётный воин 2' (16) ← регистр «воин» строчными
|
||||
```
|
||||
|
||||
**Норма (Alex: «`Нечетный`/`Нечётный` — очевидно блядь, не??»):** литературное написание
|
||||
**с ё**, суффикс диска убрать.
|
||||
|
||||
```
|
||||
'Нечетный Воин' -> 'Нечётный Воин'
|
||||
'Нечетный Воин (CD1)' -> 'Нечётный Воин'
|
||||
'Нечетный Воин (CD2)' -> 'Нечётный Воин'
|
||||
'Нечетный воин 2' -> 'Нечётный Воин 2'
|
||||
'Нечётный воин 2' -> 'Нечётный Воин 2'
|
||||
```
|
||||
|
||||
Итог: `Нечётный Воин` (24) + `Нечётный Воин 2` (20). Скрипт: `/tmp/fix_nechetny_spelling.py`.
|
||||
|
||||
**Общий принцип:** технические суффиксы (`(CD1)`, `(Disc 2)`) — не часть названия альбома;
|
||||
перед записью значения сверять написание серии с нормой (ё, регистр).
|
||||
|
||||
### 🔴 A5 — имя ПРОЕКТА вместо артиста + вложенные скобки в имени файла (сессия 9)
|
||||
|
||||
Класс: `artist` (и `albumartist`) = **название музыкального проекта**, а реальные исполнители
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Класс A2 (второй детектор): albumartist='Various Artists', но это АЛЬБОМ ОДНОГО АВТОРА.
|
||||
|
||||
Признак: папка названа по автору (или автор доминирует в artist), а стоит 'Various Artists'.
|
||||
Дополняет find_va_misuse.py (тот ловит «>50% один artist» без учёта имени папки).
|
||||
|
||||
Питфолл: 47 папок-сборников дают «кандидат» ложно (Sbornik_Novij_Rok, !Retro, !Radio/*,
|
||||
Final Fantasy VI, трибьюты, Gazgolder) — они в SKIP. Остаток после чистки:
|
||||
`Блестящие, Фриске` и `Eminem,50cent` — папки-склейки, Various Artists там ВЕРЕН.
|
||||
|
||||
Использование: python3 find_va_author.py
|
||||
Итог сессии 10: кандидатов 2 (оба защитимые).
|
||||
"""
|
||||
import csv
|
||||
import collections
|
||||
import os
|
||||
|
||||
P = '/Users/admin/Downloads/music-tags/APPLY-PLAN.csv'
|
||||
rows = list(csv.DictReader(open(P, encoding='utf-8-sig', newline='')))
|
||||
|
||||
|
||||
def s(v):
|
||||
return (v or '').strip()
|
||||
|
||||
|
||||
# музыкальные папки-КОНТЕЙНЕРЫ, где Various Artists законен сам по себе
|
||||
SKIP_PARTS = ('!Radio', 'Sbornik', 'Трибьют', 'VA ', 'Сборник', 'Сборка')
|
||||
SKIP_EXACT = {
|
||||
'!Retro', '!Rock&Folk/!rock_o_pop', '!Классика', '!Rock&Folk/Неголубой огонёк НГ 2004',
|
||||
'!A Not sorted/Sbornik_Novij_Rok',
|
||||
}
|
||||
|
||||
by = collections.defaultdict(list)
|
||||
for r in rows:
|
||||
if s(r['new_albumartist']) == 'Various Artists':
|
||||
by[r['folder']].append(r)
|
||||
|
||||
print("КАНДИДАТЫ: папка-АВТОР + Various Artists\n")
|
||||
hits = 0
|
||||
for folder, rs in sorted(by.items()):
|
||||
if any(p in folder for p in SKIP_PARTS):
|
||||
continue
|
||||
if folder in SKIP_EXACT or any(folder.startswith(x) for x in SKIP_EXACT):
|
||||
continue
|
||||
fam = os.path.basename(folder) # имя самой папки
|
||||
parent = os.path.basename(os.path.dirname(folder)) # имя родителя
|
||||
arts = collections.Counter(s(r['new_artist']) for r in rs if s(r['new_artist']))
|
||||
top, cnt = arts.most_common(1)[0] if arts else ('', 0)
|
||||
n = len(rs)
|
||||
# автор = доминирующий artist, и он же имя родительской папки
|
||||
if top and cnt >= 2 and (top == parent or top in parent or parent in top):
|
||||
print(f" {n:4d} файлов top={top!r} ({cnt}/{n}) автор-папка={parent!r}")
|
||||
print(f" {folder}")
|
||||
hits += 1
|
||||
# либо альбом назван так же, как папка, и 1 исполнитель
|
||||
elif n <= 20 and cnt >= max(2, n * 0.4):
|
||||
print(f" {n:4d} файлов top={top!r} ({cnt}/{n}) папка={fam!r}")
|
||||
print(f" {folder}")
|
||||
hits += 1
|
||||
|
||||
print(f"\nвсего кандидатов: {hits}")
|
||||
Reference in new issue
Block a user