HLS AVPlayer на iOS — вернуться к работе

У меня есть AVPlayer, который транслирует прямой поток HLS.

Когда пользователь выполняет многозадачность приложения, я вижу, что скорость воспроизведения падает до 0,0 (пауза), когда пользователь возвращается, она возвращается к 1,0 (воспроизведение), но начинает воспроизведение с того момента, когда оно было приостановлено.

Каков наилучший способ заставить игрока вернуться к жизни без полного перезапуска потока? Существует ли метод seekToTime, который обрабатывает параметр, наиболее близкий к живому времени?

Спасибо!


person angelfilm entertainment    schedule 30.10.2012    source источник


Ответы (7)


Я использую:

 double time = MAXFLOAT;
 [player seekToTime: CMTimeMakeWithSeconds(time, NSEC_PER_SEC)];

Хорошо работает в моем приложении.

person Igor Kulagin    schedule 15.12.2012

Предполагая, что player является экземпляром AVPlayer:

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)];
person Karim Mourra    schedule 19.11.2015
comment
Это настоящий ответ. Работал для меня как шарм. - person davidgoli; 29.03.2016
comment
Вы также можете использовать CMTimeAdd вместо преобразования в числа с плавающей запятой. - person Sterling Christensen; 30.03.2016
comment
Вы также можете использовать CMTimeRangeGetEnd вместо добавления длительности к началу. - person Fabian; 28.08.2016

Версия Swift 3.0

public func resumeLive() {
    guard let livePosition = player.currentItem?.seekableTimeRanges.last as? CMTimeRange else {
        return
    }
    player.seek(to:CMTimeRangeGetEnd(livePosition))
}
person Sachin    schedule 23.03.2017

Быстрая версия ответа Карима Мурры:

let seekableRanges = player.currentItem!.seekableTimeRanges
guard seekableRanges.count > 0 else {
  return
}

let range = seekableRanges.last!.CMTimeRangeValue
let livePosition = range.start + range.duration

let minus = CMTimeMakeWithSeconds(Float64(timeOffset), Int32(NSEC_PER_SEC))
let time = livePosition - minus

player.seekToTime(time)
person davidgoli    schedule 29.03.2016
comment
охранять let lastRange = player.currentItem?.seekableRange.last else { return; } player.seekToTime(lastRange.end) - person Fabian; 28.08.2016
comment
что такое таймоффсет? - person Hong Zhou; 29.05.2017
comment
@HongZhou это совершенно необязательный буфер в секундах. Вы можете просто использовать livePosition и опустить строку с timeOffset. - person davidgoli; 30.05.2017

Нет необходимости преобразовывать в числа с плавающей запятой, если вы используете функции манипуляции Apple CMTimeRange:

NSValue *value = player.currentItem.seekableTimeRanges.lastObject;
if (value) {
    CMTimeRange seekableRange = [value CMTimeRangeValue];
    CMTime latestTime = CMTimeRangeGetEnd(seekableRange);
    [player seekToTime:latestTime];
} else {
    // there are no seekable time ranges
}

РЕДАКТИРОВАТЬ: пожалуйста, проголосуйте за комментарий Фабиана ниже

person Sterling Christensen    schedule 30.03.2016
comment
Не нужно добавлять время, если вы используете CMTimeRangeGetEnd - person Fabian; 28.08.2016

Быстрая версия ответа Игоря Кулагина:

player.seek(to: kCMTimePositiveInfinity)
player.play()

Отлично работает в любых условиях. Другие решения дали мне ошибку NaN при вычислении значения livePosition или ошибку {INVALID} при работе напрямую с CMTime.

person Pietro Basso    schedule 09.01.2018
comment
на iOS 14 это больше не работает, пришлось использовать решение seekableTimeRanges - person CiNN; 09.11.2020

Свифт 4 версия:

if let seekableRange = player.currentItem?.seekableTimeRanges.last?.timeRangeValue {
    let seekableStart = seekableRange.start
    let seekableDuration = seekableRange.duration
    let livePosition = seekableStart + seekableDuration

    player.seek(to: livePosition, completionHandler: { [weak self] _ in
        self?.player.play()
    })
}
person timurbeg    schedule 30.04.2020