我正在使用AVPlayer播放直播流。这个流支持一小时的追赶功能,也就是说用户可以跳到一小时前并进行播放。但是我有一个问题,如何知道播放器当前准确的播放位置。我需要在播放器视图上显示当前位置。例如,如果用户正在播放半小时前的内容,则显示-30:00;如果用户正在播放最新的内容,则播放器将显示00:00或“直播”。谢谢。
我正在使用AVPlayer播放直播流。这个流支持一小时的追赶功能,也就是说用户可以跳到一小时前并进行播放。但是我有一个问题,如何知道播放器当前准确的播放位置。我需要在播放器视图上显示当前位置。例如,如果用户正在播放半小时前的内容,则显示-30:00;如果用户正在播放最新的内容,则播放器将显示00:00或“直播”。谢谢。
Swift解决方案:
override func getLiveDuration() -> Float {
var result : Float = 0.0;
if let items = player.currentItem?.seekableTimeRanges {
if(!items.isEmpty) {
let range = items[items.count - 1]
let timeRange = range.timeRangeValue
let startSeconds = CMTimeGetSeconds(timeRange.start)
let durationSeconds = CMTimeGetSeconds(timeRange.duration)
result = Float(startSeconds + durationSeconds)
}
}
return result;
}
AVPlayerItem
的seekableTimeRanges
属性,您可以获取实时位置,然后进行跳转:CMTimeRange seekableRange = [player.currentItem.seekableTimeRanges.lastObject CMTimeRangeValue];
CGFloat seekableStart = CMTimeGetSeconds(seekableRange.start);
CGFloat seekableDuration = CMTimeGetSeconds(seekableRange.duration);
CGFloat livePosition = seekableStart + seekableDuration;
[player seekToTime:CMTimeMake(livePosition, 1)];
此外,如果您想要追溯某个时间点,可以通过调用 currentTime
方法获取当前播放位置。
CGFloat current = CMTimeGetSeconds([self.player.currentItem currentTime]);
CGFloat diff = livePosition - current;
我知道这个问题旧了,但我有同样的需求,我认为现有的解决方案没有很好地解决问题的意图。
为了满足相同的要求,我收集了当前时间点、起始时间和流的总时长。
在进一步解释之前,我想说明一件事,当前时间可能会超过(起始时间+总时长),这是由于hls结构中ts分段的方式。 Ts分段是可播放视频的小块,您可以在可寻址范围内拥有10秒钟的5个ts分段。这并不意味着50秒是直播流的完整长度,还有一个完整的分段(因此总共60秒的播放时间),但它不是被归类为可寻址的,因为您不应该寻找那个分段。如果您这样做,您会注意到在大多数情况下重新缓冲(因为当您已经达到播放结束时,源可能仍在创建下一个ts段)。
我的做法是检查当前流的时间是否超过可寻址范围,如果超过,则意味着我们正在直播。 如果没有,您可以轻松计算距离实时的落后时间,只需要从当前时间、开始时间和总时长减去即可。
let timeRange:CMTimeRange = player.currentItem?.seekableTimeRanges.last
let start = timeRange.start.seconds
let totalDuration = timeRange.duration.seconds
let currentTime = player.currentTime().seconds
let secondsBehindLive = currentTime - totalDuration - start