0

When I use this code below and I pull my https video link from Firebase over Wifi everything is smooth, the video immediately plays with zero issues. When I use this same code over Cellular everything moves extremely slow, like the video pauses and takes forever to load.

If it plays from file wether I'm on Cellular or Wifi shouldn't matter. What is the issue here?

DataModel:

class Video {

    var httpsStr: String?
    var videoURL: URL?        

    convenience init(dict: [String: Any] {
        self.init()

        if let httpsStr = dict["httpsStr"] as? String {

            self.httpsStr = httpsStr

            let url = URL(string: httpsStr)!
            let assetKeys = [ "playable", "duration"]

            let asset = AVURLAsset(url: url)
            asset.loadValuesAsynchronously(forKeys: assetKeys, completionHandler: {
                DispatchQueue.main.async {
                
                    self.videoURL = asset.url

                    // save videoURL to FileManager to play video from disk
                }
            })
        }
    } 
}

Firebase Pull:

ref.observeSingleEvent(of: .value) { (snapshot) in

    guard let dict = snapshot.value as? [String: Any] else { return }

    let video = Video(dict: dict)
    self.video = video

    DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
        self.playVideo()
    }
}

Play Video:

func playVideo() {

    // init AVPlayer ...

    guard let videoURL = self.video.videoURL else { return }

    let lastPathComponent = videoURL.lastPathComponent
    let file = FileManager...appendingPathComponent(lastPathComponent)

    if FileManager.default.fileExists(atPath: file.path) {

        let asset = AVAsset(url: file)
        play(asset)

    } else {

        let asset = AVAsset(url: videoURL)
        play(asset)
    }
}

func play(_ asset: AVAsset) {
    
    self.playerItem = AVPlayerItem(asset: asset)

    self.player?.automaticallyWaitsToMinimizeStalling = false // I also set this to true
    self.playerItem?.preferredForwardBufferDuration = TimeInterval(1)

    self.player?.replaceCurrentItem(with: playerItem!)
    // play video
}
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256

1 Answers1

0

I followed this answer and now everything seems to work smoothly while on Cellular Data. I needed to include the tracks property in the assetKeys.

You create an asset from a URL using AVURLAsset. Creating the asset, however, does not necessarily mean that it’s ready for use. To be used, an asset must have loaded its tracks.

class Video {

    var httpsStr: String?
    var videoURL: URL?        

    convenience init(dict: [String: Any] {
        self.init()

        if let httpsStr = dict["httpsStr"] as? String {

            self.httpsStr = httpsStr

            let url = URL(string: httpsStr)!
            let assetKeys = ["playable", "duration", "tracks"] // <----- "tracks" added here

            let asset = AVURLAsset(url: url)
            asset.loadValuesAsynchronously(forKeys: assetKeys, completionHandler: {

                var error: NSError? = nil
                let status = asset.statusOfValue(forKey: "tracks", error: &error)
                switch status {

                    case .loaded:
                        // Sucessfully loaded, continue processing
                        DispatchQueue.main.async {
                
                            self.videoURL = asset.url
                            // save videoURL to FileManager to play video from disk
                        }

                    case .failed: 
                        // Examine NSError pointer to determine failure
                        print("Error", error?.localizedDescription as Any)

                    default: 
                        // Handle all other cases
                        print("default")
                }
            })
        }
    } 
}
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256