Fix Dispatcharr playback: stream URLs must use the channel UUID

The live proxy resolves /proxy/ts/stream/<key> by channel uuid (or stream
hash) — integer ids 404, so every Dispatcharr channel failed to play.
Streams now use the uuid, channels use effective_name/effective_tvg_id and
skip hidden_from_output entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 21:20:50 +02:00
parent 24d18f1066
commit 4dd59ed7aa
2 changed files with 13 additions and 6 deletions

View File

@@ -78,14 +78,15 @@ class DispatcharrRepository(private val auth: DeviceAuth) {
}
}
private fun streamUrl(id: Int): String {
val base = "${auth.serverUrl}/proxy/ts/stream/$id"
// The live proxy resolves channels by UUID (integer ids 404).
private fun streamUrl(uuid: String): String {
val base = "${auth.serverUrl}/proxy/ts/stream/$uuid"
return if (outputProfile.isNotEmpty()) "$base?output_profile=$outputProfile" else base
}
/** Re-derive stream URLs (e.g. after the output profile changed). */
fun rebuildStreamUrls() {
channels.value = channels.value.map { it.copy(url = streamUrl(it.backendId)) }
channels.value = channels.value.map { it.copy(url = streamUrl(it.streamKey)) }
}
private suspend fun fetchGroups(token: String): Map<Int, String> {
@@ -107,14 +108,17 @@ class DispatcharrRepository(private val auth: DeviceAuth) {
for (i in 0 until results.length()) {
val obj = results.getJSONObject(i)
val id = obj.getInt("id")
val uuid = obj.optString("uuid")
if (uuid.isEmpty() || obj.optBoolean("hidden_from_output")) continue
list.add(
Channel(
name = obj.optString("name"),
url = streamUrl(id),
name = obj.optString("effective_name").ifEmpty { obj.optString("name") },
url = streamUrl(uuid),
group = groups[obj.optInt("channel_group_id")].orEmpty(),
logo = "",
tvgId = obj.optString("tvg_id"),
tvgId = obj.optString("effective_tvg_id").ifEmpty { obj.optString("tvg_id") },
backendId = id,
streamKey = uuid,
)
)
}

View File

@@ -10,6 +10,7 @@ data class Channel(
val logo: String,
val tvgId: String = "",
val backendId: Int = 0,
val streamKey: String = "",
) {
fun toJson(): JSONObject = JSONObject()
.put("name", name)
@@ -18,6 +19,7 @@ data class Channel(
.put("logo", logo)
.put("tvgId", tvgId)
.put("backendId", backendId)
.put("streamKey", streamKey)
companion object {
fun fromJson(obj: JSONObject): Channel = Channel(
@@ -27,6 +29,7 @@ data class Channel(
logo = obj.optString("logo"),
tvgId = obj.optString("tvgId"),
backendId = obj.optInt("backendId"),
streamKey = obj.optString("streamKey"),
)
fun listToJson(channels: List<Channel>): JSONArray {