Skip to content

Channel 10 changed logic #247

@BarelElbaz

Description

@BarelElbaz

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions