Fix Invalid ID3TimeStamp error when writing date tags
Strip non-timestamp characters (BOM, invisible chars) from date/year values both when reading existing tags in metadata_resolver and when writing in executor. Also harden the EasyID3 except block to not wipe existing tags when adding a missing ID3 header, and add per-field try/except in MP3 tag writing so one bad field doesn't abort the entire track. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d91eb36007
commit
460b92aab3
2 changed files with 23 additions and 5 deletions
22
executor.py
22
executor.py
|
|
@ -73,7 +73,10 @@ def write_tags(path: Path, proposal: TrackProposal, album_proposal: AlbumProposa
|
|||
if proposal.disc_number:
|
||||
tags_to_write["discnumber"] = str(proposal.disc_number)
|
||||
if album_proposal.date:
|
||||
tags_to_write["date"] = album_proposal.date
|
||||
# Strip everything except valid ID3 timestamp characters to prevent ID3TimeStamp errors
|
||||
date_clean = re.sub(r"[^\d\-T:+Z]", "", str(album_proposal.date)).strip()
|
||||
if date_clean:
|
||||
tags_to_write["date"] = date_clean
|
||||
if album_proposal.genre:
|
||||
tags_to_write["genre"] = album_proposal.genre
|
||||
if album_proposal.label:
|
||||
|
|
@ -84,11 +87,22 @@ def write_tags(path: Path, proposal: TrackProposal, album_proposal: AlbumProposa
|
|||
try:
|
||||
audio = EasyID3(str(path))
|
||||
except Exception:
|
||||
audio = EasyID3()
|
||||
audio.save(str(path))
|
||||
# File has no ID3 header — add one without wiping audio data
|
||||
from mutagen.id3 import ID3NoHeaderError
|
||||
try:
|
||||
from mutagen.mp3 import MP3
|
||||
full = MP3(str(path))
|
||||
full.tags = None
|
||||
full.add_tags()
|
||||
full.save(str(path), v2_version=4)
|
||||
except Exception:
|
||||
pass
|
||||
audio = EasyID3(str(path))
|
||||
for k, v in tags_to_write.items():
|
||||
audio[k] = [v]
|
||||
try:
|
||||
audio[k] = [v]
|
||||
except Exception as tag_err:
|
||||
print(f" ⚠️ Tag-Feld '{k}' übersprungen ({path.name}): {tag_err}", file=sys.stderr)
|
||||
audio.save(v2_version=4)
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -337,8 +337,12 @@ def resolve(
|
|||
album = album or Counter(tag_albums).most_common(1)[0][0]
|
||||
|
||||
# Tag year/genre/label
|
||||
import re as _re
|
||||
for t in hints.tracks:
|
||||
year = year or t.existing_tags.get("date") or t.existing_tags.get("year")
|
||||
raw_year = t.existing_tags.get("date") or t.existing_tags.get("year")
|
||||
if raw_year and not year:
|
||||
# Strip invisible chars so ID3TimeStamp validation doesn't fail later
|
||||
year = _re.sub(r"[^\d\-T:+Z]", "", str(raw_year)).strip()[:10] or None
|
||||
genre = genre or t.existing_tags.get("genre")
|
||||
label = label or t.existing_tags.get("label") or t.existing_tags.get("organization")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue