Solución de problemas


Cómo corregir los errores "No se permite el tráfico HTTP de texto simple"

Este error ocurrirá si tu app solicita tráfico HTTP de texto simple (es decir, http:// en lugar de https://) cuando su configuración de seguridad de red no lo permita. Si tu app se orienta a Android 9 (nivel de API 28) o versiones posteriores, la configuración predeterminada inhabilita el tráfico HTTP de texto simple.

Si tu app necesita funcionar con tráfico HTTP de texto simple, debes usar una configuración de seguridad de red que lo permita. Para obtener más información, consulta la documentación sobre seguridad de red de Android. Para habilitar todo el tráfico HTTP de texto simple, simplemente puedes agregar android:usesCleartextTraffic="true" al elemento application del AndroidManifest.xml de tu app.

La app de demostración de ExoPlayer usa la configuración de seguridad de red predeterminada, por lo que no permite el tráfico HTTP de texto simple. Puedes habilitarla según las instrucciones anteriores.

Corrige los errores "SSLHandshakeException", "CertPathValidatorException" y "ERR_CERT_AUTHORITY_INVALID".

SSLHandshakeException, CertPathValidatorException y ERR_CERT_AUTHORITY_INVALID indican un problema con el certificado SSL del servidor. Estos errores no son específicos de ExoPlayer. Consulta la documentación de SSL de Android para obtener más detalles.

¿Por qué no se pueden buscar algunos archivos multimedia?

De forma predeterminada, ExoPlayer no admite los saltos en contenido multimedia en el que el único método para realizar operaciones de búsqueda precisas es que el reproductor explore e indexe todo el archivo. ExoPlayer considera que estos archivos son imposibles de buscar. La mayoría de los formatos modernos de contenedores multimedia incluyen metadatos de búsqueda (como un índice de muestra), tienen un algoritmo de búsqueda bien definido (por ejemplo, búsqueda de bisección interpolada para Ogg) o indican que su contenido tiene una tasa de bits constante. En estos casos, ExoPlayer admite operaciones de búsqueda eficientes.

Si necesitas buscar contenido multimedia que no se puede buscar, te sugerimos que conviertas el contenido para usar un formato de contenedor más apropiado. Para los archivos MP3, ADTS y AMR, también puedes habilitar la búsqueda bajo el supuesto de que los archivos tienen una tasa de bits constante, como se describe aquí.

¿Por qué la búsqueda es inexacta en algunos archivos MP3?

Los archivos MP3 con tasa de bits variable (VBR) no son adecuados principalmente para los casos de uso que requieren una búsqueda exacta. Esto se debe a dos motivos:

  1. Para la búsqueda exacta, un formato de contenedor proporcionará idealmente una asignación precisa de tiempo a bytes en un encabezado. Esta asignación permite que un jugador asigne un tiempo de búsqueda solicitado al desplazamiento de bytes correspondiente y comience a solicitar, analizar y reproducir contenido multimedia desde ese desplazamiento. Lamentablemente, los encabezados disponibles para especificar esta asignación en MP3 (como los encabezados XING) son, a menudo, imprecisos.
  2. Para los formatos de contenedor que no proporcionan una asignación precisa de tiempo a bytes (o cualquier asignación de tiempo a bytes), es posible realizar una búsqueda exacta si el contenedor incluye marcas de tiempo de muestra absolutas en la transmisión. En este caso, un jugador puede asignar el tiempo de búsqueda a la mejor estimación del desplazamiento de bytes correspondiente, comenzar a solicitar contenido multimedia desde ese desplazamiento, analizar la primera marca de tiempo de muestra absoluta y realizar de manera efectiva una búsqueda binaria guiada en el contenido multimedia hasta encontrar la muestra correcta. Lamentablemente, MP3 no incluye marcas de tiempo de muestra absolutas en la transmisión, por lo que este enfoque no es posible.

Por estos motivos, la única forma de realizar una búsqueda exacta en un archivo VBR MP3 es escanear todo el archivo y crear manualmente una asignación de tiempo a bytes en el reproductor. Esta estrategia se puede habilitar con FLAG_ENABLE_INDEX_SEEKING, que se puede configurar en un DefaultExtractorsFactory con setMp3ExtractorFlags. Ten en cuenta que no se ajusta bien a archivos MP3 grandes, en especial si el usuario intenta acercarse al final de la transmisión poco después de comenzar la reproducción, lo que requiere que el reproductor espere hasta que se descargue e indexe toda la transmisión antes de realizarla. En ExoPlayer, decidimos optimizar la velocidad sobre la precisión en este caso y, por lo tanto, FLAG_ENABLE_INDEX_SEEKING está inhabilitado de forma predeterminada.

Si controlas el contenido multimedia que reproduces, te recomendamos que uses un formato de contenedor más adecuado, como MP4. No conocemos casos de uso en los que MP3 sea la mejor opción de formato de medios.

¿Por qué los saltos en mi video son lentos?

Cuando el reproductor busca una nueva posición de reproducción en un video, debe realizar dos acciones:

  1. Carga los datos correspondientes a la nueva posición de reproducción en el búfer (es posible que esto no sea necesario si los datos ya se almacenaron en el búfer).
  2. Vacía el decodificador de video y comienza a decodificar desde el fotograma I (fotograma clave) antes de la nueva posición de reproducción, debido a la codificación dentro del fotograma que usan la mayoría de los formatos de compresión de video. Para garantizar que la búsqueda sea precisa (es decir, la reproducción comienza exactamente en la posición de búsqueda), todos los fotogramas entre el fotograma I anterior y la posición de búsqueda deben decodificarse y descartarse de inmediato (sin mostrarse en la pantalla).

La latencia que ingresa (1) se puede mitigar si aumentas la cantidad de datos que almacena el reproductor en la memoria o almacenas en caché previamente los datos en el disco.

La latencia que introdujo (2) se puede mitigar reduciendo la precisión de la búsqueda con ExoPlayer.setSeekParameters o volviendo a codificar el video para que tenga fotogramas I más frecuentes (lo que generará un archivo de salida más grande).

¿Por qué no se reproducen algunos archivos MPEG-TS?

Algunos archivos MPEG-TS no contienen delimitadores de unidad de acceso (AUD). De forma predeterminada, ExoPlayer se basa en AUD para detectar límites de fotogramas de forma económica. Del mismo modo, algunos archivos MPEG-TS no contienen fotogramas clave de IDR. De forma predeterminada, este es el único tipo de fotogramas clave que considera ExoPlayer.

Parece que ExoPlayer está atascado en el estado de almacenamiento en búfer cuando se le solicita que reproduzca un archivo MPEG-TS que no incluya fotogramas clave con AUD o IDR. Si necesitas reproducir estos archivos, puedes hacerlo con FLAG_DETECT_ACCESS_UNITS y FLAG_ALLOW_NON_IDR_KEYFRAMES, respectivamente. Estas marcas se pueden configurar en un DefaultExtractorsFactory mediante setTsExtractorFlags o en un DefaultHlsExtractorFactory con el constructor. El uso de FLAG_DETECT_ACCESS_UNITS no tiene efectos secundarios aparte de la carga computacional en relación con la detección del límite de fotogramas basada en AUD. El uso de FLAG_ALLOW_NON_IDR_KEYFRAMES puede provocar una corrupción visual temporal al comienzo de la reproducción e inmediatamente después de las búsquedas cuando se reproducen algunos archivos MPEG-TS.

¿Por qué no se encuentran subtítulos en algunos archivos MPEG-TS?

Algunos archivos MPEG-TS incluyen pistas CEA-608, pero no las declaran en los metadatos del contenedor, por lo que ExoPlayer no puede detectarlas. Para especificar manualmente las pistas de subtítulos, proporciona una lista de los formatos de subtítulos esperados a DefaultExtractorsFactory, incluidos los canales de accesibilidad que se pueden usar para identificarlos en la transmisión MPEG-TS:

Kotlin

val extractorsFactory =
  DefaultExtractorsFactory()
    .setTsSubtitleFormats(
      listOf(
        Format.Builder()
          .setSampleMimeType(MimeTypes.APPLICATION_CEA608)
          .setAccessibilityChannel(accessibilityChannel)
          // Set other subtitle format info, such as language.
          .build()
      )
    )
val player: Player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, extractorsFactory)).build()

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory()
        .setTsSubtitleFormats(
            ImmutableList.of(
                new Format.Builder()
                    .setSampleMimeType(MimeTypes.APPLICATION_CEA608)
                    .setAccessibilityChannel(accessibilityChannel)
                    // Set other subtitle format info, such as language.
                    .build()));
Player player =
    new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, extractorsFactory))
        .build();

¿Por qué algunos archivos MP4/FMP4 se reproducen incorrectamente?

Algunos archivos MP4 o FMP4 contienen listas de edición que reescriben el cronograma de contenido multimedia mediante la omisión, el movimiento o la repetición de listas de muestras. ExoPlayer es compatible parcialmente con la aplicación de listas de edición. Por ejemplo, puede retrasar o repetir grupos de muestras que comienzan en una muestra de sincronización, pero no trunca las muestras de audio ni los medios previos al video para las ediciones que no comienzan en una muestra de sincronización.

Si ves que una parte del contenido multimedia falta o se repite inesperadamente, prueba configurar Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS o FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS, lo que hará que el extractor ignore por completo las listas de edición. Se pueden configurar en un DefaultExtractorsFactory con setMp4ExtractorFlags o setFragmentedMp4ExtractorFlags.

¿Por qué algunas transmisiones fallan con el código de respuesta HTTP 301 o 302?

Los códigos de respuesta HTTP 301 y 302 indican redireccionamiento. Puedes encontrar descripciones breves en Wikipedia. Cuando ExoPlayer realiza una solicitud y recibe una respuesta con el código de estado 301 o 302, por lo general, seguirá el redireccionamiento y comenzará la reproducción con normalidad. El único caso en el que esto no sucede de forma predeterminada es con los redireccionamientos entre protocolos. Un redireccionamiento entre protocolos es aquel que redirecciona de HTTPS a HTTP o viceversa (o menos frecuente, entre otro par de protocolos). Puedes probar si una URL provoca un redireccionamiento entre protocolos con la herramienta de línea de comandos wget de la siguiente manera:

wget "https://yourserver.com/test.mp3" 2>&1  | grep Location

El resultado debería ser similar a este:

Location: https://second.com/test.mp3 [following]
Location: http://third.com/test.mp3 [following]

En este ejemplo, hay dos redireccionamientos. El primer redireccionamiento es de https://yourserver.com/test.mp3 a https://second.com/test.mp3. Ambos son HTTPS, por lo que este no es un redireccionamiento entre protocolos. El segundo redireccionamiento es de https://second.com/test.mp3 a http://third.com/test.mp3. Esto redirecciona de HTTPS a HTTP, al igual que un redireccionamiento entre protocolos. ExoPlayer no seguirá este redireccionamiento en su configuración predeterminada, lo que significa que la reproducción fallará.

Si es necesario, puedes configurar ExoPlayer para que siga redireccionamientos entre protocolos cuando se crean instancias de DefaultHttpDataSource.Factory instancias que se usan en tu aplicación. Obtén información para seleccionar y configurar la pila de red aquí.

¿Por qué algunas transmisiones fallan con UnrestrictedInputFormatException?

Esta pregunta se relaciona con las fallas de reproducción en la siguiente forma:

UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.

Hay dos causas posibles para este error. La causa más común es que intentas reproducir contenido DASH (mpd), HLS (m3u8) o SmoothStreaming (ism, isml), pero el reproductor intenta reproducirlo como una transmisión progresiva. Para reproducir estas transmisiones, debes depender del módulo de ExoPlayer respectivo. En los casos en que el URI de transmisión no termina con la extensión de archivo estándar, también puedes pasar MimeTypes.APPLICATION_MPD, MimeTypes.APPLICATION_M3U8 o MimeTypes.APPLICATION_SS a setMimeType de MediaItem.Builder para especificar de forma explícita el tipo de transmisión.

La segunda causa menos común es que ExoPlayer no admite el formato contenedor del contenido multimedia que intentas reproducir. En este caso, la falla funciona según lo previsto. Sin embargo, no dudes en enviar una solicitud de función a nuestra herramienta de seguimiento de errores, incluidos los detalles del formato del contenedor y un flujo de prueba. Busca una solicitud de función existente antes de enviar una nueva.

¿Por qué el parámetro setPlaybackParameters no funciona correctamente en algunos dispositivos?

Cuando ejecutas una compilación de depuración de tu app en Android M y versiones anteriores, es posible que experimentes un rendimiento entrecortado, artefactos audibles y un alto uso de CPU cuando usas la API de setPlaybackParameters. Esto se debe a que una optimización importante para esta API está inhabilitada para las compilaciones de depuración que se ejecutan en estas versiones de Android.

Es importante tener en cuenta que este problema solo afecta a las compilaciones de depuración. No afecta las compilaciones de lanzamiento, para las que la optimización siempre está habilitada. Por lo tanto, las versiones que proporciones a los usuarios finales no deberían verse afectadas por este problema.

¿Qué significan los errores de "Se accede al reproductor en el subproceso incorrecto"?

Consulta Nota sobre los subprocesos en la página de introducción.

¿Cómo puedo solucionar el problema “Línea de estado inesperado: ICY 200 OK”?

Este problema puede ocurrir si la respuesta del servidor incluye una línea de estado ICY, en lugar de una que sea compatible con HTTP. Las líneas de estado ICY están obsoletas y no deben usarse, por lo que si controlas el servidor, debes actualizarlo para proporcionar una respuesta compatible con HTTP. Si no puedes hacerlo, el uso de la biblioteca de OkHttp de ExoPlayer resolverá el problema, ya que puede manejar las líneas de estado ICY correctamente.

¿Cómo puedo consultar si la transmisión que se está reproduciendo es en vivo?

Puedes consultar el método isCurrentWindowLive del reproductor. Además, puedes verificar isCurrentWindowDynamic para averiguar si la ventana es dinámica (es decir, aún se actualiza con el tiempo).

¿Cómo continúo reproduciéndose cuando mi app está en segundo plano?

Sigue estos pasos para garantizar la reproducción continua de audio cuando la app está en segundo plano:

  1. Debes tener un servicio en primer plano en ejecución. Esto evita que el sistema finalice el proceso para liberar recursos.
  2. Debes conservar una WifiLock y una WakeLock. De esta manera, se garantiza que el sistema mantenga activos la radio Wi-Fi y la CPU. Esto se puede hacer fácilmente si se usa ExoPlayer llamando a setWakeMode, que adquirirá y liberará automáticamente los bloqueos necesarios en los momentos correctos.

Es importante que liberes los bloqueos (si no usas setWakeMode) y detengas el servicio en cuanto se deje de reproducir audio.

¿Por qué ExoPlayer admite mi contenido, pero la biblioteca de Cast de ExoPlayer no?

Es posible que el contenido que intentas reproducir no esté habilitado para CORS. El framework de Cast requiere que el contenido esté habilitado para CORS a fin de reproducirlo.

¿Por qué el contenido no se reproduce y no aparece ningún error?

Es posible que el dispositivo en el que reproduces el contenido no admita un formato de muestra de contenido multimedia específico. Para confirmarlo fácilmente, agrega un objeto EventLogger como objeto de escucha al reproductor y busca una línea similar a esta en Logcat:

[ ] Track:x, id=x, mimeType=mime/type, ... , supported=NO_UNSUPPORTED_TYPE

NO_UNSUPPORTED_TYPE significa que el dispositivo no puede decodificar el formato de muestra de contenido multimedia especificado por mimeType. Consulta la documentación de formatos multimedia de Android para obtener información sobre los formatos de muestra compatibles. ¿Cómo puedo hacer que una biblioteca de decodificación se cargue y se use para la reproducción? también puede ser útil.

¿Cómo puedo hacer que una biblioteca de decodificación se cargue y se utilice para la reproducción?

  • La mayoría de las bibliotecas de decodificador tienen pasos manuales para revisar y compilar las dependencias, así que asegúrate de haber seguido los pasos del archivo README para la biblioteca relevante. Por ejemplo, para la biblioteca FFmpeg de ExoPlayer, es necesario seguir las instrucciones en bibliotecas/decoder_ffmpeg/README.md, incluido pasar marcas de configuración para habilitar decodificadores en cualquier formato que desees reproducir.
  • Para las bibliotecas que tienen código nativo, asegúrate de usar la versión correcta del NDK de Android, como se especifica en el archivo README, y presta atención a cualquier error que aparezca durante la configuración y la compilación. Deberías ver que los archivos .so aparecen en el subdirectorio libs de la ruta de acceso de la biblioteca para cada arquitectura compatible después de seguir los pasos del archivo README.
  • Para probar la reproducción con la biblioteca de la aplicación de demostración, consulta Cómo habilitar los decodificadores agrupados. Consulta el archivo README de la biblioteca para obtener instrucciones sobre cómo usarla desde tu propia app.
  • Si usas DefaultRenderersFactory, deberías ver una línea de registro de nivel de información como "Loaded FfmpegAudioRenderer" en Logcat cuando se cargue el decodificador. Si falta, asegúrate de que la aplicación dependa de la biblioteca de decodificación.
  • Si ves registros de nivel de advertencia de LibraryLoader en Logcat, significa que falló la carga del componente nativo de la biblioteca. Si esto sucede, verifica que hayas seguido los pasos del archivo README de la biblioteca de forma correcta y que no se hayan producido errores mientras sigues las instrucciones.

Si aún tienes problemas para usar las bibliotecas de decodificación, consulta la herramienta de seguimiento de errores de Media3 para ver si hay algún problema reciente relevante. Si necesitas informar un problema nuevo y está relacionado con la compilación de la parte nativa de la biblioteca, incluye el resultado completo de la línea de comandos de la ejecución de instrucciones README para ayudarnos a diagnosticar el problema.

¿Puedo reproducir videos de YouTube directamente con ExoPlayer?

No, ExoPlayer no puede reproducir videos de YouTube, como URLs con el formato https://www.youtube.com/watch?v=.... En su lugar, debes usar la API del reproductor IFrame de YouTube, que es la forma oficial de reproducir videos de YouTube en Android.

La reproducción de video se entrecorta.

Es posible que el dispositivo no pueda decodificar el contenido lo suficientemente rápido si, por ejemplo, la tasa de bits o la resolución del contenido superan las capacidades del dispositivo. Es posible que debas usar contenido de menor calidad para obtener un buen rendimiento en esos dispositivos.

Si experimentas un video entrecortado en un dispositivo que ejecuta una versión de Android desde Android 6.0 (nivel de API 23) hasta Android 11 (nivel de API 30 inclusive), especialmente cuando se reproduce contenido protegido por DRM o con velocidad de fotogramas alta, puedes intentar habilitar la cola de búfer asíncrona.