jamendo: default to mp31 streaming and fall back when a format has no audio

The mp32 audioformat is not reliably provisioned for the streaming
audio URL — Jamendo returns an empty audio field for many tracks — so
mp32 as the default made playback fail with track is not streamable
even though metadata resolved. Default to mp31 (the freely streamable
MP3), and have track_stream retry without a forced format when the
configured one yields no audio, so a Pro-only format degrades to a
playable stream instead of skipping the track. Live-verified: default
config resolves a stream URL, and an explicit mp32 now falls back.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Test User 2026-07-24 16:02:13 +02:00
parent 7df5f0a1c2
commit 238e7c8f87
2 changed files with 25 additions and 18 deletions

View File

@ -260,22 +260,26 @@ impl Jam for JamApi {
}
async fn track_stream(&self, id: &str) -> Result<String, FetchError> {
let dtos: Vec<TrackDto> = self
.get(
"tracks",
&[
("id", id.to_string()),
("audioformat", self.audioformat.clone()),
],
)
.await?;
let audio = dtos
.into_iter()
.next()
.and_then(|t| t.audio)
.filter(|u| !u.is_empty())
.ok_or(FetchError::NotStreamable)?;
Ok(audio)
// Try the configured format first, then fall back to Jamendo's native
// default (mp31): some formats — notably mp32 — return an empty `audio`
// URL for many tracks, and an empty stream must degrade to the freely
// streamable one rather than skip the track.
let mut attempts: Vec<Vec<(&str, String)>> = vec![vec![
("id", id.to_string()),
("audioformat", self.audioformat.clone()),
]];
if !self.audioformat.is_empty() {
attempts.push(vec![("id", id.to_string())]);
}
for query in &attempts {
let dtos: Vec<TrackDto> = self.get("tracks", query).await?;
if let Some(audio) = dtos.into_iter().next().and_then(|t| t.audio) {
if !audio.is_empty() {
return Ok(audio);
}
}
}
Err(FetchError::NotStreamable)
}
}

View File

@ -42,8 +42,11 @@ pub const DEFAULT_SEARCH_RESULTS: usize = 50;
pub const DEFAULT_ALBUM_TRACKS: usize = 200;
/// Default per-request timeout in seconds.
pub const DEFAULT_CALL_TIMEOUT_SECS: u64 = 30;
/// Default requested audio format (`mp32` = higher-bitrate MP3).
pub const DEFAULT_AUDIOFORMAT: &str = "mp32";
/// Default requested audio streaming format. `mp31` is Jamendo's freely
/// streamable MP3; `mp32` (higher bitrate) is *not* reliably provisioned for the
/// streaming `audio` URL and comes back empty for many tracks, so it is a poor
/// default (a Pro account can still set it explicitly).
pub const DEFAULT_AUDIOFORMAT: &str = "mp31";
/// Provider settings, persisted as `jamendo.toml`. `client_id` is **required**:
/// without it the provider does not mount (D5). The rest have defaults.