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

YouTube-Player-iOS-Helper中YTPlayerView进度滑块无法到达终点

问题描述

在iOS平台使用YouTube-Player-iOS-Helper实现YTPlayerView播放器功能时,自定义进度滑块存在数值异常:视频已播放结束,但自定义滑块停在中途位置,数值无法到达最大值终点。
问题截图

原始核心代码
class PlayerViewController: UIViewController, YTPlayerViewDelegate {

    var durationOfVideo: Double?

    lazy var rewindSlider: UISlider = {
        let slider = UISlider()
        slider.minimumTrackTintColor = .white
        slider.maximumTrackTintColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 0.7)
        slider.setThumbImage(UIImage(named: "Thumb_On_ProgressLine"), for: .normal)
        slider.translatesAutoresizingMaskIntoConstraints = false
        
        slider.addTarget(self, action: #selector(handleSliderChange), for: .valueChanged)
        
        return slider
    }()

    @objc func handleSliderChange() {
        print(rewindSlider.value)
    }

    // MARK: viewDidLoad
    override func viewDidLoad() {
        super.viewDidLoad()
        
        webView.delegate = self
        webView.load(withVideoId: "kbMqWXnpXcA",
                     playerVars: ["playsinline": 1])
    }

    // MARK: Player control
    func playerViewDidBecomeReady(_ playerView: YTPlayerView) {
        playerView.duration { (time, error) in
            print("duration: \(time)")
            self.durationOfVideo = time
        }
    }

    func playerView(_ playerView: YTPlayerView, didPlayTime playTime: Float) {
        
        guard durationOfVideo != nil else { return }
        self.rewindSlider.value = Float((Double(playTime) / durationOfVideo!))
    }
}
问题根因

代码存在两处核心逻辑漏洞:

  1. 缺失播放结束状态的处理:playerView(_:didPlayTime:)是固定间隔(约1秒1次)的进度回调,受回调频率限制,视频播放到末尾时,最后一次回调返回的playTime永远小于实际总时长,不会触发进度值等于1.0的场景,滑块自然无法到达终点。
  2. 总时长获取时机错误:playerViewDidBecomeReady回调触发时,播放器刚完成初始化,此时调用duration方法拿到的视频总时长经常存在偏差(多数场景下会大于实际可播放时长),用这个偏差值做分母计算进度,哪怕视频实际播完,计算出的进度值也会小于1,进一步导致滑块停在中途。
修复方案
  • 实现playerView(_:didChangeTo:)状态回调代理:
    • 当状态切换为.playing时,重新拉取一次准确的视频总时长,覆盖之前初始化阶段拿到的不准的数值;
    • 当状态切换为.ended时,手动将rewindSlider的值设为1.0,直接将滑块拉到终点。
  • 在didPlayTime的进度计算逻辑里增加边界截断,计算出的进度值如果大于1,直接赋值为1,避免异常值导致滑块越界。

修复后的核心代码参考:

// 补充状态变化代理方法
func playerView(_ playerView: YTPlayerView, didChangeTo state: YTPlayerState) {
    switch state {
    case .playing:
        // 播放状态下重新获取准确总时长
        playerView.duration { [weak self] time, error in
            guard error == nil, time > 0 else { return }
            self?.durationOfVideo = time
        }
    case .ended:
        // 播放结束直接把滑块拉满
        self.rewindSlider.value = 1.0
    default:
        break
    }
}

func playerView(_ playerView: YTPlayerView, didPlayTime playTime: Float) {
    guard let totalDuration = durationOfVideo, totalDuration > 0 else { return }
    let progress = min(Float(playTime) / Float(totalDuration), 1.0)
    self.rewindSlider.value = progress
}

内容的提问来源于stack exchange,提问作者iOS Swift-man Junior

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:27:28