Search code examples
iosswiftgcdwebserver

Can we manually download/cache the transport stream while streaming m3u8 file


I am trying to play transport stream from m3u8 file. My requirement is to process the downloaded data before giving it to AVPlayer. For that I am using a proxy server[GCDWebserver] to intercept all the request. In proxy server I will download the data process it and feed it back.

I was able to download the media file and also have tried returning data using GCDWebServerDataResponse(data: apiData, contentType: apiResponse.mimeType ?? ""). But player is not playing the media content.

  1. I am using GCDWebserver as my proxy server.

  2. I have created an instance of AVPlayerItem with the following url http://34.55.7.151:8080/ which is actually my local servers ip & port number.

    /// Initialise AVPlayer Item

    let url = URL(string: "http://10.155.177.151:8080/")!
    let playerItem = AVPlayerItem(url: url)
    player = AVPlayer(playerItem: playerItem)
    player.automaticallyWaitsToMinimizeStalling = false
    
    let playerViewController = AVPlayerViewController()
    playerViewController.player = player
    
    DispatchQueue.main.async {
        self.present(playerViewController, animated: true) {
            playerViewController.player!.play()
        }
    }
    

/// Http proxy handler

    webServer.addDefaultHandler(forMethod: "GET", request: GCDWebServerRequest.self) { (request, completion) in

        let  mediaUrl = URL(string: "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")!

        if self.session == nil {
            self.session = URLSession(configuration: URLSessionConfiguration.default)
        }

        let dataTask = self.session?.dataTask(with: mediaUrl, completionHandler: { (data, response, error) in
            if let apiData = data, let apiResponse = response {
                completion(GCDWebServerDataResponse(data: apiData, contentType: apiResponse.mimeType ?? ""))
            } else {
                completion(GCDWebServerDataResponse(text: "Error"))
            }
        })
        dataTask!.resume()
    }

Solution

  • Something similar has been implemented here: https://github.com/StyleShare/HLSCachingReverseProxyServer

    It downloads the segments while streaming, if the segment is available locally, it will use that instead.