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:
@@ -78,14 +78,15 @@ class DispatcharrRepository(private val auth: DeviceAuth) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun streamUrl(id: Int): String {
|
// The live proxy resolves channels by UUID (integer ids 404).
|
||||||
val base = "${auth.serverUrl}/proxy/ts/stream/$id"
|
private fun streamUrl(uuid: String): String {
|
||||||
|
val base = "${auth.serverUrl}/proxy/ts/stream/$uuid"
|
||||||
return if (outputProfile.isNotEmpty()) "$base?output_profile=$outputProfile" else base
|
return if (outputProfile.isNotEmpty()) "$base?output_profile=$outputProfile" else base
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Re-derive stream URLs (e.g. after the output profile changed). */
|
/** Re-derive stream URLs (e.g. after the output profile changed). */
|
||||||
fun rebuildStreamUrls() {
|
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> {
|
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()) {
|
for (i in 0 until results.length()) {
|
||||||
val obj = results.getJSONObject(i)
|
val obj = results.getJSONObject(i)
|
||||||
val id = obj.getInt("id")
|
val id = obj.getInt("id")
|
||||||
|
val uuid = obj.optString("uuid")
|
||||||
|
if (uuid.isEmpty() || obj.optBoolean("hidden_from_output")) continue
|
||||||
list.add(
|
list.add(
|
||||||
Channel(
|
Channel(
|
||||||
name = obj.optString("name"),
|
name = obj.optString("effective_name").ifEmpty { obj.optString("name") },
|
||||||
url = streamUrl(id),
|
url = streamUrl(uuid),
|
||||||
group = groups[obj.optInt("channel_group_id")].orEmpty(),
|
group = groups[obj.optInt("channel_group_id")].orEmpty(),
|
||||||
logo = "",
|
logo = "",
|
||||||
tvgId = obj.optString("tvg_id"),
|
tvgId = obj.optString("effective_tvg_id").ifEmpty { obj.optString("tvg_id") },
|
||||||
backendId = id,
|
backendId = id,
|
||||||
|
streamKey = uuid,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ data class Channel(
|
|||||||
val logo: String,
|
val logo: String,
|
||||||
val tvgId: String = "",
|
val tvgId: String = "",
|
||||||
val backendId: Int = 0,
|
val backendId: Int = 0,
|
||||||
|
val streamKey: String = "",
|
||||||
) {
|
) {
|
||||||
fun toJson(): JSONObject = JSONObject()
|
fun toJson(): JSONObject = JSONObject()
|
||||||
.put("name", name)
|
.put("name", name)
|
||||||
@@ -18,6 +19,7 @@ data class Channel(
|
|||||||
.put("logo", logo)
|
.put("logo", logo)
|
||||||
.put("tvgId", tvgId)
|
.put("tvgId", tvgId)
|
||||||
.put("backendId", backendId)
|
.put("backendId", backendId)
|
||||||
|
.put("streamKey", streamKey)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromJson(obj: JSONObject): Channel = Channel(
|
fun fromJson(obj: JSONObject): Channel = Channel(
|
||||||
@@ -27,6 +29,7 @@ data class Channel(
|
|||||||
logo = obj.optString("logo"),
|
logo = obj.optString("logo"),
|
||||||
tvgId = obj.optString("tvgId"),
|
tvgId = obj.optString("tvgId"),
|
||||||
backendId = obj.optInt("backendId"),
|
backendId = obj.optInt("backendId"),
|
||||||
|
streamKey = obj.optString("streamKey"),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun listToJson(channels: List<Channel>): JSONArray {
|
fun listToJson(channels: List<Channel>): JSONArray {
|
||||||
|
|||||||
Reference in New Issue
Block a user