Fix musicbrainz recording id tag in mp3 files
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 20 Jun 2024 15:32:43 +0000 (17:32 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 20 Jun 2024 15:32:43 +0000 (17:32 +0200)
music_assistant/server/helpers/tags.py
pyproject.toml
requirements_all.txt

index 149e45a887bcef8fca36eaa2bb8c9fe4329e12ff..be8d66f446a4a156c6628e07d9c5774d66f323d5 100644 (file)
@@ -11,6 +11,8 @@ from dataclasses import dataclass
 from json import JSONDecodeError
 from typing import TYPE_CHECKING, Any
 
+import eyed3
+
 from music_assistant.common.helpers.util import try_parse_int
 from music_assistant.common.models.enums import AlbumType
 from music_assistant.common.models.errors import InvalidDataError
@@ -219,8 +221,6 @@ class AudioTags:
             return tag
         if tag := self.tags.get("musicbrainzrecordingid"):
             return tag
-        if tag := self.tags.get("musicbrainzreleasetrackid"):
-            return tag
         return self.tags.get("musicbrainztrackid")
 
     @property
@@ -430,6 +430,17 @@ async def parse_tags(
             tags.duration = int((file_size * 8) / tags.bit_rate)
         if not tags.duration and tags.raw.get("format", {}).get("duration"):
             tags.duration = float(tags.raw["format"]["duration"])
+
+        if file_path.endswith(".mp3") and "musicbrainzrecordingid" not in tags.tags:
+            # eyed3 is able to extract the musicbrainzrecordingid from the unique file id
+            # this is actually a bug in ffmpeg/ffprobe which does not expose this tag
+            # so we use this as alternative approach for mp3 files
+            audiofile = await asyncio.to_thread(eyed3.load, file_path)
+            for uf_id in audiofile.tag.unique_file_ids:
+                if uf_id.owner_id == b"http://musicbrainz.org" and uf_id.uniq_id:
+                    tags.tags["musicbrainzrecordingid"] = uf_id.uniq_id.decode()
+                    break
+
         return tags
     except (KeyError, ValueError, JSONDecodeError, InvalidDataError) as err:
         msg = f"Unable to retrieve info for {file_path}: {err!s}"
index 6beed63c43e3f07771a08835a8d04aa3c5921ef5..2bef6cb94bf12f78adb68610ff5548d0f6dcd76d 100644 (file)
@@ -28,6 +28,7 @@ server = [
   "certifi==2024.6.2",
   "colorlog==6.8.2",
   "aiosqlite==0.20.0",
+  "eyeD3==0.9.7",
   "python-slugify==8.0.4",
   "mashumaro==3.13.1",
   "memory-tempfile==2.2.3",
index eea9419aa9bdfb631d0f3ae5c98cc72cb8c1f5d1..f89879642287fe4773db210a94c38d3a42903de3 100644 (file)
@@ -16,6 +16,7 @@ colorlog==6.8.2
 cryptography==42.0.8
 deezer-python-async==0.3.0
 defusedxml==0.7.1
+eyeD3==0.9.7
 faust-cchardet>=2.1.18
 git+https://github.com/MarvinSchenkel/pytube.git
 hass-client==1.1.1