2013-09-27 6 views
27

Ho il seguente codice nel mio app:iOS 7 AVPlayer AVPlayerItem durata non corretta in iOS 7

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

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

questo ha funzionato benissimo con iOS 6, ma con iOS 7 per qualche motivo restituisce NaN. Durante l'ispezione di self.avPlayer.currentItem.duration l'oggetto CMTime ha 0 con una bandiera di 17.

È interessante notare che il lettore funziona correttamente, solo la durata è errata.

Qualcun altro ha riscontrato gli stessi problemi? Sto importando i seguenti:

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

risposta

48

Dopo aver suonato in giro con diversi modi di inizializzazione degli oggetti sono arrivato ad una soluzione di lavoro:

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

Sembra che il valore di durata non è sempre immediatamente disponibile da un AVPlayerItem ma sembra funzionare correttamente con un set di AVA immediatamente.

+0

Ciao Questo non ha funzionato per me. qualche altra alternativa? – Nitesh

+0

Ciao Nitesh, per favore fai la tua domanda in una nuova discussione, mostrando parte del tuo codice e l'errore/i che stai ricevendo. –

+2

Stavo usando anche [[AVPlayer currentItem] duration] che restituisce NaN in iOS 7 per i file multimediali validi. In iOS 6 se restituiva NaN significava che il file non era riproducibile. Passare all'idea di AVURLAsset risolve questo problema. – Deminetix

24

In iOS 7, per AVPlayerItem già creato, è anche possibile ottenere la durata dall'attività underlaying:

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

Invece di farlo direttamente da AVPlayerItem, che ti dà un NaN:

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

Grazie per questo! – JKoko

+0

fantastico! GRAZIE – SpaceDog

4

il modo consigliato di fare questo, come descritto nella the manual è osservando lo stato oggetto giocatore:

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

Poi, all'interno 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); 
     // ... 
    } 
} 

Inoltre, assicurarsi di rimuovere l'osservatore quando si modifica la voce di un giocatore:

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

Btw, è anche possibile osservare direttamente la proprietà duration; tuttavia, è stata la mia esperienza personale che i risultati non sono affidabili come dovrebbero essere ;-)

+0

Purtroppo questo non funziona in iOS 10.x – user3069232

+0

@ user3069232 di "non funziona", cosa intendi? quali sono le tue osservazioni? –

+0

Restituisce nan ... Ho finito per utilizzare una combinazione di AVURLAsset e lo stato di AVPlayer che hai usato qui per farlo funzionare. – user3069232