2013-09-27 3 views
27

я следующий код в моем приложении:IOS 7 AVPlayer AVPlayerItem продолжительность некорректная в прошивке 7

NSURL *url = [NSURL fileURLWithPath: [self.DocDir stringByAppendingPathComponent: self.FileName] isDirectory: NO]; 
self.avPlayer = [AVPlayer playerWithURL: url]; 

Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration); 

Это работало отлично с прошивкой 6, но с прошивкой 7 по какой-то причине она возвращает NaN. При проверке self.avPlayer.currentItem.duration объект CMTime имеет 0 с флагом 17.

Интересно, что игрок отлично работает, только продолжительность неправильная.

Есть ли у кого-нибудь еще те же проблемы? Я ввожу следующее:

#import <Foundation/Foundation.h> 
#import <AVFoundation/AVFoundation.h> 
#import <MediaPlayer/MediaPlayer.h> 
#import <CoreMedia/CoreMedia.h> 
#import <AVFoundation/AVAsset.h> 

ответ

48

После игры вокруг с различными способами инициализации объектов я прибыл в рабочем растворе:

AVURLAsset *asset = [AVURLAsset assetWithURL: url]; 
Float64 duration = CMTimeGetSeconds(asset.duration); 
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset: asset]; 
self.avPlayer = [[AVPlayer alloc] initWithPlayerItem: item]; 

Оказывается, значение длительности не всегда сразу же доступны из AVPlayerItem, но, похоже, он работает отлично с AVAsset сразу.

+0

Hi Это не сработало для меня. любая другая альтернатива? – Nitesh

+0

Привет, Нитеш, задайте свой вопрос в новой теме, показывая некоторые из вашего кода и ошибки/вы получаете. –

+2

Я также использовал [[AVPlayer currentItem] duration], который возвращает NaN в iOS 7 для действительных медиафайлов. В iOS 6, если он вернул NaN, это означало, что файл не воспроизводится. Переключение на идею AVURLAsset устраняет это. – Deminetix

24

В прошивке 7, для AVPlayerItem уже создан, вы можете также получить срок от нижележащего актива:

CMTimeGetSeconds([[[[self player] currentItem] asset] duration]); 

Вместо того, чтобы получить его непосредственно из AVPlayerItem, который дает вам NaN:

CMTimeGetSeconds([[[self player] currentItem] duration]); 
+0

Спасибо за это! – JKoko

+0

фантастический! THANKS – SpaceDog

4

рекомендуемый способ сделать это, как описано в the manual, наблюдая статус элемента игрока:

[self.avPlayer.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:nil]; 

Затем внутри observeValueForKeyPath:ofObject:change:context:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    // TODO: use either keyPath or context to differentiate between value changes 
    if (self.avPlayer.currentItem.status == AVPlayerStatusReadyToPlay) { 
     Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration); 
     // ... 
    } 
} 

Кроме того, убедитесь, что вы удалить наблюдателя при изменении элемента игрока:

if (self.avPlayer.currentItem) { 
    [self.avPlayer.currentItem removeObserver:self forKeyPath:@"status"]; 
} 

Btw, вы можете также наблюдать duration свойство непосредственно; однако, это был мой личный опыт, что результаты не так надежно, как должны быть ;-)

+0

К сожалению, это не работает в iOS 10.x – user3069232

+0

@ user3069232 «не работает», что вы имеете в виду? каковы ваши наблюдения? –

+0

Он возвращает nan ... В итоге я использовал комбинацию AVURLAsset и статус AVPlayer, который вы использовали здесь, чтобы заставить его работать. – user3069232

Смежные вопросы