feat(lossless-tags): copy ID3 tags from lossy files onto lossless replacements#14
Open
deviationist wants to merge 2 commits into
Open
feat(lossless-tags): copy ID3 tags from lossy files onto lossless replacements#14deviationist wants to merge 2 commits into
deviationist wants to merge 2 commits into
Conversation
…lacements New `lossless-tags` subcommand: walk a music root, pair each lossy file (MP3) with a same-named lossless sibling (AIFF) in the same folder, and copy the whole ID3 tag wholesale (all frames incl. APIC artwork) onto the lossless file so curated metadata survives the swap. Read-only/parity by default; --write backs up each lossless original, aligns the AIFF NAME chunk to the new title, and optionally deletes the lossy source. --show matched|unmatched|both lists the upgrade backlog. --refresh-plex queues a partial Plex scan of affected dirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The wholesale ID3 copy already transfers TPE2 (albumartist) — and every other frame — but the preview table only displayed Title/Artist/Album/Genre. Add an AlbumArtist column so the dry-run shows it transferring. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
I'm replacing leftover lossy files (MP3) with lossless ones (AIFF) over time. When a fresh AIFF is dropped next to the old MP3 (same basename, same folder), the new file has poor/no tags. This adds a
lossless-tagssubcommand that copies the entire ID3 tag wholesale (all frames incl. APIC artwork) from the lossy file onto its lossless replacement, so curated metadata survives the swap — then the MP3 can be deleted.Like
aiff-titles, this edits the audio file on disk; it never pushes metadata via the Plex API.How it works
--root/MUSIC_ROOT), pairing lossy↔lossless by basename in the same directory (utils/pairing.py).AIFF.save()rewrites only theID3chunk, leaving the audio (SSND) byte-identical. The AIFF nativeNAMEchunk is then aligned to the new title (reusingutils/aiff_chunks.rewrite_name) so Plex shows it right, or stripped with--remove-name.--write(behind theWRITE-TAGStoken) backs up every lossless original first.--show matched|unmatched|bothlists the upgrade backlog;--delete-lossy,--refresh-plex,--ignore-case,--limit,--mirror-version.Safety / edge cases
Only AIFF/AIFF-C targets are supported (FLAC/WAV skipped); ambiguous (>1 sibling), untagged-source, and zero-byte/broken-symlink pairings are skipped + reported. The lossy file is only deleted after a fully successful copy.
Tests
New
tests/id3_tags_test.py+tests/LosslessTagCopy_test.py(incl. the real backup→copy→NAME-fix→delete write path).ruff/black/mypyclean; full suite green. Docs updated (CLAUDE.md, README,.env.example).🤖 Generated with Claude Code