You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS UIKit/Swift蜂窝数据带宽被节流?AVPlayer卡顿求助

HLS播放器蜂窝数据下卡顿与带宽限制问题

我使用AVPlayer开发了一个HLS文件播放器,WiFi环境下播放几乎完美,无延迟无等待,可立即播放!但切换到蜂窝数据后,播放频繁卡顿。

实际测试设备的蜂窝数据下载速度约为300Mbps,WiFi约为150Mbps,但应用内测试MP4文件下载速度时,WiFi能达到100Mbps以上,与测速结果一致,而蜂窝数据下载速度仅约13Mbps,带宽被大幅限制。

AVPlayer配置代码

func preloadSegment(for url: URL) {
        guard players[url] == nil else {
            print("Player for URL is already preloaded.")
            return
        }
        
        print("Preloading \(url.absoluteString)")
        

        DispatchQueue.main.async {
            let assetOptions = [AVURLAssetPreferPreciseDurationAndTimingKey: false]
            let asset = AVURLAsset(url: url, options: assetOptions)
            
            // Initialize the AVPlayerItem with the asset
            let playerItem = AVPlayerItem(asset: asset)
            
            // Customize the AVPlayerItem settings
            playerItem.preferredPeakBitRate = 4_000_000 // Setting to 4 Mbps
            playerItem.preferredForwardBufferDuration = 5
            playerItem.canUseNetworkResourcesForLiveStreamingWhilePaused = true
            
            // Limiting the resolution can be beneficial for certain network conditions
            if #available(iOS 11.0, *) {
                playerItem.preferredMaximumResolution = CGSize(width: 720, height: 1280)
            }
            
            // Initialize the player with the playerItem
            let player = AVPlayer(playerItem: playerItem)
            player.automaticallyWaitsToMinimizeStalling = true
            player.usesExternalPlaybackWhileExternalScreenIsActive = false
            player.allowsExternalPlayback = false
            
            player.currentItem?.preferredMaximumResolutionForExpensiveNetworks = CGSize(width: 360, height: 640)

            self.players[url] = player
        }
    }
    
    func cleanup() {
        for observer in playerObservers {
            observer.player?.removeTimeObserver(observer.observerToken)
        }
        playerObservers.removeAll()
    }
    
    func configuredPlayerItem(for url: URL) -> AVPlayerItem {
        let assetOptions = [AVURLAssetPreferPreciseDurationAndTimingKey: false]
        let asset = AVURLAsset(url: url, options: assetOptions)
        let playerItem = AVPlayerItem(asset: asset)

        playerItem.preferredPeakBitRate = 4_000_000
        playerItem.preferredForwardBufferDuration = 5
        playerItem.canUseNetworkResourcesForLiveStreamingWhilePaused = true

        if #available(iOS 11.0, *) {
            playerItem.preferredMaximumResolution = CGSize(width: 1280, height: 720)
        }

        return playerItem
    }

应用内下载速度测试代码

class SpeedTestViewController: UIViewController {

    private var startTime: TimeInterval?
    private var stopTime: TimeInterval?
    private var bytesReceived: Int64 = 0

    // Label to display download speed
    private let speedLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        view.addSubview(speedLabel)

        NSLayoutConstraint.activate([
            speedLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            speedLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])

        testDownloadSpeed()
    }

    private func testDownloadSpeed() {
        guard let url = URL(string: "MP4 URL") else { return } // Replace with your file URL
        let request = URLRequest(url: url)

        startTime = Date().timeIntervalSince1970
        bytesReceived = 0
        stopTime = nil

        let configuration = URLSessionConfiguration.default
        let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
        let task = session.dataTask(with: request)
        task.resume()
    }

    private func calculateSpeed() {
        guard let startTime = startTime, let stopTime = stopTime else { return }
        let elapsed = stopTime - startTime

        // Speed in bytes per second
        let speed = Double(bytesReceived) / elapsed

        // Convert to megabits per second
        let speedMbps = speed * 8 / 1_000_000
        DispatchQueue.main.async {
            self.speedLabel.text = String(format: "Download speed: %.2f Mbps", speedMbps)
        }
    }
}

extension SpeedTestViewController: URLSessionDataDelegate {
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        bytesReceived += Int64(data.count)
        stopTime = Date().timeIntervalSince1970

        if dataTask.countOfBytesExpectedToReceive > 0 {
            // If the size of the file is known, update progress here
            print("huh")
        }
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        calculateSpeed()
    }
}

已尝试的解决方案

  • 确认未在Xcode中设置网络节流
  • 为AVPlayerItem设置preferredMaximumResolutionForExpensiveNetworks参数,无效果
  • 在Build Settings中切换Testability为Release/Debug模式,无变化
  • 调整automaticallyWaitsToMinimizeStalling以及preferredPeakBitRate、preferredForwardBufferDuration、canUseNetworkResourcesForLiveStreamingWhilePaused等参数,均未解决卡顿问题

这些视频时长仅几秒,大小大多小于1MB,无法理解为何会被节流。有没有办法取消应用对蜂窝数据的带宽限制?如需更多代码请告知。

内容的提问来源于stack exchange,提问作者Sam Chahine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:36:02