iOS 7 AVPlayer AVPlayerItem duración incorrecta en iOS 7

Tengo el siguiente código en mi aplicación:

NSURL *url = [NSURL fileURLWithPath: [self.DocDir stringByAppendingPathComponent: self.FileName] isDirectory: NO]; self.avPlayer = [AVPlayer playerWithURL: url]; Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration); 

Esto funcionó bien con iOS 6 pero con iOS 7 por alguna razón devuelve NaN. Al inspeccionar self.avPlayer.currentItem.duration, el object CMTime tiene 0 con un indicador de 17.

Curiosamente, el jugador funciona bien, solo la duración es incorrecta.

¿Alguien más ha experimentado los mismos problemas? Estoy importando lo siguiente:

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

Después de jugar con diferentes forms de inicializar los objects, llegué a una solución funcional:

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

Parece que el valor de la duración no siempre está disponible de inmediato desde un AVPlayerItem, pero parece funcionar bien con un AVAsset inmediatamente.

En iOS 7, para AVPlayerItem ya creado, también puede get la duración del activo subyacente:

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

En lugar de getlo directamente de AVPlayerItem, que le proporciona un NaN:

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

La forma recomendada de hacer esto, como se describe en el manual, es observar el estado del elemento del jugador:

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

Entonces, 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); // ... } } 

Además, asegúrese de eliminar el observador cuando cambie el elemento del reproductor:

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

Por cierto, también puede observar la propiedad de duration directamente; sin embargo, ha sido mi experiencia personal que los resultados no son tan confiables como deberían ser 😉