-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Description
Here is a new code adapted to their new logic (Kotlin)
/**
* Process DASH format streams (.livx extension) like Channel 10
* The method follows redirects, parses the DASH XML, and extracts the highest quality stream
*/
private suspend fun processDashUrl(url: String, userAgent: String, referer: String): String {
Log.d(TAG, "Processing DASH URL: $url")
// Build headers for DASH request
val headers = mapOf(
"User-Agent" to userAgent,
"Accept" to "*/*",
"Origin" to "https://tv10.co.il",
"Referer" to referer,
"Connection" to "keep-alive"
)
// Make request to get the DASH XML
val dashXml = makeRequest(url, userAgent, headers["Referer"], headers)
Log.d(TAG, "DASH XML response: $dashXml")
// Parse the DASH XML to extract video representations
// We're looking for the highest quality video stream
val baseUrlRegex = "<BaseURL>(.*?)</BaseURL>".toRegex()
val baseUrlMatch = baseUrlRegex.find(dashXml) ?: throw IOException("No BaseURL found in DASH XML")
val baseUrl = baseUrlMatch.groupValues[1]
Log.d(TAG, "Base URL: $baseUrl")
// Extract video representations with their bandwidth and resolution
val videoRepRegex = "<Representation id=\"(\\d+)\".*?bandwidth=\"(\\d+)\".*?width=\"(\\d+)\".*?height=\"(\\d+)\".*?/>".toRegex()
val videoReps = videoRepRegex.findAll(dashXml).map { match ->
val id = match.groupValues[1]
val bandwidth = match.groupValues[2].toInt()
val width = match.groupValues[3].toInt()
val height = match.groupValues[4].toInt()
VideoRepresentation(id, bandwidth, width, height)
}.sortedByDescending { it.bandwidth }.toList()
if (videoReps.isEmpty()) {
throw IOException("No video representations found in DASH XML")
}
// Extract audio representation - using a more flexible pattern to match the actual XML structure
val audioRepRegex = "<AdaptationSet[^>]*?contentType=\"audio\"[^>]*?>.*?<Representation id=\"(\\d+)\".*?bandwidth=\"(\\d+)\".*?/>".toRegex(RegexOption.DOT_MATCHES_ALL)
val audioRep = audioRepRegex.find(dashXml)?.let { match ->
val id = match.groupValues[1]
val bandwidth = match.groupValues[2].toInt()
AudioRepresentation(id, bandwidth)
} ?: throw IOException("No audio representation found in DASH XML - please check the XML structure")
// Log available streams for debugging
videoReps.forEach { rep ->
Log.d(TAG, "Available video stream: ${rep.bandwidth / 1000}kbps [${rep.width}x${rep.height}] ID: ${rep.id}")
}
Log.d(TAG, "Audio stream: ${audioRep.bandwidth / 1000}kbps ID: ${audioRep.id}")
// Choose the highest quality video representation
val bestVideoRep = videoReps.first()
Log.d(TAG, "Selected video stream: ${bestVideoRep.bandwidth / 1000}kbps [${bestVideoRep.width}x${bestVideoRep.height}]")
// Construct the video initialization URL
val videoInitUrl = "$baseUrl?type=video&ft=0&id=${bestVideoRep.id}&bitrate=${bestVideoRep.bandwidth}"
Log.d(TAG, "Video init URL: $videoInitUrl")
// Construct the audio initialization URL
val audioInitUrl = "$baseUrl?type=audio&ft=0&id=${audioRep.id}&bitrate=${audioRep.bandwidth}"
Log.d(TAG, "Audio init URL: $audioInitUrl")
// For ExoPlayer, we need to use the DASH format directly
// Return the base URL with query parameters that ExoPlayer can use
val finalUrl = baseUrl + "?indexMode&dvr=10800000"
Log.d(TAG, "Final DASH URL: $finalUrl")
return finalUrl
}
// Data classes for DASH processing
private data class VideoRepresentation(val id: String, val bandwidth: Int, val width: Int, val height: Int)
private data class AudioRepresentation(val id: String, val bandwidth: Int)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels