Compare commits

...

2 Commits

Author SHA1 Message Date
6840a57e0b
Implement JSONification 2025-06-20 19:54:55 +02:00
2c555ba8e0
Add UUID to songs 2025-06-20 19:22:31 +02:00
4 changed files with 48 additions and 3 deletions

View File

@ -1,10 +1,11 @@
# Karaokatalog # Karaokatalog
Tools to manage an Ultrastar DX song library. Features include: Tools to manage an UltraStar DX song library. Features include:
1. Deduplication 1. Deduplication
2. Organization 2. Organization
3. Recoding 3. Recoding
4. Jsonification
## Setup ## Setup
@ -55,3 +56,13 @@ python3 -m karaokatalog.organize $SONG_LIBRARY
```bash ```bash
python3 -m karaokatalog.recode $SONG_LIBRARY python3 -m karaokatalog.recode $SONG_LIBRARY
``` ```
### Jsonification
**Create a `songs.json` file with some song metadata in the root library dir.**
This operation is risk-free: If a `songs.json` already exists, it is kept intact (so no data loss possible).
```bash
python3 -m karaokatalog.jsonify $SONG_LIBRARY
```

View File

@ -1,9 +1,10 @@
from __future__ import annotations from __future__ import annotations
import filecmp import filecmp
from dataclasses import dataclass from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import Self from typing import Self
from uuid import UUID, uuid4
from karaokatalog.parse_song_txt import parse_song_txt from karaokatalog.parse_song_txt import parse_song_txt
@ -25,6 +26,7 @@ class Song:
video: Path | None video: Path | None
cover: Path | None cover: Path | None
song_txt: Path song_txt: Path
uuid: UUID = field(default=uuid4())
@property @property
def dir(self) -> Path: def dir(self) -> Path:
@ -52,6 +54,7 @@ class Song:
audio_name = tags.get("AUDIO", tags.get("MP3")) audio_name = tags.get("AUDIO", tags.get("MP3"))
video_name = tags.get("VIDEO") video_name = tags.get("VIDEO")
cover_name = tags.get("COVER") cover_name = tags.get("COVER")
uuid = tags.get("UUID")
if not title or not artist: if not title or not artist:
# Both are mandatory according to the specification # Both are mandatory according to the specification
@ -64,11 +67,12 @@ class Song:
video=song_txt / video_name if video_name else None, video=song_txt / video_name if video_name else None,
cover=song_txt / cover_name if cover_name else None, cover=song_txt / cover_name if cover_name else None,
song_txt=song_txt, song_txt=song_txt,
uuid=UUID(uuid) if uuid else uuid4(),
) )
def as_dict(self) -> dict[str, str]: def as_dict(self) -> dict[str, str]:
return { return {
"uuid": str(self.uuid),
"title": self.title, "title": self.title,
"artist": self.artist, "artist": self.artist,
# TODO More fields
} }

View File

View File

@ -0,0 +1,30 @@
import json
import logging
from karaokatalog.get_parser import get_parser
from karaokatalog.Library import Library
logging.basicConfig(
format="%(asctime)s [%(levelname)s] %(message)s", level=logging.INFO
)
if __name__ == "__main__":
args = get_parser(
"jsonify", "Create a JSON file containing metadata of all songs in the library"
).parse_args()
logging.info("Karaokatalog Jsonification started")
logging.info("Loading library")
library = Library.from_dir(args.library_path)
logging.info("Library loaded")
songs = [song.as_dict() for song in library.songs]
json_path = args.library_path / "songs.json"
logging.info(f"Writing JSON to {json_path}")
with json_path.open("x", encoding="utf-8") as f:
json.dump(songs, f, ensure_ascii=False, indent=4)
logging.info("Karaokatalog Jsonification done")