Quality profiles#
Quality profiles, the playback downgrade ladder, and codec helpers.
Tidal’s playback API accepts a small set of API qualities
(LOW/HIGH/LOSSLESS/HI_RES_LOSSLESS/HI_RES). Hosts
think in profiles (what the user asked for). This module maps between
the two and decides, in order, which API qualities to attempt when the
requested one cannot be delivered.
The ladder encodes real Tidal behaviour (subscribed tier, per-track availability, spatial-audio quirks) and is the single place it lives.
- class tidalpy.quality.Quality(*values)[source]#
-
Host-facing quality profiles, ordered from lossy to highest lossless.
- HIGH = 'HIGH'#
- HI_RES_LOSSLESS = 'HI_RES_LOSSLESS'#
- LOSSLESS = 'LOSSLESS'#
- LOW = 'LOW'#
- tidalpy.quality.needs_stereo_fallback(requested_api_quality, codec)[source]#
A lossless request that came back spatial/proprietary/lossy.
Tidal sometimes answers a lossless request with a spatial or proprietary (MQA/E-AC3) rendition, which is useless for the DJ/CDJ use case; the caller should retry at
LOSSLESS.
- tidalpy.quality.parse_iso8601_duration(value)[source]#
PT4M48S-> whole seconds (0 for missing/invalid).Accepts a plain seconds value too (int/float, or a bare number string): the API paths disagree on the shape (v2 sends ISO-8601, v1 and search rows send plain seconds), and a bare number must not parse as 0 the way the unit regex would.
- tidalpy.quality.parse_quality(value, default=Quality.LOSSLESS)[source]#
Parse a human quality label into a
Qualityprofile.Accepts enum members, API quality names, and common aliases (
"Master","hifi","24/192", …). Falls back todefaultfor empty/unknown input.
- tidalpy.quality.playback_attempts(profile, media_tags=None, catalog_quality=None)[source]#
Ordered API qualities to attempt for a playback request.
- tidalpy.quality.quality_label(quality)[source]#
A short human label for an API quality (
"HI_RES_LOSSLESS"->"Max"). Unknown non-empty values pass through unchanged; empty/None give""— never"Unknown"in a file name.
- tidalpy.quality.quality_meets_profile(profile, delivered_quality, codec)[source]#
Whether a delivered stream satisfies the host’s profile.
Lossy profiles are always satisfied (Tidal may deliver
HIGHfor aLOWrequest, which is fine). Lossless profiles require an actually lossless delivery (API quality or codec).
- tidalpy.quality.representation_key(rep)[source]#
Fidelity ranking for DASH representations.
Higher is better: lossless first, then bit depth, sample rate, bandwidth, channels. Selection uses this key instead of trusting the XML order Tidal emits.
- tidalpy.quality.resolve_api_quality(profile, media_tags=None, catalog_quality=None)[source]#
The primary API quality to request for a profile and a track.
catalog_qualityis the track/album’s advertisedaudioQuality(e.g.HI_RES_LOSSLESS);media_tagsare itsmediaMetadata.tags. When the catalog already says the track is not hi-res, requestingHI_RES_LOSSLESSjust burns a 404, so the primary tier is lowered before any network call.When the catalog is unknown (playlist tracks are not album-bound), the primary tier stays
HI_RES_LOSSLESS— deliberately optimistic where the reference client falls back toLOSSLESS: hi-res playlist tracks would be silently downgraded otherwise, and the v2-first FLAC manifest keeps the cost of a miss to one extra request.
- tidalpy.quality.select_representation(representations, requested_api_quality)[source]#
Pick the best representation for a requested API quality.
non-audio / spatial representations are filtered out
lossless requests get the best lossless representation (for
HI_RES_LOSSLESSthe highest-rate FLAC specifically)everything else falls back to the best AAC, then the best overall
- tidalpy.quality.stereo_media_tags(tags)[source]#
Media tags with spatial-audio tags removed (stereo delivery only).
- tidalpy.quality.QUALITY_LABELS: dict[str, str] = {'HIGH': 'High', 'HI_RES': 'HiRes', 'HI_RES_LOSSLESS': 'Max', 'LOSSLESS': 'HiFi', 'LOW': 'Low'}#
Short human labels for API qualities — display and the
{quality}naming placeholder. Mirrors the reference client’s label set (its"Master (legacy)"becomes"HiRes": the old label is confusing in a file name).