Cómo reducir el retraso de inicio de iOS AVPlayer

Tenga en cuenta, para la siguiente pregunta: Todos los activos son locales en el dispositivo, no se está realizando la transmisión de la red. Los videos contienen pistas de audio.

Estoy trabajando en una aplicación iOS que requiere la reproducción de archivos de video con un retraso mínimo para iniciar el videoclip en cuestión. Desafortunadamente, no sabemos qué video clip específico está a continuación hasta que realmente necesitamos iniciarlo. Específicamente: cuando se reproduzca un videoclip, sabremos cuál es el siguiente conjunto de (aproximadamente) 10 videoclips, pero no sabemos cuál exactamente, hasta que llega el momento de reproducir el siguiente clip 'inmediatamente'.

Lo que he hecho para ver los retrasos reales de inicio es llamaraddBoundaryTimeObserverForTimes en el reproductor de video, con un período de tiempo de un milisegundo para ver cuándo comenzó a reproducirse el video, y tomo la diferencia de esa marca de tiempo con el primer lugar en el código que indica qué activo comenzar a reproducir.

Por lo que he visto hasta ahora, he encontrado que usando la combinación deAVAsset cargando, y luego creando unaAVPlayerItem a partir de ese momento está listo, y luego esperandoAVPlayerStatusReadyToPlay antes de llamar a la reproducción, suele tardar entre 1 y 3 segundos en iniciar el clip.

Desde entonces he cambiado a lo que creo que es aproximadamente equivalente: llamar[AVPlayerItem playerItemWithURL:] y esperandoAVPlayerItemStatusReadyToPlay jugar. Aproximadamente el mismo rendimiento.

Una cosa que estoy observando es que la primera carga de elementos de AVPlayer es más lenta que el resto. Parece que una idea es hacer un vuelo previo al AVPlayer con un recurso corto / vacío antes de intentar reproducir el primer video que podría ser una buena práctica general. ElInicio lento para AVAudioPlayer la primera vez que se reproduce un sonido

Me encantaría que el tiempo de inicio del video sea lo más bajo posible, y tener algunas ideas de cosas para experimentar, pero me gustaría recibir orientación de cualquier persona que pueda ayudar.

Actualización: la idea 7, a continuación, según se implementa, produce tiempos de conmutación de alrededor de 500 ms. Esto es una mejora, pero sería bueno obtener esto aún más rápido.

Idea 1: usar N AVPlayers (no funcionará)

Utilizando ~ 10AVPPlayer objetos y comenzar y pausar todos los ~ 10 clips, y una vez que sepamos cuál realmente necesitamos, cambiamos y pausamos la pausa correctaAVPlayer, y empezar de nuevo para el siguiente ciclo.

No creo que esto funcione, porque he leído que hay aproximadamente un límite de 4 activosAVPlayer's en iOS. Alguien preguntó sobre esto en StackOverflow aquí, y se enteró del límite de 4 AVPlayer:cambio rápido entre los videos que usan

Idea 2: usar AVQueuePlayer (no funcionará)

No creo que empujar 10AVPlayerItems en unaAVQueuePlayer Los cargaría a todos para un arranque perfecto.AVQueuePlayer es una cola, y creo que en realidad solo prepara el siguiente video en la cola para la reproducción inmediata. No sé de cuál de los 10 videos que queremos reproducir, hasta que sea el momento de comenzar ese.ios-avplayer-video-preloading

Idea 3: Cargar, jugar y retenerAVPlayerItems en el fondo (todavía no estoy 100% seguro, pero no se ve bien)

Observo si hay algún beneficio para cargar y reproducir el primer segundo de cada videoclip en segundo plano (suprimir la salida de audio y video), y mantener una referencia a cada uno.AVPlayerItem, y cuando sepamos qué elemento se debe jugar de verdad, intercambie ese elemento y cambie el AVPlayer de fondo por el activo. Enjuague y repita.

La teoría sería que recientemente jugó.AVPlayer/AVPlayerItemEs posible que aún contengan algunos recursos preparados que harían la reproducción posterior más rápida. Hasta ahora, no he visto beneficios de esto, pero podría no tener elAVPlayerLayer Configuración correcta para el fondo. Dudo que esto realmente mejore las cosas de lo que he visto.

Idea 4: use un formato de archivo diferente, ¿quizás uno que sea más rápido de cargar?

Actualmente estoy usando el formato H.264 de .m4v (video-MPEG4). H.264 tiene muchas opciones diferentes de códecs, por lo que es posible que algunas opciones sean más rápidas de buscar que otras. Descubrí que el uso de configuraciones más avanzadas que hacen que el tamaño del archivo sea más pequeño aumenta el tiempo de búsqueda, pero no he encontrado ninguna opción que vaya a la inversa.

Idea 5: Combinación de formato de video sin pérdida + AVQueuePlayer

Si hay un formato de video que es rápido de cargar, pero tal vez donde el tamaño del archivo sea insano, una idea podría ser preparar previamente los primeros 10 segundos de cada video clip con una versión hinchada pero más rápida de cargar, pero de vuelta que hasta con un activo que está codificado en H.264. Use un AVQueuePlayer y agregue los primeros 10 segundos en el formato de archivo sin comprimir, y continúe con uno que esté en H.264, que obtiene hasta 10 segundos de tiempo de preparación / precarga. Así que obtendría lo mejor de ambos mundos: tiempos de inicio rápidos, pero también se beneficia de un formato más compacto.

Idea 6: Usar un AVPlayer no estándar / escribir mi propio / usar el de otra persona

Dadas mis necesidades, tal vez no pueda usar AVPlayer, pero tengo que recurrir a AVAssetReader, y descodificar los primeros segundos (posiblemente escribir el archivo raw en el disco), y cuando se trata de la reproducción, utilice el formato raw para reproducirlo vuelta rapido Me parece un gran proyecto, y si lo hago de una manera ingenua, no está claro / es poco probable que funcione mejor. Cada cuadro de video decodificado y sin comprimir es de 2.25 MB. Hablando ingenuamente: si vamos con ~ 30 fps para el video, terminaré con un requisito de ~ 60 MB / s de lectura del disco, lo que probablemente sea imposible / empujarlo. Obviamente, tendríamos que hacer un cierto nivel de compresión de imagen (quizás formatos de compresión openGL / es nativos a través de PVRTC) ... pero eso es un poco loco. Tal vez hay una biblioteca por ahí que puedo usar?

Idea 7: Combina todo en un solo activo de película y seekToTime

Una idea que podría ser más fácil que algunas de las anteriores, es combinar todo en una sola película y usar seekToTime. La cosa es que estaríamos saltando por todos lados. Esencialmente acceso aleatorio a la película. Creo que esto realmente puede funcionar bien:avplayer-movie-playing-lag-in-ios5

¿Qué enfoque crees que sería mejor? Hasta ahora, no he avanzado mucho en términos de reducir el retraso.

Respuestas a la pregunta(5)

Su respuesta a la pregunta