Skip to content

Commit 478e9b6

Browse files
blacklightYutongGu
authored andcommitted
fix(playback): Avoid MPD manifest parsing to fix regression with new TIDAL group="main" manifests
TIDAL appears to have changed the MPEG-DASH MPD manifests returned for some streams to include non-numeric values in `<AdaptationSet group="...">` (e.g. group="main"). The current `mpegdash` parser expects group to be an integer and raises a `ValueError`, which `tidalapi` wraps as `ManifestDecodeError`. This caused `mopidy-tidal` playback to fail and tracks to be marked “not playable”. This PR updates mopidy-tidal’s playback provider to avoid parsing MPD manifests via tidalapi/mpegdash. For MPD manifests we only need to persist the MPD XML and return a `file://` URI, so parsing is unnecessary. **Root cause** - [`tidalapi.StreamManifest`](https://github.com/EbbLabs/python-tidal/blob/08742362ee8cef7df1362387cef60c2846aa84ee/tidalapi/media.py#L644) → [`DashInfo.from_mpd()`](https://github.com/EbbLabs/python-tidal/blob/08742362ee8cef7df1362387cef60c2846aa84ee/tidalapi/media.py#L770) → `mpegdash` parser - New MPD contains: `<AdaptationSet ... group="main" ...>` - [`mpegdash` tries to parse group as int](https://github.com/sangwonl/python-mpegdash/blob/48b52122cdbcaebe1804b79f77d05dfc1ce32900/mpegdash/nodes.py#L782) → `ValueError` → `tidalapi.exceptions.ManifestDecodeError` - Mopidy logs: backend exception + _Track is not playable_ **Changes** - **MPD path** (`ManifestMimeType.MPD`) - Stop calling `stream.get_stream_manifest()` (this triggers MPD parsing and the crash) - Use `stream.get_manifest_data()` to fetch raw MPD XML - Write the MPD to `manifest.mpd` in the extension cache directory - Return `file://…/manifest.mpd` for playback (same end result as before, but without parsing) - **BTS path** (ManifestMimeType.BTS) - Keep existing behavior using stream.get_stream_manifest() **Why this is safe** mopidy-tidal already ultimately plays MPD by writing it to disk and handing Mopidy a `file://` URI. The parsed MPD data from tidalapi wasn’t required for playback logic here; it was effectively only used for logging (codecs). Closes: EbbLabs/python-tidal#397
1 parent d52bd7c commit 478e9b6

1 file changed

Lines changed: 24 additions & 11 deletions

File tree

mopidy_tidal/playback.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,18 @@ def translate_uri(self, uri):
3838
)
3939

4040
stream = session.track(track_id).get_stream()
41-
manifest = stream.get_stream_manifest()
4241
logger.info("MimeType:{}".format(stream.manifest_mime_type))
43-
logger.info(
44-
"Starting playback of track:{}, (quality:{}, codec:{}, {}bit/{}Hz)".format(
45-
track_id,
46-
stream.audio_quality,
47-
manifest.get_codecs(),
48-
stream.bit_depth,
49-
stream.sample_rate,
50-
)
51-
)
5242

5343
if stream.manifest_mime_type == ManifestMimeType.MPD:
44+
logger.info(
45+
"Starting playback of track:{}, (quality:{}, {}bit/{}Hz)".format(
46+
track_id,
47+
stream.audio_quality,
48+
stream.bit_depth,
49+
stream.sample_rate,
50+
)
51+
)
52+
5453
data = stream.get_manifest_data()
5554
if data:
5655
mpd_path = Path(
@@ -63,4 +62,18 @@ def translate_uri(self, uri):
6362
else:
6463
raise AttributeError("No MPD manifest available!")
6564
elif stream.manifest_mime_type == ManifestMimeType.BTS:
66-
return manifest.get_urls()
65+
manifest = stream.get_stream_manifest()
66+
logger.info(
67+
"Starting playback of track:{}, (quality:{}, codec:{}, {}bit/{}Hz)".format(
68+
track_id,
69+
stream.audio_quality,
70+
manifest.get_codecs(),
71+
stream.bit_depth,
72+
stream.sample_rate,
73+
)
74+
)
75+
urls = manifest.get_urls()
76+
if isinstance(urls, list):
77+
return urls[0]
78+
else:
79+
return urls

0 commit comments

Comments
 (0)