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

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

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

@ property (nonatomic,только чтение) NSTimeInterval playableDuration

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

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

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

Ответы [ 5 ]

16 голосов
/ 04 сентября 2012

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, проверив AVTlayerItem'sloadedTimeRanges, вы можете вычислить приблизительную playableDuration.

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

6 голосов
/ 26 ноября 2014

все что вам нужно это

self.player.currentItem.asset.duration

просто лучше

4 голосов
/ 29 августа 2013

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

Это явное поведение по умолчанию для игроков 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));
}

}

2 голосов
/ 05 августа 2011

Вам нужно будет определить, когда 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);
1 голос
/ 01 сентября 2017

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
}
...