mirror of https://github.com/nathom/streamrip.git
commit
d1b5bd2958
|
@ -8,6 +8,7 @@ from mutagen.flac import FLAC, Picture
|
||||||
from mutagen.id3 import (
|
from mutagen.id3 import (
|
||||||
APIC, # type: ignore
|
APIC, # type: ignore
|
||||||
ID3,
|
ID3,
|
||||||
|
ID3NoHeaderError,
|
||||||
)
|
)
|
||||||
from mutagen.mp4 import MP4, MP4Cover
|
from mutagen.mp4 import MP4, MP4Cover
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ MP4_KEYS = (
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
"----:com.apple.iTunes:ISRC",
|
||||||
)
|
)
|
||||||
|
|
||||||
MP3_KEYS = (
|
MP3_KEYS = (
|
||||||
|
@ -61,6 +63,7 @@ MP3_KEYS = (
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
id3.TSRC,
|
||||||
)
|
)
|
||||||
|
|
||||||
METADATA_TYPES = (
|
METADATA_TYPES = (
|
||||||
|
@ -84,6 +87,7 @@ METADATA_TYPES = (
|
||||||
"tracktotal",
|
"tracktotal",
|
||||||
"disctotal",
|
"disctotal",
|
||||||
"date",
|
"date",
|
||||||
|
"isrc",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,7 +107,10 @@ class Container(Enum):
|
||||||
elif self == Container.AAC:
|
elif self == Container.AAC:
|
||||||
return MP4(path)
|
return MP4(path)
|
||||||
elif self == Container.MP3:
|
elif self == Container.MP3:
|
||||||
return ID3(path)
|
try:
|
||||||
|
return ID3(path)
|
||||||
|
except ID3NoHeaderError:
|
||||||
|
return ID3()
|
||||||
# unreachable
|
# unreachable
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
@ -113,7 +120,7 @@ class Container(Enum):
|
||||||
elif self == Container.MP3:
|
elif self == Container.MP3:
|
||||||
return self._tag_mp3(meta)
|
return self._tag_mp3(meta)
|
||||||
elif self == Container.AAC:
|
elif self == Container.AAC:
|
||||||
return self._tag_aac(meta)
|
return self._tag_mp4(meta)
|
||||||
# unreachable
|
# unreachable
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -147,13 +154,18 @@ class Container(Enum):
|
||||||
out.append((v.__name__, v(encoding=3, text=text)))
|
out.append((v.__name__, v(encoding=3, text=text)))
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def _tag_aac(self, meta: TrackMetadata):
|
def _tag_mp4(self, meta: TrackMetadata):
|
||||||
out = []
|
out = []
|
||||||
for k, v in MP4_KEY.items():
|
for k, v in MP4_KEY.items():
|
||||||
if k == "tracknumber":
|
if k == "tracknumber":
|
||||||
text = [(meta.tracknumber, meta.album.tracktotal)]
|
text = [(meta.tracknumber, meta.album.tracktotal)]
|
||||||
elif k == "discnumber":
|
elif k == "discnumber":
|
||||||
text = [(meta.discnumber, meta.album.disctotal)]
|
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:
|
else:
|
||||||
text = self._attr_from_meta(meta, k)
|
text = self._attr_from_meta(meta, k)
|
||||||
|
|
||||||
|
@ -170,6 +182,7 @@ class Container(Enum):
|
||||||
"tracknumber",
|
"tracknumber",
|
||||||
"discnumber",
|
"discnumber",
|
||||||
"composer",
|
"composer",
|
||||||
|
"isrc",
|
||||||
}
|
}
|
||||||
if attr in in_trackmetadata:
|
if attr in in_trackmetadata:
|
||||||
if attr == "album":
|
if attr == "album":
|
||||||
|
|
|
@ -36,6 +36,7 @@ class TrackMetadata:
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_qobuz(cls, album: AlbumMetadata, resp: dict) -> TrackMetadata | None:
|
def from_qobuz(cls, album: AlbumMetadata, resp: dict) -> TrackMetadata | None:
|
||||||
title = typed(resp["title"].strip(), str)
|
title = typed(resp["title"].strip(), str)
|
||||||
|
isrc = typed(resp["isrc"], str)
|
||||||
streamable = typed(resp.get("streamable", False), bool)
|
streamable = typed(resp.get("streamable", False), bool)
|
||||||
|
|
||||||
if not streamable:
|
if not streamable:
|
||||||
|
@ -81,11 +82,13 @@ class TrackMetadata:
|
||||||
tracknumber=tracknumber,
|
tracknumber=tracknumber,
|
||||||
discnumber=discnumber,
|
discnumber=discnumber,
|
||||||
composer=composer,
|
composer=composer,
|
||||||
|
isrc=isrc,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_deezer(cls, album: AlbumMetadata, resp) -> TrackMetadata | None:
|
def from_deezer(cls, album: AlbumMetadata, resp) -> TrackMetadata | None:
|
||||||
track_id = str(resp["id"])
|
track_id = str(resp["id"])
|
||||||
|
isrc = typed(resp["isrc"], str)
|
||||||
bit_depth = 16
|
bit_depth = 16
|
||||||
sampling_rate = 44.1
|
sampling_rate = 44.1
|
||||||
explicit = typed(resp["explicit_lyrics"], bool)
|
explicit = typed(resp["explicit_lyrics"], bool)
|
||||||
|
@ -111,12 +114,14 @@ class TrackMetadata:
|
||||||
tracknumber=tracknumber,
|
tracknumber=tracknumber,
|
||||||
discnumber=discnumber,
|
discnumber=discnumber,
|
||||||
composer=composer,
|
composer=composer,
|
||||||
|
isrc=isrc,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_soundcloud(cls, album: AlbumMetadata, resp: dict) -> TrackMetadata:
|
def from_soundcloud(cls, album: AlbumMetadata, resp: dict) -> TrackMetadata:
|
||||||
track = resp
|
track = resp
|
||||||
track_id = track["id"]
|
track_id = track["id"]
|
||||||
|
isrc = typed(safe_get(track, "publisher_metadata", "isrc"), str | None)
|
||||||
bit_depth, sampling_rate = None, None
|
bit_depth, sampling_rate = None, None
|
||||||
explicit = typed(
|
explicit = typed(
|
||||||
safe_get(track, "publisher_metadata", "explicit", default=False),
|
safe_get(track, "publisher_metadata", "explicit", default=False),
|
||||||
|
@ -143,15 +148,16 @@ class TrackMetadata:
|
||||||
tracknumber=tracknumber,
|
tracknumber=tracknumber,
|
||||||
discnumber=0,
|
discnumber=0,
|
||||||
composer=None,
|
composer=None,
|
||||||
|
isrc=isrc,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_tidal(cls, album: AlbumMetadata, track) -> TrackMetadata:
|
def from_tidal(cls, album: AlbumMetadata, track) -> TrackMetadata:
|
||||||
title = typed(track["title"], str).strip()
|
title = typed(track["title"], str).strip()
|
||||||
item_id = str(track["id"])
|
item_id = str(track["id"])
|
||||||
|
isrc = typed(track["isrc"], str)
|
||||||
version = track.get("version")
|
version = track.get("version")
|
||||||
explicit = track.get("explicit", False)
|
explicit = track.get("explicit", False)
|
||||||
isrc = track.get("isrc")
|
|
||||||
if version:
|
if version:
|
||||||
title = f"{title} ({version})"
|
title = f"{title} ({version})"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue