Tenga en cuenta que para la siguiente pregunta: Todos los activos son locales en el dispositivo; no se está realizando ninguna transmisión de red. Los videos contienen pistas de audio.
Estoy trabajando en una aplicación de iOS que requiere reproducir archivos de video con un retraso mínimo para iniciar el videoclip en cuestión. Desafortunadamente, no sabemos qué videoclip específico es el siguiente hasta que realmente necesitamos iniciarlo. Específicamente: cuando se reproduce un videoclip, sabremos cuál es el siguiente conjunto de (aproximadamente) 10 videoclips, pero no sabemos cuál es exactamente, hasta que llegue el momento de reproducir "inmediatamente" el siguiente clip.
Lo que he hecho para ver los retrasos de inicio reales es llamar addBoundaryTimeObserverForTimes
al 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 jugar.
Por lo que he visto hasta ahora, he descubierto que usar la combinación de AVAsset
cargar, y luego crear una a AVPlayerItem
partir de eso una vez que está lista, y luego esperar AVPlayerStatusReadyToPlay
antes de llamar a play, tiende a tomar entre 1 y 3 segundos para iniciar la acortar.
Desde entonces, cambié a lo que creo que es aproximadamente equivalente: llamar [AVPlayerItem playerItemWithURL:]
y esperar para AVPlayerItemStatusReadyToPlay
jugar. Aproximadamente el mismo rendimiento.
Una cosa que estoy observando es que la carga del primer elemento de AVPlayer es más lenta que el resto. Parece que una idea es realizar un vuelo previo del AVPlayer con un activo corto / vacío antes de intentar reproducir el primer video. Podría ser una buena práctica general. [ Inicio lento para AVAudioPlayer la primera vez que se reproduce un sonido
Me encantaría reducir los tiempos de inicio del video tanto como sea posible y tener algunas ideas de cosas con las que 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 hacerlo aún más rápido.
Idea 1: use N AVPlayers (no funcionará)
Usando ~ 10 AVPPlayer
objetos e inicie y pause los ~ 10 clips, y una vez que sepamos cuál necesitamos realmente, cambiemos y cancelemos la pausa del correcto AVPlayer
, y comience de nuevo para el siguiente ciclo.
No creo que esto funcione, porque he leído que hay aproximadamente un límite de 4 activos AVPlayer's
en iOS. Alguien preguntó sobre esto en StackOverflow aquí y descubrió el límite de 4 AVPlayer: cambio rápido entre videos usando avfoundation
Idea 2: use AVQueuePlayer (no funcionará)
No creo que meter 10 AVPlayerItems
en un AVQueuePlayer
precargarlos todos para comenzar sin problemas. AVQueuePlayer
es una cola, y creo que en realidad solo hace que el siguiente video de la cola esté listo para su reproducción inmediata. No sé cuál de ~ 10 videos queremos reproducir, hasta que sea el momento de comenzar con ese. ios-avplayer-video-preloading
Idea 3: cargar, reproducir y retener AVPlayerItems
en segundo plano (todavía no estoy 100% seguro, pero no se ve bien)
Estoy viendo si hay algún beneficio para cargar y reproducir el primer segundo de cada clip de video en segundo plano (suprimir la salida de video y audio), y mantener una referencia a cada uno AVPlayerItem
, y cuando sepamos qué elemento debe reproducirse real, cámbielo y cambie el AVPlayer de fondo por el activo. Enjuague y repita.
La teoría sería que los reproducidos recientemente AVPlayer/AVPlayerItem
pueden contener algunos recursos preparados que harían más rápida la reproducción posterior. Hasta ahora, no he visto beneficios de esto, pero es posible que no tenga la AVPlayerLayer
configuración correcta para el fondo. Dudo que esto realmente mejore las cosas de lo que he visto.
Idea 4: utilice un formato de archivo diferente, ¿tal vez 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 de códec diferentes, 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 al revés.
Idea 5: combinación de formato de video sin pérdida + AVQueuePlayer
Si hay un formato de video que se carga rápidamente, pero tal vez donde el tamaño del archivo es una locura, una idea podría ser preparar previamente los primeros 10 segundos de cada clip de video con una versión que esté hinchada pero que se cargue más rápido, pero al revés eso 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 obtenga 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: use un AVPlayer no estándar / escriba el mío / use el de otra persona
Dadas mis necesidades, tal vez no pueda usar AVPlayer, pero tengo que recurrir a AVAssetReader y decodificar los primeros segundos (posiblemente escribir un archivo sin procesar en el disco), y cuando se trata de reproducción, hacer uso del formato sin procesar para reproducirlo. volver rápido. 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 elegimos ~ 30 fps para el video, terminaría con un requisito de lectura desde el disco de ~ 60 MB / s, lo que probablemente sea imposible / presionarlo. Obviamente, tendríamos que hacer algún nivel de compresión de imagen (quizás formatos de compresión nativos openGL / es a través de PVRTC) ... pero eso es una locura. ¿Quizás hay una biblioteca que pueda usar?
Idea 7: combine todo en un solo recurso de película y busque a tiempo
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. Lo que pasa es que estaríamos saltando por todos lados. Acceso esencialmente aleatorio a la película. Creo que esto 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:
Para iOS 10.xy superior para reducir el retraso de inicio de AVPlayer, configuré:
avplayer.automaticallyWaitsToMinimizeStalling = false;
y eso pareció arreglarlo para mí. Esto podría tener otras consecuencias, pero aún no las he alcanzado.Tengo la idea de: https://stackoverflow.com/a/50598525/9620547
fuente
Es posible que el activo no esté listo una vez que lo cree, puede realizar cálculos como la duración de la película, asegúrese de contener todos los metadatos de la película en el archivo.
fuente
Primero debe probar la opción # 7, solo para ver si puede hacer que funcione. Sospecho que en realidad no funcionará para sus necesidades, ya que es probable que el tiempo de búsqueda no sea lo suficientemente rápido como para brindarle un cambio perfecto entre clips. Si lo intenta y falla, le aconsejaría que opte por la opción 4/6 y eche un vistazo a mi biblioteca de iOS diseñada específicamente para este propósito, simplemente haga una búsqueda rápida en Google en AVAnimator para obtener más información. Mi biblioteca permite 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 se decodificarían en archivos antes de comenzar, pero luego cambiar entre ellos sería rápido.
fuente
Sin haber hecho nada como esto en el pasado, basándome en sus pensamientos y experiencias, probaría una combinación de 7 y 1: precargue un AVPlayer con los primeros segundos de los 10 videos de seguimiento. Entonces, es muy probable que la omisión sea más rápida y 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 segundo plano. Cuando finaliza el comienzo, cambia al AVPlayer preparado. Entonces, en total, en un momento dado tiene un máximo de 2 AVPlayers cargados.
Por supuesto, no sé si el cambio se puede hacer con tanta fluidez que no perturbe la reproducción.
(Habría agregado esto como comentario si pudiera).
Mejor, Peter
fuente
Si entendí correctamente su problema, parece que tiene un video continuo en el que necesita cargar la pista de audio en un momento.
Si ese es el caso, sugiero mirar en BASS . BASS es una biblioteca de audio muy parecida a AVPlayer que le brinda (relativamente) fácil acceso a las API de bajo nivel del marco AudioUnits en iOS. ¿Qué significa para ti? Significa que con un poco de manipulación del búfer (es posible que ni siquiera 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 dije, es una biblioteca de audio , por lo que cualquier manipulación de video deberá realizarse con AVPlayer. Sin embargo, al usarlo
-seekToTime:toleranfeBefore:toleranceAfter:
, debería poder lograr una búsqueda rápida dentro del video siempre que realice un pre-roll con todas las opciones necesarias.Si está sincronizando en varios dispositivos (lo que su aplicación podría sugerir) simplemente deje un comentario y estaré encantado de editar mi respuesta.
PD: BASS puede parecer desalentador al principio debido a su formato tipo C, pero es realmente muy fácil de usar por lo que es.
fuente
Aquí hay varias propiedades y métodos proporcionados por la clase AVAsset que pueden ayudar:
fuente