¿Cómo me logging cuando AVPlayer realmente comienza a reproducirse (desde una fuente externa)?

Estoy teniendo problemas para registrar CUANDO el reproductor está comenzando a reproducir videos externos (a través de Internet) usando AVPlayer . Lea la pregunta antes de sugerir soluciones. Inicializo el reproductor así:

 player = [[AVPlayer alloc] initWithURL:[[NSURL alloc] initWithString:@"http://example.com/video.mp4"]]; playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; [playerLayer setFrame:[videoView bounds]]; [videoView.layer addSublayer:playerLayer]; 

Esto agrega el reproductor a la vista correctamente. He agregado las siguientes dos líneas de código para mantener un logging de cuándo está listo el jugador, y cuál es el estado / tasa;

 [player addObserver:self forKeyPath:@"rate" options:0 context:nil]; [player addObserver:self forKeyPath:@"status" options:0 context:nil]; 

Estas dos líneas llamarán al método - (void)observeValueForKeyPath:.... cuando algo cambie con el estado o la velocidad del AVPlayer .

Hasta ahora, se ve así:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { //To print out if it is 'rate' or 'status' that has changed: NSLog(@"Changed: %@", keyPath); if ([keyPath isEqualToString:@"rate"]) //If rate has changed: { if ([player rate] != 0) //If it started playing { NSLog(@"Total time: %f", CMTimeGetSeconds([[player currentItem] duration])); // This NSLog is supposed to print out the duration of the video. [self setControls]; // This method (setControls) is supposed to set play/pause-buttons // as well as labels for the current and total time of the current video. } } else if ([keyPath isEqualToString:@"status"]) // If the status changed { if(player.status == AVPlayerStatusReadyToPlay) //If "ReadyToPlay" { NSLog(@"ReadyToPlay"); [player play]; //Start the video } } } 

El state del AVPlayer cambia a readyToPlay casi inmediatamente después de inicializarlo, y luego llamo [player play] . Cuando esto sucede, la rate cambia a 1.00000 , lo que significa que en realidad se está reproduciendo a esa velocidad, pero el video ahora está comenzando a almacenarse, no a jugar. La pantalla es negra y tarda unos segundos y luego comienza a reproducirse. La tasa, sin embargo, indica que comienza a jugar antes de que lo haga. La tasa se mantiene en 1.00000 , y no baja a 0 cuando se inicia el almacenamiento en búfer, lo que dificulta mucho saber cuándo el jugador tiene suficiente información para comenzar a configurar los controles (sellos de time IE, etc.).

El NSLog() imprime la duración del video anterior imprime nan (Not A Number), lo que me lleva a pensar que el ítem no está listo para ser reproducido, sin embargo, la tasa se mantiene en 1.0000 hasta que se haya almacenado en un buffer , entonces realmente se reproducirá, aún con una tasa de 1.0000 .

Sin embargo, recibe una llamada dos veces. La rate "cambia" a 1.0000 dos veces sin ser otra cosa en el medio. En ninguna de las llamadas, la duración del video es una variable disponible.

Mi objective es get la timestamp actual y total del video lo más rápido posible (IE 0:00/3:52 ). Esto también se utilizará para registrar el lavado de un control deslizante (para avance rápido, etc.).

Estos valores no están listos cuando el jugador me notifica que está reproduciendo a una velocidad de 1.0000 , dos veces. Si presiono "reproducir" manualmente después de un segundo más o less (y llamo [player play] ), entonces está funcionando. ¿Cómo me puedo registrar para saber cuándo está listo el video, no solo 'listo para estar listo'?

Ver addBoundaryTimeObserverForTimes: queue: usingBlock: en AVPlayer y este ejemplo de Apple.

 AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:@"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"]]; [player play]; // Assumes a property: @property (strong) id playerObserver; // Cannot use kCMTimeZero so instead use a very small period of time self.playerObserver = [player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:CMTimeMake(1, 1000)]] queue:NULL usingBlock:^{ //Playback started [player removeTimeObserver:self.playerObserver]; }]; 

Creo que lo más cercano a ti es observar player.currentItem.playbackLikelyToKeepUp