Commit graph

64 commits

Author SHA1 Message Date
8e46c46263 Docs: add --from-photo (Variante E) to scan command documentation
- BEDIENUNGSANLEITUNG: new Variante E section with usage examples,
  updated flowchart to include option E
- README: Schnellstart shows --from-photo as Variante A2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:45:31 +01:00
a32b0229f5 Add --from-photo to scan, retry in MB disc loop, temp/ to .gitignore
- scan: new --from-photo <img> option extracts EAN via Vision-LLM,
  then falls through to existing MusicBrainz barcode lookup
- ripper: MB disc loop now retries the same disc on rip failure instead
  of printing "Bitte Album neu starten"; user decline raises RuntimeError
- .gitignore: suppress temp/ directory
- tests: 4 new tests for scan --from-photo (225 total)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:43:37 +01:00
55c71823d1 Add tests for extract_barcode_from_image
9 new test cases covering: plain digit response, thinking-tag stripping,
digit extraction from surrounding text, empty/no-digit response → None,
exception handling → None, correct model/URL forwarding, EAN_PROMPT usage,
and base64 image encoding in request payload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:34:59 +01:00
2490293dcf Fix MB-hit path: poll scanner for backcover photo at disc insert prompt
If Cover Art Archive has no backcover, the scanner server (already running
since EAN prompt) is now also monitored at each disc insert prompt via
_input_or_scan. On photo upload, Vision-LLM starts in the background and
the photo is saved as backcover.jpg after ripping. Phone photo takes
priority over any CAA cover.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:31:09 +01:00
7135e681f8 Fix sanitize_filename consistency, add scanner server tests, remove stray file
- Unify sanitize_filename (organizer) and _sanitize_name (ripper): both now use
  whitelist approach — spaces→underscore, keep \w and hyphens, remove everything
  else (brackets, punctuation, commas, dots, …). _sanitize_name removed from
  ripper.py; ripper now imports sanitize_filename from organizer directly.
- Add tests/test_scanner_server.py: 15 tests covering HTTP GET/POST handlers,
  image upload queue, 404/400 error paths, _get_local_ip fallback, print_qr
  graceful degradation without qrcode installed.
- Delete empty stray file '3' from repo root.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:20:03 +01:00
32c84b9edb Add phone-based EAN scanning, scanner server for cover upload, Vision-LLM integration
New features:
- EAN/Barcode can now be entered by typing or by photographing the CD sleeve;
  Vision-LLM (extract_barcode_from_image) reads the barcode from the photo
- Scanner server (port 8765) starts at the beginning of every album loop,
  serving both EAN barcode scanning and back cover upload via QR code
- Vision-LLM analyses back cover in background thread while ripping;
  priority: Vision-LLM > MusicBrainz > CDDB
- _find_abcde_mbid reads MBID from abcde temp dirs for CAA cover download
  even when the CD barcode is not linked in MusicBrainz
- Concrete copy-paste apply commands shown after each album in 'Next steps'
- _sanitize_name: whitelist approach (removes brackets and punctuation)
- qrcode added as dependency for terminal QR code display

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:05:59 +01:00
6c12510f76 Update docs for EAN-first workflow and genre field
- README: mention EAN-first auto-rip in quickstart
- BEDIENUNGSANLEITUNG: rewrite workflow diagram and interactive example
  for EAN-first flow (auto-rip on MB hit, fallback on miss), document
  genre field in album.json, update multi-disc and tips sections

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 00:25:08 +01:00
8b449493cd EAN-first workflow in interactive_rip + GnuDB DYEAR/DGENRE parsing
EAN is now asked before the album name. On MusicBrainz hit, the ripper
enters an auto-rip flow (no album name prompt, no CDDB confirm, disc
count from MB data). On miss/empty EAN, the previous fallback flow
(album name → CDDB confirm) is preserved.

GnuDB responses now parse DYEAR and DGENRE fields into a new CddbResult
NamedTuple. Album model gains an optional genre field.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 00:21:42 +01:00
90713452c2 Fix organizer: omit empty artist suffix in filenames
Same fix as ripper: when track.artist and album.artist are both empty,
the filename now ends with just the title instead of '_-_.flac'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 23:40:48 +01:00
de12afa67a Fix album.json landing in wrong directory
album.json was written to a separately computed album_root that could
differ from the actual disc_dir parent (e.g. when CDDB returned a
different album name). Now album.json is always saved in disc_dir.parent
where the audio files actually reside. Also adopts CDDB album name when
the user accepted the default name.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 23:34:35 +01:00
cf836b4528 Fix filename: omit empty artist suffix, sanitize single quotes
Regular (non-compilation) tracks had an empty artist producing
trailing '_-_.flac'. Now artist suffix is only appended when non-empty.
Also added single quote to _sanitize_name's removed characters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 23:25:26 +01:00
12bf67e977 Fix CDDB parser: only ' / ' splits artist/title, never ' - '
Classical titles like 'Sonate: I. Largo - Allegro' were incorrectly split
at the movement-separator dash, producing wrong artist/title pairs.
Now only ' / ' (CDDB compilation standard) is treated as artist-title
separator; ' - ' is always part of the title.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 22:45:38 +01:00
9e61b01f92 Fix M3U #EXTINF to include artist: 'Artist - Title' format
#EXTINF:0,Title was missing the artist, causing VLC and other players
to show only the track title without the performer. Standard M3U
extended format is '#EXTINF:<duration>,<Artist> - <Title>'.
Falls back to album.artist when no per-track artist is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:37:58 +01:00
97910623c8 Reduce log noise and fix spurious cover-not-found warning
- organizer: skip move when src == dst (in-place re-apply produces no
  log spam); log only filename instead of full path
- cover: demote 'Kein Front-Cover gefunden' from WARNING to DEBUG —
  copy_covers is not the final authority on cover availability
- cli apply: emit user-visible hint only when cover is truly absent
  after all fallbacks (including parent-dir search for CD subdirs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:17:55 +01:00
c27c1f9510 Find cover in parent directory when album_dir is a CD subdirectory
When applying in-place with input_dir=CD1, cover files naturally live
in the album root (parent). Fall back to searching the parent when
album_dir matches the CD\d+ pattern and no cover is found in-place.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:12:48 +01:00
984d8acc88 Fix album_dir path after in-place directory rename
_rename_album_dir_inplace now returns the updated input_dir path
(e.g. .../Golden_Oldies_Vol_11/CD1 instead of .../Album1/CD1).
apply uses the return value so the final 'Fertig!' message and any
subsequent operations reference the correct, post-rename path.

Also fix CDDB header album name extraction (regex search between
---- markers instead of stripping leading/trailing dashes).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:44:09 +01:00
0c0311b00f Fix CDDB album name extraction from header line
The header line can have a prefix before the dashes, e.g.:
  "#1 (Musicbrainz): ---- Artist / Album ----"
Use regex search for content between ---- markers instead of
stripping leading/trailing dashes from the full line.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:32:35 +01:00
f902e50018 Remove idea/ directory from version control
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:12:34 +01:00
7ced974279 Add CDDB confirmation, cd-discid hint, CD-counter increment, check command
- interactive_rip: after CDDB lookup, show album name + tracklist and ask
  'Treffer korrekt? (j/n)' before renaming files; rip_disc gains rename=False
  option for deferred renaming
- interactive_rip: CD number prompt now shows disc_counter as default
  instead of always showing [1]
- _rip_with_abcde: when CDDB fails and cd-discid is not installed, print
  a visible hint with install command instead of silently doing nothing
- _stream_abcde: extract album name from CDDB header line (---- DTITLE ----)
  and return it as part of the result tuple
- _rename_files: early return when output directory does not exist
- check command (cli.py): already present from previous session

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:02:01 +01:00
2f80cb2693 Remove MusicBrainz retry logic — HTTP 200 means no data, not transient error
MusicBrainz always returns HTTP 200; an empty result set is definitive.
Retrying would never yield a different outcome.

- lookup_by_barcode(): retries parameter removed, random import removed
- Removed 3 retry-related tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:48:07 +01:00
09c01c9370 Fix CDDB parser for compilations and add grab-progress fallback
- _parse_cddb_lines now handles both 'Artist - Title' and 'Artist / Title'
  (slash separator used by abcde for compilation albums like Various Artists)
- _stream_abcde collects grab-progress lines (track N: Artist / Title)
  as a fallback TrackInfo source when no CDDB lines are found
- New _parse_grab_tracks() splits grab titles on ' / ' into artist+title
- 5 new tests (TestParseCddbLines.test_compilation_slash_separator,
  TestParseGrabTracks.*)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:42:03 +01:00
e75e5d7de0 feat: GnuDB fallback with retries when abcde CDDB lookup returns nothing
- New module cddb.py: direct GnuDB/FreeDB HTTP lookup using CDDB protocol,
  with same retry+random-delay logic as MusicBrainz barcode lookup
- get_discid() reads disc fingerprint via cd-discid before ripping
- If abcde returns no CDDB track data, lookup_by_discid() queries GnuDB
  directly (up to 3 retries, 2-6 s random pause between attempts)
- TrackInfo moved from ripper.py to models.py to break circular import
  (cddb.py and ripper.py both use TrackInfo)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 07:24:16 +01:00
65164d428c feat: retry MusicBrainz barcode lookup with random delay on empty result
Up to 3 retries with 2–6 s random wait between attempts, as MusicBrainz
occasionally returns no results on the first try. retries parameter is
configurable (default: 3).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 07:16:32 +01:00
468fac6d2b docs: document auto-rename of album directory in apply --in-place
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:53:24 +01:00
7554cade50 feat: auto-rename album directory after in-place apply
After all file operations (rename, tag, cover, playlist), apply now
renames the album root directory to match album.json metadata:

- input_dir = CD1/CD2 etc.: parent directory is renamed automatically
  e.g. Kärntner_Doppelsextett/ → Du_Berührst_Mi_20_Jahre_Kärntner_Doppelsextett/
- input_dir = album root: a hint with the mv command is printed instead
  (avoids renaming an actively used path)
- Existing directory with target name: warning, no rename

Also: _sanitize_filename() in organizer.py made public (sanitize_filename),
used consistently across organizer, playlist and cli modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:49:17 +01:00
c0e4d2aa85 fix: show clean error message when MusicBrainz barcode lookup fails
Catch ValueError (barcode not found) and httpx.HTTPError (network error)
in _scan_to_album and print a user-friendly message with hint instead of
a raw Python traceback. Also remove unused `call` import in test_ripper.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:18:12 +01:00
b70127e838 docs: document MusicBrainz barcode lookup in README and Bedienungsanleitung
- README: Schnellstart shows --barcode as fastest option
- Bedienungsanleitung:
  - Workflow diagram updated (EAN path, Varianten A-D)
  - Interactive rip example shows EAN prompt with MusicBrainz output
  - New Variante D: scan --barcode (no image, no OCR, no local LLM)
  - Variante C: corrected default model to qwen3-vl:235b-cloud
  - Tipps: barcode as first/fastest option, updated CDDB fallback hints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:16:18 +01:00
b30aaa617d Add MusicBrainz barcode lookup (scan --barcode and interactive rip)
- New module musicbrainz.py: lookup_by_barcode() via EAN-13/UPC-12,
  two-step API (barcode search → release detail with recordings),
  respects 1 req/s rate limit with User-Agent header
- cli.py: scan command gets --barcode option as highest-priority mode
  (no images needed); _scan_to_album() dispatches to MusicBrainz first
- ripper.py: interactive_rip() prompts for optional EAN after album name;
  MusicBrainz data (incl. year) takes priority over CDDB for album.json;
  album_root.mkdir() added so JSON can be written even when MB changes dir
- tests: test_musicbrainz.py (16 tests), test_ripper.py +6 barcode tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:13:10 +01:00
6aba30c0e5 Default Vision-Model auf qwen3-vl:235b-cloud gesetzt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 05:56:44 +01:00
db47aa4456 Fix: Album.album akzeptiert null-Werte vom LLM
Wenn das LLM keinen Albumtitel erkennt (z.B. nur Ensemblename auf
dem Backcover), gibt es "album": null zurück. Statt mit
ValidationError abzubrechen, wird null jetzt in "" konvertiert.
Der Nutzer kann den leeren Titel in album.json manuell ergänzen.

Geändert:
- Album.album: str = "" (statt str ohne Default)
- field_validator mode="before", None → ""

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 05:49:37 +01:00
795be8609a Opus/M4A-Cover-Embedding, cover.py-Tests und OCR-Tests
- tagger.py: embed_cover() unterstützt jetzt .opus (Vorbis-Comment
  METADATA_BLOCK_PICTURE) und .m4a (MP4Cover); imports ergänzt
- test_tagger.py: 2 neue Tests für Opus/M4A; minimale Audio-Fixtures
  als base64-Konstanten (176 B Opus, 856 B M4A)
- test_cover.py: TestPrepareCover (5 Tests) und TestCopyCovers (6 Tests)
  für prepare_cover() und copy_covers()
- test_ocr.py: 13 Tests für run_ocr(), _detect_and_fix_rotation()
  und ocr_images(); Tesseract via subprocess.run gemockt

144 Tests, 0 Fehler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 04:50:13 +01:00
cfc2a2018e Tagger- und CLI-Tests; Bugfix embed_cover für MP3 ohne ID3-Header
- tests/test_tagger.py: 20 Tests für tag_file, tag_album,
  _scale_cover_for_embed, embed_cover (FLAC + MP3), embed_album_cover
- tests/test_cli.py: 14 Tests für apply (in-place, disc-mismatch,
  dry-run, playlist, multi-disc), check und scan (via Mock)
- tagger.py: embed_cover für MP3 fängt ID3NoHeaderError ab und
  erstellt einen neuen ID3-Tag wenn keiner vorhanden ist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 04:37:07 +01:00
70c096cde4 Lint-Fixes, process-Disc-Validierung und Forgejo-CI
- ruff: Import-Sortierung, unused imports, Zeilenlängen behoben
- cli.py: _check_disc_counts_or_exit() extrahiert; auch process-Befehl
  prüft jetzt Disc-Anzahlen vor dem Umbenennen
- .forgejo/workflows/ci.yml: ruff + pytest auf push/PR gegen main

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 00:51:14 +01:00
88b89fbb50 LLM-Parser-Tests, check-Befehl und Cover-Doku
tests/test_llm_parser.py: 13 Tests für _call_ollama, _call_openai_compatible
  und parse_tracklist (Retry-Logik, Markdown-Block, Track-Artist, Mock)

cli: neuer check-Befehl zeigt Tags und Cover-Status aller Audiodateien;
  ♪ markiert Dateien mit eingebettetem Cover

BEDIENUNGSANLEITUNG: neuer Abschnitt 7 (check-Befehl), Cover-Konvention
  (frontcover.jpg/backcover.jpg, Embedding, 500px) in Schritt 3

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 00:45:49 +01:00
256be0ae33 Cover-Embedding: Auflösung auf 500px reduzieren vor dem Einbetten
Neue Hilfsfunktion _scale_cover_for_embed() skaliert das Coverbild
mit Pillow auf max. 500px (EMBED_COVER_MAX_SIZE) und kodiert es
als JPEG quality=85 in-memory. embed_cover() liest nicht mehr die
rohen Bytes der Originaldatei, sondern nutzt das skalierte Bild.

Ergebnis: eingebettete Cover ~40–100 KB statt 200–500 KB des
1200px-Originals, auf HiDPI-Displays noch scharf erkennbar.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 00:40:11 +01:00
3fa6237f94 Cover-Embedding: frontcover.jpg/backcover.jpg als Standard-Konvention
cover: find_cover() sucht frontcover.jpg/.png und backcover.jpg/.png;
  copy_covers() speichert als frontcover.jpg / backcover.jpg
tagger: embed_album_cover() bettet Frontcover in alle Tracks ein
cli: apply und process rufen embed_album_cover() nach copy_covers() auf
tests: TestFindCover mit 7 Tests (jpg, png, Symlink, Priorität, Negativ)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 00:35:28 +01:00
c9152cf19f Bedienungsanleitung aktualisieren: neues Dateinamen-Schema und CDDB→album.json
- Workflow-Diagramm: CDDB speichert album.json automatisch
- Rip-Ergebnis: korrektes Schema 01_-_Titel_-_Kuenstler.flac
- apply-Ergebnisse: Dateinamen angepasst
- album.json: optionales Track-artist-Feld erklärt
- Dateinamen-Schema-Abschnitt: vollständige Beschreibung

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 00:26:09 +01:00
4e6d82a41d Einheitliches Dateinamen-Schema: 01_-_Titel_-_Kuenstler.flac
organizer: Separator vor Titel angleichen (war: 01_Titel_-_K., neu: 01_-_Titel_-_K.)
playlist: Glob-Pattern und Fallback auf neues Schema angepasst
tests: Assertions aktualisiert

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 00:22:54 +01:00
bafea5f335 CDDB→album.json + LLM-Prompts mit Track-Künstler
ripper: nach erfolgreichem CDDB-Rip album.json im Album-Verzeichnis
speichern (Artist, Titel, alle Discs mit Track-Künstlern) — Workflow-
Lücke zwischen rip und apply geschlossen.

llm_parser, vision_llm: Prompts erklären das optionale Track-artist-
Feld; LLM setzt es nur wenn Track-Interpret vom Album-Künstler abweicht.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 00:16:44 +01:00
255496bd1b Add per-track artist to filename: 09_Titel_-_Kuenstler.flac
- Track model: add optional artist field (None = fall back to album artist)
- organizer: append _-_<artist> to each filename
- tagger: use track.artist over album.artist for the 'artist' tag
- playlist: widen glob pattern to match new _-_<artist> suffix
- tests: update assertions + add test for track-artist override

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 00:11:07 +01:00
775f274d02 Fix and expand tests: 63 tests passing, covers all core modules
Remove tests/ from .gitignore (was accidentally excluded).

- test_ripper.py: rewrite for current API (_parse_cddb_lines,
  _extract_tracks, _rename_files, _clean_input); fix default quality
- test_organizer.py: update filename assertions (spaces→underscores);
  add TestSanitizeFilename, TestCheckDiscCounts, in-place mode
- test_playlist.py: fix dummy filenames to underscore scheme;
  add multi-disc, filename sanitization, EXTINF and fallback tests

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 00:00:44 +01:00
734bc80b79 Update Bedienungsanleitung: in-place mode, Unterstrich-Schema, Disc-Validierung
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 23:52:17 +01:00
070a0573ae Add --in-place mode to apply: rename and tag without moving files
When no output_dir is given (or --in-place is set), files are renamed
and tagged directly in the source directory instead of being moved into
a separate Jellyfin library hierarchy.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 23:41:29 +01:00
67b8653b3c Fix tagger and playlist to use underscore filename pattern
After the organizer was updated to use underscores in filenames,
the tagger (glob pattern "01 *") and playlist generator (pattern
"01 title.*") still used spaces and failed to find any files.
Updated both to use "01_*" / "01_title.*" patterns.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 23:34:16 +01:00
8a39f7c41e Sanitize filenames: replace spaces/punctuation with underscores
Replace all non-word characters (spaces, punctuation, brackets, etc.)
with underscores in track titles, album names and artist names.
Collapse consecutive underscores to one, strip leading/trailing ones.
Umlauts (ä, ö, ü, ß) and digits are preserved.

Also use underscore instead of space between track number and title.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 23:25:28 +01:00
f4e49a3df6 Add disc count validation before apply
Check audio file count vs JSON track count per disc before processing.
Aborts with a clear error showing which discs have discrepancies and
whether tracks are missing from the JSON or audio files are missing
from the directory.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 23:08:24 +01:00
b599c9eb8a Fix default model, increase timeout, improve multi-column prompt
- Change default text-LLM from llama3 (not installed) to gemma3:12b
- Increase LLM timeout from 120s to 300s (large models need longer)
- Add explicit multi-column layout instruction to vision prompt to
  prevent skipping columns on dense CD back-cover tracklists

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 22:56:02 +01:00
8765e991b0 Fix broken abcde command: build output_fmt before cmd construction
cmd[-2] was overwriting the -a action value instead of the -o format
value when -P was appended last. Now output_fmt is computed upfront and
the cmd list is built cleanly without post-hoc index manipulation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 21:10:11 +01:00
430775adf8 Add live progress, progress bar and CDDB logging to ripper
- Replace capture_output=True with Popen+live streaming (_stream_abcde)
- Show track counter:  "Track 3/14  Title..."
- Show cdparanoia progress bar: [████████░░░░░░░░░░░░░░░░░░░░░░]  45.2%  12.3 MB
- Show CDDB album header and track list as they appear
- Show tagging progress: "Tagging 14/14"
- Print abcde command for full transparency
- Collect CDDB track lines while streaming for later parsing
- Log warnings when CDDB returns no data
- Print full renamed file list after ripping

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 20:25:30 +01:00
d0d64da12e Change default quality from medium to high
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 20:17:58 +01:00