From: Marcel van der Veldt Date: Tue, 14 Mar 2023 19:29:23 +0000 (+0100) Subject: Fix parsing tags from smb provider (#530) X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=e4120d9e5570864034ef8042680f7d8cd9225148;p=music-assistant-server.git Fix parsing tags from smb provider (#530) Fix some issues with parsing tags (e.g. duration) from the SMB music provider and set some other defaults --- diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 97f5364c..41123d49 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip build setuptools - pip install .[test] + pip install . .[test] - name: Lint/test with pre-commit run: pre-commit run --all-files @@ -47,6 +47,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip build setuptools - pip install .[test] + pip install . .[test] - name: Pytest run: pytest --durations 10 --cov-report term-missing --cov=music_assistant --cov-report=xml tests/ diff --git a/music_assistant/server/helpers/compare.py b/music_assistant/server/helpers/compare.py index 0c8fe79e..114eae97 100644 --- a/music_assistant/server/helpers/compare.py +++ b/music_assistant/server/helpers/compare.py @@ -2,7 +2,6 @@ from __future__ import annotations from music_assistant.common.helpers.util import create_safe_string, create_sort_name -from music_assistant.common.models.enums import AlbumType from music_assistant.common.models.media_items import ( Album, Artist, @@ -238,11 +237,9 @@ def compare_track(left_track: Track, right_track: Track): for right_album in right_track.albums: if compare_album(left_album, right_album): return True - # fallback: both albums are compilations and (near-exact) track duration match - if ( - abs(left_track.duration - right_track.duration) <= 2 - and left_track.album.album_type in (AlbumType.UNKNOWN, AlbumType.COMPILATION) - and right_track.album.album_type in (AlbumType.UNKNOWN, AlbumType.COMPILATION) + # fallback: exact album match and (near-exact) track duration match + if abs(left_track.duration - right_track.duration) <= 3 and compare_album( + left_track.album, right_track.album ): return True return False diff --git a/music_assistant/server/helpers/tags.py b/music_assistant/server/helpers/tags.py index 0081a7dd..fd064043 100644 --- a/music_assistant/server/helpers/tags.py +++ b/music_assistant/server/helpers/tags.py @@ -199,7 +199,9 @@ class AudioTags: return self.tags.get(key, default) -async def parse_tags(input_file: str | AsyncGenerator[bytes, None]) -> AudioTags: +async def parse_tags( + input_file: str | AsyncGenerator[bytes, None], file_size: int | None = None +) -> AudioTags: """Parse tags from a media file. input_file may be a (local) filename/url accessible by ffmpeg or @@ -227,12 +229,17 @@ async def parse_tags(input_file: str | AsyncGenerator[bytes, None]) -> AudioTags if file_path == "-": # feed the file contents to the process async def chunk_feeder(): - # pylint: disable=protected-access + bytes_written = 0 async for chunk in input_file: try: await proc.write(chunk) except BrokenPipeError: break # race-condition: read enough data for tags + + # grabbing the first 5MB is enough to get the embedded tags + bytes_written += len(chunk) + if bytes_written > (5 * 1024000): + break proc.write_eof() proc.attach_task(chunk_feeder()) @@ -242,7 +249,11 @@ async def parse_tags(input_file: str | AsyncGenerator[bytes, None]) -> AudioTags data = json.loads(res) if error := data.get("error"): raise InvalidDataError(error["string"]) - return AudioTags.parse(data) + tags = AudioTags.parse(data) + if not tags.duration and file_size and tags.bit_rate: + # estimate duration from filesize/bitrate + tags.duration = int((file_size * 8) / tags.bit_rate) + return tags except (KeyError, ValueError, JSONDecodeError, InvalidDataError) as err: raise InvalidDataError(f"Unable to retrieve info for {file_path}: {str(err)}") from err diff --git a/music_assistant/server/providers/filesystem_local/base.py b/music_assistant/server/providers/filesystem_local/base.py index 6c8f85e6..9814cb19 100644 --- a/music_assistant/server/providers/filesystem_local/base.py +++ b/music_assistant/server/providers/filesystem_local/base.py @@ -343,7 +343,7 @@ class FileSystemProviderBase(MusicProvider): # parse tags input_file = file_item.local_path or self.read_file_content(file_item.absolute_path) - tags = await parse_tags(input_file) + tags = await parse_tags(input_file, file_item.file_size) name, version = parse_title_and_version(tags.title) track = Track( diff --git a/music_assistant/server/providers/filesystem_smb/manifest.json b/music_assistant/server/providers/filesystem_smb/manifest.json index 391a8ff2..ae7844d8 100644 --- a/music_assistant/server/providers/filesystem_smb/manifest.json +++ b/music_assistant/server/providers/filesystem_smb/manifest.json @@ -65,7 +65,7 @@ "key": "is_direct_tcp", "type": "boolean", "label": "Use Direct TCP", - "default_value": false, + "default_value": true, "description": "Controls whether the NetBIOS over TCP/IP (is_direct_tcp=False) or the newer Direct hosting of SMB over TCP/IP (is_direct_tcp=True) will be used for the communication. The default parameter is False which will use NetBIOS over TCP/IP for wider compatibility (TCP port: 139).", "advanced": true, "required": false