- Cómo corregir los errores "No se permite el tráfico HTTP de texto simple"
- Cómo corregir los errores "SSLHandshakeException", "CertPathValidatorException" y "ERR_CERT_AUTHORITY_INVALID"
- ¿Por qué no se puede buscar en algunos archivos multimedia?
- ¿Por qué la búsqueda es imprecisa en algunos archivos MP3?
- ¿Por qué la búsqueda en mi video es lenta?
- ¿Por qué no se reproducen algunos archivos MPEG-TS?
- ¿Por qué no se encuentran subtítulos en algunos archivos MPEG-TS?
- ¿Por qué algunos archivos MP4/FMP4 se reproducen de forma incorrecta?
- ¿Por qué algunas transmisiones fallan con el código de respuesta HTTP 301 o 302?
- ¿Por qué algunas transmisiones fallan con UnrecognizedInputFormatException?
- ¿Por qué setPlaybackParameters no funciona correctamente en algunos dispositivos?
- ¿Qué significan los errores "Se accedió al reproductor en el subproceso incorrecto"?
- ¿Cómo puedo corregir el error "Unexpected status line: ICY 200 OK"?
- ¿Cómo puedo consultar si la transmisión que se está reproduciendo es una transmisión en vivo?
- ¿Cómo puedo mantener la reproducción de audio cuando mi app está en segundo plano?
- ¿Por qué ExoPlayer admite mi contenido, pero la biblioteca de Cast de ExoPlayer no?
- ¿Por qué no se reproduce el contenido, pero no aparece ningún error?
- ¿Cómo puedo hacer que se cargue una biblioteca de decodificación y se use para la reproducción?
- ¿Puedo reproducir videos de YouTube directamente con ExoPlayer?
- La reproducción de video se entrecorta
- Errores de lint de la API inestable
- ¿Cómo puedo probar o aislar los problemas que causan las optimizaciones o funciones nuevas?
Cómo corregir los errores "No se permite el tráfico HTTP de texto simple"
Este error se producirá si tu app solicita tráfico HTTP de texto simple (es decir,
http:// en lugar de https://) cuando su configuración de seguridad de redes no
lo permite. Si tu app se orienta a Android 9 (nivel de API 28) o versiones posteriores, el tráfico HTTP de texto simple se inhabilita con la configuración predeterminada.
Si tu app necesita trabajar con tráfico HTTP de texto simple, debes usar una configuración de seguridad de redes que lo permita. Para obtener más detalles, consulta la documentación de seguridad de redes de Android. Para habilitar todo el tráfico HTTP de texto simple, puedes agregar
android:usesCleartextTraffic="true" al elemento application del archivo
AndroidManifest.xml de tu app.
La app de demo de ExoPlayer usa la configuración de seguridad de redes predeterminada, por lo que no permite el tráfico HTTP de texto simple. Puedes habilitarla con las instrucciones anteriores.
Cómo corregir 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 puede buscar en algunos archivos multimedia?
De forma predeterminada, ExoPlayer no admite la búsqueda en contenido multimedia en el que el único método para realizar operaciones de búsqueda precisas es que el reproductor analice e indexe todo el archivo. ExoPlayer considera que esos archivos no se pueden buscar. La mayoría de los formatos de contenedor de contenido multimedia modernos incluyen metadatos para la 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 y permite realizar operaciones de búsqueda eficientes.
Si necesitas buscar, pero tienes contenido multimedia que no se puede buscar, te sugerimos que conviertas tu contenido para usar un formato de contenedor más apropiado. En el caso de los archivos MP3, ADTS y AMR, también puedes habilitar la búsqueda suponiendo que los archivos tienen una tasa de bits constante, como se describe aquí.
¿Por qué la búsqueda es imprecisa en algunos archivos MP3?
Los archivos MP3 con tasa de bits variable (VBR) no son adecuados para casos de uso que requieren una búsqueda exacta. Esto se debe a dos motivos:
- Para la búsqueda exacta, lo ideal es que un formato de contenedor proporcione una asignación precisa de tiempo a byte en un encabezado. Esta asignación permite que un reproductor 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) suelen ser imprecisos.
- En el caso de los formatos de contenedor que no proporcionan una asignación precisa de tiempo a bytes (o ninguna asignación de tiempo a bytes), aún 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 reproductor puede asignar el tiempo de búsqueda a una 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 eficaz una búsqueda binaria guiada en el contenido multimedia hasta que encuentre la muestra correcta. Lamentablemente, el formato 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 MP3 con VBR es analizar 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 establecer en un DefaultExtractorsFactory con
setMp3ExtractorFlags. Ten en cuenta que no se escala bien a archivos MP3 grandes, en especial si el usuario intenta buscar cerca del final de la transmisión poco después de iniciar la reproducción, lo que requiere que el reproductor espere hasta que se descargue y se indexe toda la transmisión antes de realizar la búsqueda. En ExoPlayer, decidimos optimizar la velocidad por sobre la exactitud en este caso y, por lo tanto, FLAG_ENABLE_INDEX_SEEKING está inhabilitado de forma predeterminada.
Si controlas el contenido multimedia que estás reproduciendo, te recomendamos que uses un formato de contenedor más apropiado, como MP4. No conocemos ningún caso de uso en el que MP3 sea la mejor opción de formato multimedia.
¿Por qué la búsqueda en mi video es lenta?
Cuando el reproductor busca una nueva posición de reproducción en un video, debe hacer dos cosas:
- Carga los datos correspondientes a la nueva posición de reproducción en el búfer (es posible que esto no sea necesario si estos datos ya están almacenados en el búfer).
- 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 intra-frame que usan la mayoría de los formatos de compresión de video. Para garantizar que la búsqueda sea precisa (es decir, que la reproducción comience 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 introduce (1) se puede mitigar aumentando la cantidad de datos almacenados en el búfer de datos de memoria por el reproductor o almacenando previamente en caché los datos en el disco.
La latencia que introduce (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 dará como resultado un archivo de salida más grande).
¿Por qué no se reproducen algunos archivos MPEG-TS?
Algunos archivos MPEG-TS no contienen delimitadores de unidades de acceso (AUD). De forma predeterminada, ExoPlayer se basa en los AUD para detectar los límites de los fotogramas de forma económica. Del mismo modo, algunos archivos MPEG-TS no contienen fotogramas clave IDR. De forma predeterminada, estos son los únicos tipos de fotogramas clave que considera ExoPlayer.
ExoPlayer parecerá estar bloqueado en el estado de almacenamiento en búfer cuando se le solicite que reproduzca un archivo MPEG-TS que no tenga AUD ni fotogramas clave IDR. Si necesitas reproducir esos archivos,
puedes hacerlo con FLAG_DETECT_ACCESS_UNITS y
FLAG_ALLOW_NON_IDR_KEYFRAMES, respectivamente. Estas marcas se pueden establecer en un
DefaultExtractorsFactory con setTsExtractorFlags o en un
DefaultHlsExtractorFactory con el
constructor.
El uso de FLAG_DETECT_ACCESS_UNITS no tiene efectos secundarios, excepto que es costoso desde el punto de vista computacional en relación con la detección de límites de fotogramas basada en AUD. El uso de FLAG_ALLOW_NON_IDR_KEYFRAMES puede provocar daños visuales temporales al comienzo de la reproducción y, de inmediato, 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. Puedes especificar manualmente cualquier pista de subtítulos proporcionando una lista de los formatos de subtítulos esperados al DefaultExtractorsFactory, incluidos los canales de accesibilidad que se pueden usar para identificarlos en la transmisión de 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 o FMP4 se reproducen de forma incorrecta?
Algunos archivos MP4/FMP4 contienen listas de edición que reescriben la línea de tiempo de contenido multimedia omitiendo, moviendo o repitiendo listas de muestras. ExoPlayer tiene compatibilidad parcial para aplicar 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 el contenido multimedia de anuncios previos al video para las ediciones que no comienzan en una muestra de sincronización.
Si ves que falta parte del contenido multimedia o se repite de forma inesperada, intenta configurar Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS o FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS, lo que hará que el extractor ignore las listas de edición por completo. Estos se pueden establecer 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, normalmente sigue el redireccionamiento y comienza la reproducción de forma habitual. El único caso en el que esto no sucede de forma predeterminada es para los redireccionamientos entre protocolos. Un redireccionamiento entre protocolos es aquel que redirecciona de HTTPS a HTTP o viceversa (o, con menos frecuencia, entre otro par de protocolos). Puedes probar si una URL causa un redireccionamiento entre protocolos con la herramienta de línea de comandos wget de la siguiente manera:
wget "https://yourserver.example.com/test.mp3" 2>&1 | grep Location
El resultado debería ser similar a este:
Location: https://secondserver.example.net/test.mp3 [following]
Location: http://thirdserver.example.org/test.mp3 [following]
En este ejemplo, hay dos redireccionamientos. El primer redireccionamiento es de
https://yourserver.example.com/test.mp3 a
https://secondserver.example.net/test.mp3. Ambas son HTTPS, por lo que no se trata de
un redireccionamiento entre protocolos. El segundo redireccionamiento es de
https://secondserver.example.net/test.mp3 a
http://thirdserver.example.org/test.mp3. Esto redirecciona de HTTPS a HTTP y,
por lo tanto, es 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 los redireccionamientos entre protocolos cuando crees instancias de DefaultHttpDataSource.Factory que se usen en tu aplicación. Obtén información para seleccionar y configurar la pila de red
aquí.
¿Por qué algunas transmisiones fallan con UnrecognizedInputFormatException?
Esta pregunta se relaciona con las fallas de reproducción de la siguiente forma:
UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.
Existen 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 esas transmisiones, debes depender del módulo de ExoPlayer correspondiente. En los casos en que el URI de transmisión no termine 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 de contenedor del contenido multimedia que intentas reproducir. En este caso, la falla funciona según lo previsto. Sin embargo, puedes enviar una solicitud de función a nuestra herramienta de seguimiento de errores, incluidos los detalles del formato del contenedor y una transmisión de prueba. Busca una solicitud de función existente antes de enviar una nueva.
¿Por qué 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 irregular, artefactos audibles y un uso elevado de la CPU cuando uses 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 "Se accedió al reproductor en el subproceso incorrecto"?
Consulta Nota sobre los subprocesos en la página de introducción.
¿Cómo puedo corregir el error "Unexpected status line: ICY 200 OK"?
Este problema puede ocurrir si la respuesta del servidor incluye una línea de estado ICY, en lugar de una que cumpla con HTTP. Las líneas de estado de ICY están obsoletas y no deben usarse, por lo que, si controlas el servidor, debes actualizarlo para que proporcione una respuesta compatible con HTTP. Si no puedes hacerlo, usa la biblioteca de OkHttp de ExoPlayer para resolver el problema, ya que puede controlar las líneas de estado de ICY correctamente.
¿Cómo puedo consultar si la transmisión que se está reproduciendo es una transmisión en vivo?
Puedes consultar el método isCurrentWindowLive del reproductor. Además, puedes
verificar isCurrentWindowDynamic para saber si la ventana es dinámica
(es decir, si se sigue actualizando con el tiempo).
¿Cómo mantengo la reproducción de audio cuando mi app está en segundo plano?
Sigue estos pasos para garantizar la reproducción continua de audio cuando la app se ejecuta en segundo plano:
- Debes tener un servicio en primer plano en ejecución. Esto evita que el sistema finalice tu proceso para liberar recursos.
- Debes tener un
WifiLocky unWakeLock. Esto garantiza que el sistema mantenga activos la radio Wi-Fi y la CPU. Esto se puede hacer fácilmente si usasExoPlayerllamando asetWakeMode, 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 el audio.
¿Por qué ExoPlayer admite mi contenido, pero la biblioteca de Cast de ExoPlayer no?
Es posible que el contenido que intentas reproducir no tenga CORS habilitado. El framework de Cast requiere que el contenido tenga habilitado el CORS para poder reproducirlo.
¿Por qué no se reproduce el contenido, pero no se muestra ningún error?
Es posible que el dispositivo en el que estás reproduciendo el contenido no admita un formato de muestra de contenido multimedia específico. Esto se puede confirmar fácilmente agregando un EventLogger como objeto de escucha a tu reproductor y buscando 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 el mimeType. Consulta la documentación de formatos de contenido multimedia de Android para obtener información sobre los formatos de muestra compatibles. ¿Cómo puedo hacer que se cargue una biblioteca de decodificación y se use para la reproducción? también puede ser útil.
¿Cómo puedo hacer que se cargue una biblioteca de decodificación y se use para la reproducción?
- La mayoría de las bibliotecas de decodificadores tienen pasos manuales para revisar y compilar las dependencias, así que asegúrate de haber seguido los pasos del archivo README de la biblioteca correspondiente. Por ejemplo, para la biblioteca de FFmpeg de ExoPlayer, es necesario seguir las instrucciones que se indican en libraries/decoder_ffmpeg/README.md, lo que incluye pasar marcas de configuración para habilitar decodificadores para cualquier formato que quieras reproducir.
- En el caso de 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 los errores que aparezcan durante la configuración y la compilación. Deberías ver que aparecen archivos
.soen el subdirectoriolibsde 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 en la aplicación de demostración, consulta Cómo habilitar decodificadores empaquetados. 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 tenga una dependencia en la biblioteca de decodificación. - Si ves registros de nivel de advertencia de
LibraryLoaderen Logcat, significa que no se pudo cargar el componente nativo de la biblioteca. Si esto sucede, verifica que hayas seguido correctamente los pasos del archivo README de la biblioteca y que no se hayan producido errores mientras seguías las instrucciones.
Si sigues teniendo problemas para usar las bibliotecas de decodificación, consulta la herramienta de seguimiento de errores de Media3 para ver si hay problemas recientes pertinentes. Si necesitas informar un problema nuevo relacionado con la compilación de la parte nativa de la biblioteca, incluye el resultado completo de la línea de comandos que se obtiene cuando se ejecutan las instrucciones del archivo README para ayudarnos a diagnosticar el problema.
¿Puedo reproducir videos de YouTube directamente con ExoPlayer?
No, ExoPlayer no puede reproducir videos de YouTube, como las URLs con el formato https://www.youtube.com/watch?v=.... En su lugar, debes usar la API de iframe Player 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 con la rapidez suficiente 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 interrupciones de video 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, en especial cuando reproduces contenido protegido por DRM o con una alta velocidad de fotogramas, puedes intentar habilitar la puesta en cola asíncrona del búfer.
Errores de lint de la API inestable
Media3 garantiza la compatibilidad binaria para un subconjunto de la plataforma de la API. Las partes que no garantizan la compatibilidad binaria se marcan con @UnstableApi. Para que esta distinción sea clara, los usos de símbolos de API inestables generan un error de lint, a menos que se anoten con @OptIn.
La anotación @UnstableApi no implica nada sobre la calidad o el rendimiento de una API, solo el hecho de que no está "congelada".
Tienes dos opciones para controlar los errores de lint de la API inestable:
- Cambia a una API estable que logre el mismo resultado.
- Sigue usando la API inestable y anota el uso con
@OptIn, como se muestra más adelante.
Agrega la anotación @OptIn
Android Studio puede ayudarte a agregar la anotación:
También puedes anotar de forma manual sitios de uso específicos:
Kotlin
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
@OptIn(UnstableApi::class)
fun functionUsingUnstableApi() { ... }
Java
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
@OptIn(markerClass = UnstableApi.class)
private void methodUsingUnstableApis() { ... }
Se pueden habilitar paquetes completos agregando un archivo package-info:
Kotlin
// In your package-info.kt
@OptIn(UnstableApi::class)
package name.of.your.package
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
Java
// In your package-info.java
@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
Se pueden habilitar proyectos completos suprimiendo el error de lint específico en su
archivo lint.xml:
<?xml version="1.0" encoding="utf-8"?>
<lint>
<issue id="UnsafeOptInUsageError">
<option name="opt-in" value="androidx.media3.common.util.UnstableApi" />
</issue>
</lint>
También hay una anotación kotlin.OptIn que no se debe usar. Es importante usar la anotación androidx.annotation.OptIn.
¿Cómo puedo probar o aislar los problemas causados por las optimizaciones o funciones nuevas?
Media3 incluye una infraestructura de marcas de funciones en la que las funciones y optimizaciones nuevas se habilitan de forma predeterminada en el modo Canary.
Si sospechas que un problema o una regresión en tu app se relaciona con una función o una optimización nuevas, puedes inhabilitar temporalmente el modo Canary:
Flags.setCanaryModeEnabled(false);
También puedes inhabilitar marcas de funciones específicas de forma individual con
Flags.disableFlag(flagId). Para obtener más detalles sobre cómo configurar el modo Canary,
anular marcas y configurar interruptores de apagado remoto, consulta la
guía de marcas de funciones y modo Canary.