fix encoding detection
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 17 Oct 2024 10:43:10 +0000 (12:43 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 17 Oct 2024 10:43:10 +0000 (12:43 +0200)
music_assistant/server/helpers/audio.py
music_assistant/server/helpers/util.py

index eda1fbb49f103d5d00f31652c8d3d82abf856af2..30a05ecb330413a0770f6eae294be2882972f0ff 100644 (file)
@@ -46,7 +46,7 @@ from .playlists import HLS_CONTENT_TYPES, IsHLSPlaylist, PlaylistItem, fetch_pla
 from .process import AsyncProcess, check_output, communicate
 from .tags import parse_tags
 from .throttle_retry import BYPASS_THROTTLER
-from .util import TimedAsyncGenerator, create_tempfile
+from .util import TimedAsyncGenerator, create_tempfile, detect_charset
 
 if TYPE_CHECKING:
     from music_assistant.common.models.player_queue import QueueItem
@@ -603,8 +603,9 @@ async def get_hls_radio_stream(
             substream_url, headers=HTTP_HEADERS, timeout=timeout
         ) as resp:
             resp.raise_for_status()
-            charset = resp.charset or "utf-8"
-            substream_m3u_data = await resp.text(charset)
+            raw_data = await resp.read()
+            encoding = resp.charset or await detect_charset(raw_data)
+            substream_m3u_data = raw_data.decode(encoding)
         # get chunk-parts from the substream
         hls_chunks = parse_m3u(substream_m3u_data)
         chunk_seconds = 0
@@ -679,8 +680,9 @@ async def get_hls_substream(
         url, allow_redirects=True, headers=HTTP_HEADERS, timeout=timeout
     ) as resp:
         resp.raise_for_status()
-        charset = resp.charset or "utf-8"
-        master_m3u_data = await resp.text(charset)
+        raw_data = await resp.read()
+        encoding = resp.charset or await detect_charset(raw_data)
+        master_m3u_data = raw_data.decode(encoding)
     substreams = parse_m3u(master_m3u_data)
     if any(x for x in substreams if x.length and not x.key):
         # this is already a substream!
index 95896f6d94aeaef940a5db3f9a64f937e33063a5..6cdde467bf6327a27f519d722368a0ddf765997d 100644 (file)
@@ -19,6 +19,7 @@ from importlib.metadata import version as pkg_version
 from types import TracebackType
 from typing import TYPE_CHECKING, Any, ParamSpec, Self, TypeVar
 
+import cchardet as chardet
 import ifaddr
 import memory_tempfile
 from zeroconf import IPVersion
@@ -181,6 +182,14 @@ async def close_async_generator(agen: AsyncGenerator[Any, None]) -> None:
     await agen.aclose()
 
 
+async def detect_charset(data: bytes, fallback="utf-8") -> str:
+    """Detect charset of raw data."""
+    try:
+        return (await asyncio.to_thread(chardet.detect, data))["encoding"]
+    except (ImportError, AttributeError):
+        return fallback
+
+
 class TaskManager:
     """
     Helper class to run many tasks at once.