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

MPMoviePlayerController има свойство, наречено playableDuration.

playableDuration Количеството текущо възпроизвеждано съдържание (само за четене).

@property (nonatomic, само за четене) 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, като проверите loadedTimeRanges на AVPlayerItem, можете да изчислите прогнозна продължителност за възпроизвеждане.

За видеоклипове, които имат само 1 раздел, можете да използвате тази процедура; но за многосекционно видео може да искате да проверите всички времеви диапазони в масива от loadedTimeRagnes, за да получите правилен отговор.

person John Lingburg    schedule 04.09.2012
comment

Всичко, което искам, е да отпечатам размера на файла в байтове, който използвам

DIR *d;
struct dirent *dir;
d= opendir(absolute_path);

while((dir= readdir(d))!=NULL){
    printf("%s\t %d\t %u\n",dir->d_name,dir->d_type,(int long long )dir->d_off);
}

Отпечатването на d_off, което е тип off_t, е грешно. За файл от 323,388 bytes той отпечатва 1296623584

Мисля, че кастингът е проблемът. Опитах много кастинги като %d, %s,%u, %llu... Кое е правилното кастинг?

РЕДАКТИРАНЕ: Правилната функция, която да използвате за намиране на размера на файла, е lstat() с помощта на stat структура.

- 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 asset] duration] ще върне общата продължителност на филма; не продължителността на възпроизвеждане (т.е. количеството изтеглени данни, които могат да бъдат възпроизведени. - person spd; 09.08.2011

Бърза версия на затваряне на възможна продължителност:

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