iOS - Как я могу получить игровую продолжительность AVPlayer

MPMoviePlayerController имеет свойство playableDuration.

playableDuration Количество воспроизводимого в данный момент контента (только для чтения).

@property (неатомарное, только для чтения) NSTimeInterval playableDuration

Для постепенно загружаемого сетевого контента это свойство отражает объем контента, который можно воспроизвести сейчас.

Есть что-то подобное для AVPlayer? Я ничего не могу найти в Apple Docs или Google (даже здесь, на Stackoverflow.com).

Заранее спасибо.


person MystyxMac    schedule 25.07.2011    source источник


Ответы (5)


playableDuration можно грубо реализовать с помощью следующей процедуры:

- (NSTimeInterval) playableDuration
{
//  use loadedTimeRanges to compute playableDuration.
AVPlayerItem * item = _moviePlayer.currentItem;

if (item.status == AVPlayerItemStatusReadyToPlay) {
    NSArray * timeRangeArray = item.loadedTimeRanges;

    CMTimeRange aTimeRange = [[timeRangeArray objectAtIndex:0] CMTimeRangeValue];

    double startTime = CMTimeGetSeconds(aTimeRange.start);
    double loadedDuration = CMTimeGetSeconds(aTimeRange.duration);

    // FIXME: shoule we sum up all sections to have a total playable duration,
    // or we just use first section as whole?

    NSLog(@"get time range, its start is %f seconds, its duration is %f seconds.", startTime, loadedDuration);


    return (NSTimeInterval)(startTime + loadedDuration);
}
else
{
    return(CMTimeGetSeconds(kCMTimeInvalid));
}
}

_moviePlayer — это ваш экземпляр AVPlayer, проверив загруженные TimeRanges AVPlayerItem, вы можете вычислить предполагаемую playableDuration.

Для видео, состоящего только из 1 части, вы можете использовать эту процедуру; но для многосекционного видео вы можете проверить все временные диапазоны в массиве загруженных TimeRagnes, чтобы получить правильный ответ.

person John Lingburg    schedule 04.09.2012
comment
Спасибо за Ваш ответ. Я знаю, что это было пару месяцев назад, но сегодня я просматривал некоторые старые вопросы. Это решение выглядит так, как будто я мог бы его использовать. Поэтому я отмечаю это как ответ. - person MystyxMac; 04.02.2013

все что тебе нужно это

self.player.currentItem.asset.duration

просто лучший

person Syed Ali Salman    schedule 26.11.2014
comment
Продолжительность актива может не совпадать с воспроизводимой продолжительностью актива, например, если актив загружен не полностью. - person yuf; 12.06.2015
comment
Да, это то, что AVPlayer делает, когда вы инициализируете его из NSURL - person Syed Ali Salman; 12.06.2015

Опираясь на ответ Джона…

Это очевидное поведение плееров Apple по умолчанию: «Показать максимальное время воспроизводимого диапазона, которое охватывает текущее время».

- (NSTimeInterval)currentItemPlayableDuration{

//  use loadedTimeRanges to compute playableDuration.
AVPlayerItem * item = self.audioPlayer.currentItem;

if (item.status == AVPlayerItemStatusReadyToPlay) {
    NSArray * timeRangeArray = item.loadedTimeRanges;

    CMTime currentTime = self.audioPlayer.currentTime;

    __block CMTimeRange aTimeRange;

    [timeRangeArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

       aTimeRange = [[timeRangeArray objectAtIndex:0] CMTimeRangeValue];

        if(CMTimeRangeContainsTime(aTimeRange, currentTime))
            *stop = YES;

    }];

    CMTime maxTime = CMTimeRangeGetEnd(aTimeRange);

    return CMTimeGetSeconds(maxTime);
}
else
{
    return(CMTimeGetSeconds(kCMTimeInvalid));
}

}

person Corey Floyd    schedule 29.08.2013
comment
Этот код неверен. Он должен иметь obj внутри блока вместо [timeRangeArray objectAtIndex:0] - person Joris Weimar; 07.11.2018

Вам нужно будет определить, когда AVPlayer будет готов воспроизвести ваш медиафайл. Дайте мне знать, если вы не знаете, как это сделать.

Однако после загрузки медиафайла вы можете использовать этот метод:

#import <AVFoundation/AVFoundation.h>

/**
 * Get the duration for the currently set AVPlayer's item. 
 */
- (CMTime)playerItemDuration {
    AVPlayerItem *playerItem = [mPlayer currentItem];
    if (playerItem.status == AVPlayerItemStatusReadyToPlay) {
        return [[playerItem asset] duration];
    }
    return(kCMTimeInvalid);
}

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

CMTime playerDuration = [self playerItemDuration];
if (CMTIME_IS_INVALID(playerDuration)) {
    return;
}
double duration = CMTimeGetSeconds(playerDuration);
person leviathan    schedule 05.08.2011
comment
Спасибо за Ваш ответ. Но что мне нужно, так это игровая продолжительность, сколько я могу играть, прежде чем фильм остановится? Я отредактирую свой вопрос. - person MystyxMac; 07.08.2011
comment
MystyxMac прав. [[playerItem актив] продолжительность] вернет общую продолжительность фильма; а не воспроизводимая продолжительность (т.е. количество загруженных данных, которые можно воспроизвести. - person spd; 09.08.2011

Версия Swift закрывает игровую продолжительность:

var playableDuration: TimeInterval? {
    guard let currentItem = currentItem else { return nil }
    guard currentItem.status == .readyToPlay else { return nil }

    let timeRangeArray = currentItem.loadedTimeRanges
    let currentTime = self.currentTime()

    for value in timeRangeArray {
        let timeRange = value.timeRangeValue
        if CMTimeRangeContainsTime(timeRange, currentTime) {
            return CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange))
        }
    }

    guard let timeRange = timeRangeArray.first?.timeRangeValue else { return 0}

    let startTime = CMTimeGetSeconds(timeRange.start)
    let loadedDuration = CMTimeGetSeconds(timeRange.duration)
    return startTime + loadedDuration
}
person Michal Zaborowski    schedule 01.09.2017