Backend-neutral fetchArtistAlbums/fetchAlbumTracks/fetchInstantMix/ fetchLyrics, lyrics model + LRC parser, audio quality presets, music transcode (plex /music universal, jellyfin audio PlaybackInfo profile), station/InstantMix radio, music search, playlist type derivation, and audio download resolution.
46 lines
1.6 KiB
Dart
46 lines
1.6 KiB
Dart
/// [mediaSegment] selects the endpoint family: Jellyfin serves the identical
|
|
/// static-stream contract under `/Videos/{id}/stream` and `/Audio/{id}/stream`
|
|
/// — music track playback passes `'Audio'`.
|
|
String buildJellyfinDirectStreamUrl({
|
|
required String baseUrl,
|
|
required String accessToken,
|
|
required String deviceId,
|
|
required String itemId,
|
|
String mediaSegment = 'Videos',
|
|
String? container,
|
|
String? mediaSourceId,
|
|
String? playSessionId,
|
|
String? liveStreamId,
|
|
int? audioStreamIndex,
|
|
}) {
|
|
final params = <String, String>{
|
|
'Static': 'true',
|
|
'api_key': accessToken,
|
|
'DeviceId': deviceId,
|
|
'Container': ?container,
|
|
'MediaSourceId': ?mediaSourceId,
|
|
'PlaySessionId': ?playSessionId,
|
|
'LiveStreamId': ?liveStreamId,
|
|
'AudioStreamIndex': ?audioStreamIndex?.toString(),
|
|
};
|
|
final encodedItem = Uri.encodeComponent(itemId);
|
|
return '$baseUrl/$mediaSegment/$encodedItem/stream?${_encodeQuery(params)}';
|
|
}
|
|
|
|
String buildJellyfinTrickplayTileUrl({
|
|
required String baseUrl,
|
|
required String accessToken,
|
|
required String deviceId,
|
|
required String itemId,
|
|
required int width,
|
|
required int sheetIndex,
|
|
String? mediaSourceId,
|
|
}) {
|
|
final params = <String, String>{'api_key': accessToken, 'DeviceId': deviceId, 'MediaSourceId': ?mediaSourceId};
|
|
final encodedItem = Uri.encodeComponent(itemId);
|
|
return '$baseUrl/Videos/$encodedItem/Trickplay/$width/$sheetIndex.jpg?${_encodeQuery(params)}';
|
|
}
|
|
|
|
String _encodeQuery(Map<String, String> params) =>
|
|
params.entries.map((e) => '${e.key}=${Uri.encodeQueryComponent(e.value)}').join('&');
|