For an ANIME title, getMedia returns EntryMedia.Playback(descriptor):
@Serializable
class Server(val id: String, val name: String, val dub: String, val playlistUrl: String)
override suspend fun getMedia(chapter: SEntryChapter, selection: PlaybackSelection): EntryMedia {
val all = servers(chapter)
val dub = all.firstOrNull { it.dub == selection.dubKey }?.dub ?: all.first().dub
val dubbed = all.filter { it.dub == dub }
val server = dubbed.firstOrNull { it.id == selection.serverKey } ?: dubbed.first()
return EntryMedia.Playback(
PlaybackDescriptor(
selection = PlaybackSelection(dubKey = dub, serverKey = server.id),
dubs = all.map { it.dub }.distinct().map { VideoPlaybackOption(key = it, label = it.uppercase()) },
servers = dubbed.map { VideoPlaybackOption(key = it.id, label = it.name) },
streams = listOf(
VideoStream(
request = VideoRequest(server.playlistUrl, headers = mapOf("Referer" to "$baseUrl/")),
label = server.name,
type = VideoStreamType.HLS,
key = "hls",
),
),
),
)
}
dataclass PlaybackDescriptor -
What
EntryMedia.Playbackholds.Fields
selection:PlaybackSelection = PlaybackSelection() - The choices the streams were found for.
dubs:List<VideoPlaybackOption> = emptyList() - The dubs the site offers.
servers:List<VideoPlaybackOption> = emptyList() - The servers the site offers for the selected dub, in the order Katari should try them.
sourceQualities:List<VideoPlaybackOption> = emptyList() - The qualities, for a site that serves each one separately.
streams:List<VideoStream> = emptyList() - The streams for the selection.
dataclass PlaybackSelection( dubKey: String? = null, serverKey: String? = null, streamKey: String? = null, sourceQualityKey: String? = null ) - Each a key you gave, or null for none chosen.
dataclass VideoPlaybackOption( key: String, label: String, description: String? = null ) -
labelis shown in the player, anddescriptionunder it.
The player shows the message of an exception getMedia throws. Katari gives up on getMedia after 15
seconds.