2012-06-23 31 views
99

Tenga en cuenta que para la siguiente pregunta: todos los recursos son locales en el dispositivo, no se está produciendo la transmisión de la red. Los videos contienen pistas de audio.Cómo reducir el retraso de inicio de iOS AVPlayer

Estoy trabajando en una aplicación de iOS que requiere reproducir archivos de video con un retraso mínimo para iniciar el video clip en cuestión. Lamentablemente, no sabemos qué video clip es el siguiente hasta que realmente necesitemos iniciarlo. Específicamente: cuando se está reproduciendo un video, sabremos cuál es el siguiente conjunto de (aproximadamente) 10 video clips, pero no sabemos cuál exactamente, hasta que llegue el momento de reproducir el siguiente clip "inmediatamente".

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

Por lo que he visto hasta-ahora, he encontrado que el uso de la combinación de AVAsset carga y, a continuación, crear una AVPlayerItem de que una vez que esté listo, y luego esperar a que AVPlayerStatusReadyToPlay antes de que llame juego, tiende a tomar entre 1 y 3 segundos para comenzar el clip.

Desde entonces me he cambiado a lo que creo que es más o menos equivalente: llamar al [AVPlayerItem playerItemWithURL:] y esperar a que AVPlayerItemStatusReadyToPlay juegue. Aproximadamente el mismo rendimiento.

Una cosa que estoy observando es que la carga del primer elemento AVPlayer es más lenta que el resto. Parece que una idea es realizar un pre-vuelo del AVPlayer con un activo corto/vacío antes de intentar reproducir el primer video que podría ser una buena práctica general. [Slow start for AVAudioPlayer the first time a sound is played

Me encantaría tener los tiempos de inicio del video tanto como sea 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 implementa, produce tiempos de conmutación de alrededor de 500 ms. Esto es una mejora, pero sería bueno hacerlo aún más rápido.

Idea 1: Uso N AVPlayers (no funcionarán)

Usando ~ 10 AVPPlayer objetos y puesta en pausa y todos ~ 10 clips, y una vez que sabemos cuál realmente necesitamos, conmutador para, y sin pausa, el AVPlayer correcto, y vuelva a comenzar para el próximo ciclo.

No creo que esto funcione, porque he leído que hay aproximadamente un límite de 4 AVPlayer's activos en iOS. Hubo alguien que preguntaba sobre esto en StackOverflow aquí, y descubrió el límite de 4 AVPlayer: fast-switching-between-videos-using-avfoundation

Idea 2: Uso AVQueuePlayer (no funciona)

no creo que empujar 10 AVPlayerItems en un AVQueuePlayer los precargará todos para un inicio sin interrupciones. AVQueuePlayer es una cola, y creo que realmente solo hace que el siguiente video en la cola esté listo para su reproducción inmediata. No sé cuál de los ~ 10 videos que queremos reproducir, hasta que sea hora de comenzar ese.ios-avplayer-video-preloading

Idea 3: Carga, Play, y retener AVPlayerItems en el fondo (no es 100% seguro todavía - pero no en buen estado)

estoy mirando si hay algún beneficio para cargar y reproducir el primer segundo de cada videoclip en segundo plano (suprima la salida de audio y video), y mantenga una referencia a cada AVPlayerItem, y cuando sepamos qué elemento debe reproducirse de manera real, intercambie ese uno y cambie el fondo de AVPlayer por el activo Enjuague y repita.

La teoría sería que recientemente se ha reproducido AVPlayer/AVPlayerItem 's todavía puede contener algunos recursos preparados que harían la posterior reproducción más rápida. Hasta ahora, no he visto beneficios de esto, pero es posible que no tenga la configuración AVPlayerLayer correctamente para el fondo. Dudo que esto realmente mejore las cosas de lo que he visto.

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

Actualmente estoy usando .m4v (video-MPEG4) formato H.264. H.264 tiene muchas opciones diferentes de códec, por lo que es posible que algunas opciones sean más rápidas de buscar que otras. He descubierto 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 ha encontrado ninguna opción que vaya en la otra dirección.

Idea 5: combinación de formato de vídeo sin pérdida + AVQueuePlayer

Si hay un formato de vídeo que es rápido para cargar, pero tal vez en que el tamaño del archivo es una locura, una idea podría ser la de pre-preparar el los primeros 10 segundos de cada video clip con una versión hinchada pero más rápida de cargar, pero respaldada con un activo codificado en H.264. Use un AVQueuePlayer, y agregue los primeros 10 segundos en el formato de archivo sin comprimir, y siga 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: Utilice un AVPlayer no estándar/escribir mi propia/usar de otra persona

Dadas mis necesidades, tal vez no puedo usar AVPlayer, pero tienen que recurrir a AVAssetReader, y decodificar la primera unos segundos (posiblemente, escriba el archivo sin procesar en el disco), y cuando se trata de reproducción, utilice el formato sin formato para reproducirlo rápidamente. Parece un gran proyecto para mí, y si lo hago de una manera ingenua, no está claro/es probable que incluso funcione mejor. Cada cuadro de video decodificado y sin comprimir tiene 2.25 MB. Hablando ingenuamente, si vamos con ~ 30 fps para el video, terminaría con un requisito de lectura de disco de ~ 60 MB/s, lo que probablemente sea imposible/lo presione. Obviamente, tendríamos que hacer un cierto nivel de compresión de imágenes (tal vez formatos de compresión nativos de OpenGL/es a través de PVRTC) ... pero eso es una locura. Tal vez hay una biblioteca por ahí que puedo usar?

Idea 7: Combine todo en un solo activo película, y seekToTime

Una idea que podría ser más fácil que algunos de los anteriores, es combinar todo en una sola película, y utilizar seekToTime. El caso 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

¿Cuál enfoque crees que sería el mejor? Hasta ahora, no he progresado tanto en términos de reducción del retraso.

+0

Por lo que vale la pena, voy con la idea 7. Todavía es lento, pero no es tan impredecible lento como las otras opciones. La siguiente pregunta que tengo es: ¿las opciones del códec, la resolución y la frecuencia de las tramas clave tienen un impacto en la búsqueda del tiempo? –

+0

Tarde en el juego, pero puede valer la pena cambiar los videos lo más rápido posible (es decir, inmediatamente después de que el nuevo comienza a reproducirse) y perfilar la aplicación para ver dónde pasa la mayor parte de su tiempo de CPU. –

+1

Casi un año después, ¿qué descubriste con esto? – lnafziger

Respuesta

0

Sin haber hecho algo como esto en el pasado, basándome en sus pensamientos y experiencias probaría una combinación de 7 y 1: precargar un AVPlayer con los primeros segundos de los 10 videos de seguimiento. Entonces es muy probable que omitir sea más rápido y más confiable debido a la menor cantidad de datos. Mientras reproduce la pieza seleccionada, tiene tiempo suficiente para preparar el AVPlayer para el resto del video de seguimiento seleccionado en el fondo. Cuando el comienzo está terminado, cambia al AVPlayer preparado. Entonces, en total, usted en un momento dado tiene un máximo de 2 AVPlayers cargados.

Por supuesto que no saben si la conmutación se puede hacer tan bien que no perturbe la reproducción.

(habría añadido esto como un comentario si pudiera.)

Best, Peter

+0

No he encontrado ningún beneficio de cargar 10 activos en serie en un AVPlayer. Además, no entiendo su sugerencia, ya que veo la opción (1) y (7) mutuamente excluyentes. La opción 7 fusiona todos los activos de video en un único activo, por lo que solo hay un único activo para el período de carga. Esto es lo que estoy haciendo hoy, y por lo que vale, tengo aproximadamente 500 ms de retraso en los tiempos reales de inicio/juego. Vale la pena señalar que el SeekTo se completa más rápido que el primer fotograma real, por lo que para los verdaderos tiempos de inicio, mido cuando el primer fotograma se está reproduciendo a través de una devolución de llamada programada. –

+0

Solo para aclarar mi idea: mi idea era dividir un activo en dos partes: los primeros segundos y el resto. Ahora ha creado dos activos de uno. Los 10 comienzos en los que te unirías y usarías omitir y, al jugar al principio, cargarías el resto. Esto comprende la sugerencia 8 que se agrega a su lista. – ilmiacs

+0

Pero, según tengo entendido por su último comentario, mientras tanto empujó la investigación más allá de lo que es bueno, y la solución 7 tampoco funciona. Parece que AV básicamente se mantiene en su camino y la única forma de que usted vaya probablemente sea utilizar la tecnología subyacente, que es Core Media, para tener más control sobre sus activos. Peter. – ilmiacs

1

El activo puede no listo una vez que lo crea, es posible que no cálculos como la duración de la película, asegúrese de contiene todos los metadatos de la película en el archivo.

1

Usted debe tratar opción # 7 en primer lugar, sólo para ver si usted puede conseguir que de trabajo. Sospecho que en realidad no funcionará para sus necesidades, ya que el tiempo de búsqueda probablemente no sea lo suficientemente rápido como para proporcionarle un cambio sin interrupciones entre los clips. Si prueba eso y falla, le aconsejaría que haga la opción 4/6 y eche un vistazo a mi biblioteca de iOS diseñada específicamente para este propósito, solo haga una búsqueda rápida en Google en AVAnimator para obtener más información. Mi biblioteca hace posible implementar bucles sin interrupciones y cambiar de un clip a otro, es muy rápido porque el video debe decodificarse en un archivo de antemano. En su caso, los 10 videoclips serían decodificados en archivos antes de comenzar, pero luego cambiarlos sería rápido.

+0

¿Qué pasa con la parte de audio del video? Necesito que el video y el audio estén sincronizados. –

+0

Sí, el audio ya se maneja con una sincronización muy ajustada entre la pista de audio y el videoclip. Vea el ejemplo de proyectos xcode. Ya está todo implementado, solo necesitas descargarlo y probarlo. – MoDJ

+0

¿Existe la posibilidad de reproducir video de red con AVAnimator? –

-1

Aquí hay varias propiedades y métodos proporcionados por la clase AVAsset que pueden ayudar:

- (void)_pu_setCachedDuration:(id)arg1; 
- (id)pu_cachedDuration; 
- (struct 
{ 
    long long x1; 
    int x2; 
    unsigned int x3; 
    long long x4; 
})pu_duration; 
- (void)pu_loadDurationWithCompletionHandler:(id /* block */)arg1; 
0

Si he entendido el problema correctamente, parece que usted tiene un video continua a la que tiene que cargar la pista de audio para en un momento previo aviso.

Si ese es el caso Sugiero mirar en BASS. BASS es una biblioteca de audio muy similar a AVPlayer que le brinda acceso (relativamente) fácil a las API de bajo nivel del framework AudioUnits en iOS. ¿Qué significa para ti? Significa que con un poco de manipulación del búfer (puede que ni lo necesite, depende de qué tan pequeño desee el retraso) puede comenzar a reproducir música al instante.

Sin embargo, las limitaciones se extienden al video, como ya dije, es una biblioteca de audio por lo que cualquier manipulación de video tendrá que realizarse con AVPlayer. Sin embargo, al usar -seekToTime:toleranfeBefore:toleranceAfter:, debe poder lograr una búsqueda rápida dentro del video, siempre y cuando se despliegue previamente con todas las opciones necesarias.

Si estás sincronizando a través de múltiples dispositivos (lo que podría sugerir su aplicación) simplemente dejar un comentario y yo estaría feliz de editar mi respuesta.

PS: BASS puede parecer intimidante al principio debido a su formato similar a C, pero en realidad es muy fácil de usar para lo que es.

Cuestiones relacionadas