e45ef785cf
The Playback quality setting now drives streaming: getStreamUrl appends ?quality= and useAudioPlayer feeds the server-synced streamQuality, so the backend transcodes on demand (miss → original). Adds an optimizeTrack mutation and an Optimize action in the metadata editor to warm a track's rendition. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
import { getApiBaseUrl } from '../../config/runtime-config';
|
|
|
|
/**
|
|
* Audio stream URL for the `<audio>` element. The access token rides as a query
|
|
* param because `<audio>` can't send an `Authorization` header; the backend
|
|
* accepts `?token=` on `GET /stream/{id}` for exactly this reason.
|
|
*/
|
|
export function getStreamUrl(
|
|
trackId: string,
|
|
token: string,
|
|
quality?: string,
|
|
): string {
|
|
const base = getApiBaseUrl();
|
|
const q =
|
|
quality && quality !== 'original'
|
|
? `&quality=${encodeURIComponent(quality)}`
|
|
: '';
|
|
return `${base}/stream/${trackId}?token=${encodeURIComponent(token)}${q}`;
|
|
}
|
|
|
|
export function getCoverUrl(artUrl: string | undefined): string | undefined {
|
|
if (!artUrl) return undefined;
|
|
if (artUrl.startsWith('http://') || artUrl.startsWith('https://'))
|
|
return artUrl;
|
|
const base = getApiBaseUrl();
|
|
return `${base}${artUrl}`;
|
|
}
|
|
|
|
/**
|
|
* Cover image URL for a track, served by `GET /tracks/{id}/cover`. Like the
|
|
* audio stream, an `<img>` can't send an `Authorization` header, so the access
|
|
* token rides as `?token=`. Returns undefined when the track has no cover.
|
|
*/
|
|
export function getTrackCoverUrl(
|
|
trackId: string,
|
|
token: string,
|
|
hasCover: boolean,
|
|
): string | undefined {
|
|
if (!hasCover) return undefined;
|
|
const base = getApiBaseUrl();
|
|
return `${base}/tracks/${trackId}/cover?token=${encodeURIComponent(token)}`;
|
|
}
|
|
|
|
/**
|
|
* Cover image URL for an album, served by `GET /albums/{id}/cover`. Same
|
|
* `?token=` rationale as the track cover. Returns undefined when the album has
|
|
* no cover (so callers fall back to generated tile art).
|
|
*/
|
|
export function getAlbumCoverUrl(
|
|
albumId: string,
|
|
token: string,
|
|
hasCover: boolean,
|
|
): string | undefined {
|
|
if (!hasCover) return undefined;
|
|
const base = getApiBaseUrl();
|
|
return `${base}/albums/${albumId}/cover?token=${encodeURIComponent(token)}`;
|
|
}
|