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> { async fn track_stream(&self, id: &str) -> Result<String, FetchError> {
let dtos: Vec<TrackDto> = self // Try the configured format first, then fall back to Jamendo's native
.get( // default (mp31): some formats — notably mp32 — return an empty `audio`
"tracks", // URL for many tracks, and an empty stream must degrade to the freely
&[ // streamable one rather than skip the track.
("id", id.to_string()), let mut attempts: Vec<Vec<(&str, String)>> = vec![vec![
("audioformat", self.audioformat.clone()), ("id", id.to_string()),
], ("audioformat", self.audioformat.clone()),
) ]];
.await?; if !self.audioformat.is_empty() {
let audio = dtos attempts.push(vec![("id", id.to_string())]);
.into_iter() }
.next() for query in &attempts {
.and_then(|t| t.audio) let dtos: Vec<TrackDto> = self.get("tracks", query).await?;
.filter(|u| !u.is_empty()) if let Some(audio) = dtos.into_iter().next().and_then(|t| t.audio) {
.ok_or(FetchError::NotStreamable)?; if !audio.is_empty() {
Ok(audio) 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; pub const DEFAULT_ALBUM_TRACKS: usize = 200;
/// Default per-request timeout in seconds. /// Default per-request timeout in seconds.
pub const DEFAULT_CALL_TIMEOUT_SECS: u64 = 30; pub const DEFAULT_CALL_TIMEOUT_SECS: u64 = 30;
/// Default requested audio format (`mp32` = higher-bitrate MP3). /// Default requested audio streaming format. `mp31` is Jamendo's freely
pub const DEFAULT_AUDIOFORMAT: &str = "mp32"; /// 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**: /// Provider settings, persisted as `jamendo.toml`. `client_id` is **required**:
/// without it the provider does not mount (D5). The rest have defaults. /// without it the provider does not mount (D5). The rest have defaults.