From 87987f72d1900a8c29fa0f487dabc3f06e191941 Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Fri, 22 Dec 2023 13:07:26 -0800 Subject: [PATCH 1/6] Add isrc to trackmetadata --- streamrip/metadata/track_metadata.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/streamrip/metadata/track_metadata.py b/streamrip/metadata/track_metadata.py index 822fe70..2560aec 100644 --- a/streamrip/metadata/track_metadata.py +++ b/streamrip/metadata/track_metadata.py @@ -1,6 +1,5 @@ from __future__ import annotations -import json import logging from dataclasses import dataclass from typing import Optional @@ -37,6 +36,7 @@ class TrackMetadata: @classmethod def from_qobuz(cls, album: AlbumMetadata, resp: dict) -> TrackMetadata | None: title = typed(resp["title"].strip(), str) + isrc = typed(resp["isrc"], str) streamable = typed(resp.get("streamable", False), bool) if not streamable: @@ -82,15 +82,13 @@ class TrackMetadata: tracknumber=tracknumber, discnumber=discnumber, composer=composer, + isrc=isrc, ) @classmethod def from_deezer(cls, album: AlbumMetadata, resp) -> TrackMetadata | None: - with open("resp.json", "w") as f: - json.dump(resp, f) - - logger.debug(resp.keys()) track_id = str(resp["id"]) + isrc = typed(resp["isrc"], str) bit_depth = 16 sampling_rate = 44.1 explicit = typed(resp["explicit_lyrics"], bool) @@ -116,6 +114,7 @@ class TrackMetadata: tracknumber=tracknumber, discnumber=discnumber, composer=composer, + isrc=isrc, ) @classmethod @@ -152,14 +151,11 @@ class TrackMetadata: @classmethod def from_tidal(cls, album: AlbumMetadata, track) -> TrackMetadata: - with open("tidal_track.json", "w") as f: - json.dump(track, f) - title = typed(track["title"], str).strip() item_id = str(track["id"]) + isrc = typed(track["isrc"], str) version = track.get("version") explicit = track.get("explicit", False) - isrc = track.get("isrc") if version: title = f"{title} ({version})" From 5e887ed479078a95a013c517817d9da5a885d36a Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Fri, 22 Dec 2023 13:19:01 -0800 Subject: [PATCH 2/6] Tag files with isrc --- streamrip/metadata/tagger.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/streamrip/metadata/tagger.py b/streamrip/metadata/tagger.py index 251fb23..d2eff84 100644 --- a/streamrip/metadata/tagger.py +++ b/streamrip/metadata/tagger.py @@ -38,6 +38,7 @@ MP4_KEYS = ( None, None, None, + "---:com.apple.iTunes:ISRC", ) MP3_KEYS = ( @@ -61,6 +62,7 @@ MP3_KEYS = ( None, None, None, + id3.TSRC, ) METADATA_TYPES = ( @@ -84,6 +86,7 @@ METADATA_TYPES = ( "tracktotal", "disctotal", "date", + "isrc", ) @@ -170,6 +173,7 @@ class Container(Enum): "tracknumber", "discnumber", "composer", + "isrc", } if attr in in_trackmetadata: if attr == "album": From 906332e61d1fbf4167acfd2761edab80bb54ec22 Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Sun, 24 Dec 2023 11:15:24 -0800 Subject: [PATCH 3/6] Fix ISRC for mp4 files --- streamrip/metadata/tagger.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/streamrip/metadata/tagger.py b/streamrip/metadata/tagger.py index d2eff84..0bbafa1 100644 --- a/streamrip/metadata/tagger.py +++ b/streamrip/metadata/tagger.py @@ -38,7 +38,7 @@ MP4_KEYS = ( None, None, None, - "---:com.apple.iTunes:ISRC", + "----:com.apple.iTunes:ISRC", ) MP3_KEYS = ( @@ -116,7 +116,7 @@ class Container(Enum): elif self == Container.MP3: return self._tag_mp3(meta) elif self == Container.AAC: - return self._tag_aac(meta) + return self._tag_mp4(meta) # unreachable return [] @@ -150,13 +150,15 @@ class Container(Enum): out.append((v.__name__, v(encoding=3, text=text))) return out - def _tag_aac(self, meta: TrackMetadata): + def _tag_mp4(self, meta: TrackMetadata): out = [] for k, v in MP4_KEY.items(): if k == "tracknumber": text = [(meta.tracknumber, meta.album.tracktotal)] elif k == "discnumber": text = [(meta.discnumber, meta.album.disctotal)] + elif k == "isrc" and meta.isrc is not None: + text = meta.isrc.encode("utf-8") else: text = self._attr_from_meta(meta, k) From 86595984a0e042743d17b53005524ee634726025 Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Sun, 24 Dec 2023 11:22:49 -0800 Subject: [PATCH 4/6] Explanation of ISRC edge case --- streamrip/metadata/tagger.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/streamrip/metadata/tagger.py b/streamrip/metadata/tagger.py index 0bbafa1..aa9286d 100644 --- a/streamrip/metadata/tagger.py +++ b/streamrip/metadata/tagger.py @@ -158,6 +158,9 @@ class Container(Enum): elif k == "discnumber": text = [(meta.discnumber, meta.album.disctotal)] elif k == "isrc" and meta.isrc is not None: + # because ISRC is an mp4 freeform value (not supported natively) + # we have to pass in the actual bytes to mutagen + # See mutagen.MP4Tags.__render_freeform text = meta.isrc.encode("utf-8") else: text = self._attr_from_meta(meta, k) From df44ae75a5152f7b828c762148f3ca69d70f56bc Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Sun, 24 Dec 2023 11:26:02 -0800 Subject: [PATCH 5/6] Handle ID3NoHeaderError for qobuz mp3 --- streamrip/metadata/tagger.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/streamrip/metadata/tagger.py b/streamrip/metadata/tagger.py index aa9286d..5c74f1d 100644 --- a/streamrip/metadata/tagger.py +++ b/streamrip/metadata/tagger.py @@ -8,6 +8,7 @@ from mutagen.flac import FLAC, Picture from mutagen.id3 import ( APIC, # type: ignore ID3, + ID3NoHeaderError, ) from mutagen.mp4 import MP4, MP4Cover @@ -106,7 +107,10 @@ class Container(Enum): elif self == Container.AAC: return MP4(path) elif self == Container.MP3: - return ID3(path) + try: + return ID3(path) + except ID3NoHeaderError: + return ID3() # unreachable return {} From 68c8ea0946dfa57dee9b212f706265f1dd4fd1bd Mon Sep 17 00:00:00 2001 From: Nathan Thomas Date: Wed, 27 Dec 2023 14:20:51 -0800 Subject: [PATCH 6/6] ISRC for soundcloud --- streamrip/metadata/track_metadata.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/streamrip/metadata/track_metadata.py b/streamrip/metadata/track_metadata.py index 2560aec..8572321 100644 --- a/streamrip/metadata/track_metadata.py +++ b/streamrip/metadata/track_metadata.py @@ -121,6 +121,7 @@ class TrackMetadata: def from_soundcloud(cls, album: AlbumMetadata, resp: dict) -> TrackMetadata: track = resp track_id = track["id"] + isrc = typed(safe_get(track, "publisher_metadata", "isrc"), str | None) bit_depth, sampling_rate = None, None explicit = typed( safe_get(track, "publisher_metadata", "explicit", default=False), @@ -147,6 +148,7 @@ class TrackMetadata: tracknumber=tracknumber, discnumber=0, composer=None, + isrc=isrc, ) @classmethod