iOS 7 AVPlayer AVPlayerItem duración incorrecta en iOS 7
ios7 avfoundation (3)
Después de jugar con diferentes formas de inicializar los objetos, llegué a una solución de trabajo:
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 duración no siempre está disponible inmediatamente desde un AVPlayerItem pero parece funcionar bien con un AVAsset inmediatamente.
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 objeto CMTime tiene 0 con un indicador de 17.
Curiosamente el jugador trabaja bien, solo que 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>
En iOS 7, para AVPlayerItem ya creado, también puede obtener la duración del activo subyacente:
CMTimeGetSeconds([[[[self player] currentItem] asset] duration]);
En lugar de obtenerlo directamente de AVPlayerItem, que le da 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];
Luego, dentro de 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 jugador:
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 ;-)