AVPlayerItem replaceCurrentItemWithPlayerItem Blocking

Primero, un pequeño context sobre la aplicación …
– Hay una gran cantidad de operaciones pesadas de interfaz de usuario que involucran a reproductores de video (en su mayoría desplazamientos)
– Los videos son dynamics y cambian según nuestra página actual.
– por lo que los videos deben ser dynamics y seguir cambiando y también la interfaz de usuario debe ser receptiva

Inicialmente estaba usando un MPMoviePlayerController pero luego, debido a ciertos requisitos, tuve que recurrir a AVPlayer
Hice mi propia envoltura para AVPlayer .
Para cambiar el contenido en el videoPlayer, este es el aspecto del método en la class de envoltorio AVPlayer

 /**We need to change the whole playerItem each time we wish to change a video url */ -(void)initializePlayerWithUrl:(NSURL *)url { AVPlayerItem *tempItem = [AVPlayerItem playerItemWithURL:url]; [tempItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:nil]; [tempItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:nil]; //Not sure if this should be stopped or paused under the ideal circumstances //These will be changed to custom enums later [self setPlaybackState:MPMoviePlaybackStateStopped]; [self setLoadState:MPMovieLoadStateUnknown]; [self.videoPlayer replaceCurrentItemWithPlayerItem:tempItem]; //This is requinetworking only if we wish to pause the video immediately as we change the url //[self.videoPlayer pause]; } 

Ahora, por supuesto, todo funcionaba bien … excepto …

 [self.videoPlayer replaceCurrentItemWithPlayerItem:tempItem]; 

Parece que está bloqueando la interfaz de usuario por una fracción de segundo y durante el desplazamiento esto hace que la interfaz de usuario no responda y sea fea, además esta operación no se puede realizar en segundo plano

¿Hay alguna solución o solución para esto …?

La solución que encontré fue asegurar que el AVAsset subyacente esté listo para devolver información básica, como su duración, antes de AVPlayer al AVPlayer . AVAsset tiene un método loadValuesAsynchronouslyForKeys: que es útil para esto:

 AVAsset *asset = [AVAsset assetWithURL:self.mediaURL]; [asset loadValuesAsynchronouslyForKeys:@[@"duration"] completionHandler:^{ AVPlayerItem *newItem = [[AVPlayerItem alloc] initWithAsset:asset]; [self.avPlayer replaceCurrentItemWithPlayerItem:newItem]; }]; 

En mi caso, la URL es un recurso de networking y replaceCurrentItemWithPlayerItem: realidad bloqueará durante varios segundos a la espera de que esta información se descargue de otra manera.

Tuvimos el mismo problema al build Ultravisual. No puedo recordar exactamente cómo lo resolvimos, pero IIRC implicó hacer la mayor cantidad posible de configuration del elemento en un subprocess de background, y esperar hasta que el nuevo elemento informe que está 'listo para reproducirse' antes de llamar a replaceCurrentItemWithPlayerItem .

Lamentablemente, esto implica una danza vudú con un KVO asíncrono algo inconsistente, que no es divertido.