- Cómo corregir errores de "No se permite el tráfico HTTP de texto sin formato"
- Cómo corregir los errores "SSLHandshakeException", "CertPathValidatorException" y "ERR_CERT_AUTHORITY_INVALID"
- ¿Por qué no se pueden buscar 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 pueden reproducir 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é fallan algunas transmisiones 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 de "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 el contenido que se reproduce es una transmisión en vivo?
- ¿Cómo puedo mantener la reproducción de audio cuando mi app se ejecuta en segundo plano?
- ¿Por qué ExoPlayer admite mi contenido, pero la biblioteca de ExoPlayer Cast no?
- ¿Por qué no se reproduce el contenido, pero no aparece ningún error?
- ¿Cómo puedo obtener una biblioteca de decodificación para cargarla y usarla en la reproducción?
- ¿Puedo reproducir videos de YouTube directamente con ExoPlayer?
- La reproducción de video se interrumpe
- Errores de lint de la API inestables
Cómo corregir errores de "Cleartext HTTP traffic not permitted"
Este error se producirá si tu app solicita tráfico HTTP de texto no cifrado (es decir, http://
en lugar de https://
) cuando su configuración de seguridad de red no lo permite. Si tu app se segmenta para 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 no cifrado, 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 habilitarlo siguiendo 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 pueden buscar 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 estos archivos no se pueden buscar. La mayoría de los formatos de contenedores de medios modernos incluyen metadatos para la búsqueda (como un índice de muestras), 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 operaciones de búsqueda eficientes.
Si necesitas buscar contenido multimedia, pero este no se puede buscar, te sugerimos que conviertas tu contenido para usar un formato de contenedor más adecuado. En el caso de los archivos MP3, ADTS y AMR, también puedes habilitar la búsqueda bajo la suposición de 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 los 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 suposición del desplazamiento de bytes correspondiente, comenzar a solicitar contenido multimedia desde ese desplazamiento, analizar la primera marca de tiempo absoluta de la muestra y, de hecho, realizar una búsqueda binaria guiada en el contenido multimedia hasta que encuentre la muestra correcta. Lamentablemente, MP3 no incluye marcas de tiempo de muestras 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 de 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 configurar en un DefaultExtractorsFactory
con setMp3ExtractorFlags
. Ten en cuenta que no se adapta bien a los 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 en lugar de la precisión en este caso, por lo que 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 ningún caso de uso en el que el formato de medios MP3 sea la mejor opción.
¿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 en el búfer los datos correspondientes a la nueva posición de reproducción (esto puede no ser necesario si estos datos ya están en el búfer).
- Vacía el decodificador de video y comienza a decodificar desde el I-frame (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), se deben decodificar y descartar de inmediato todos los fotogramas entre el I-frame anterior y la posición de búsqueda (sin mostrarlos en la pantalla).
La latencia que introduce (1) se puede mitigar aumentando la cantidad de datos almacenados en búfer en la memoria del reproductor o almacenando previamente 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 más fotogramas I frecuentes (lo que generará un archivo de salida más grande).
¿Por qué no se pueden reproducir algunos archivos MPEG-TS?
Algunos archivos MPEG-TS no contienen delimitadores de unidades de acceso (AUD). De forma predeterminada, ExoPlayer se basa en las 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 atascado en el estado de almacenamiento en búfer cuando se le solicite reproducir un archivo MPEG-TS que no tenga AUD ni IDR keyframes. Si necesitas reproducir este tipo de archivos, puedes hacerlo con FLAG_DETECT_ACCESS_UNITS
y FLAG_ALLOW_NON_IDR_KEYFRAMES
, respectivamente. Estas marcas se pueden establecer en un objeto DefaultExtractorsFactory
con setTsExtractorFlags
o en un objeto DefaultHlsExtractorFactory
con el constructor.
El uso de FLAG_DETECT_ACCESS_UNITS
no tiene efectos secundarios más allá de ser costoso en términos de procesamiento en comparación con la detección de límites de fotogramas basada en AUD. El uso de FLAG_ALLOW_NON_IDR_KEYFRAMES
puede provocar una corrupción visual temporal al inicio 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 a DefaultExtractorsFactory
, incluidos los canales de accesibilidad que se pueden usar para identificarlos en el flujo 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/FMP4 se reproducen de forma incorrecta?
Algunos archivos MP4/FMP4 contienen listas de edición que reescriben la línea de tiempo de los medios omitiendo, moviendo o repitiendo listas de muestras. ExoPlayer admite parcialmente la aplicación de listas de edición. Por ejemplo, puede retrasar o repetir grupos de muestras a partir de una muestra de sincronización, pero no trunca muestras de audio ni adelanta medios para ediciones que no comienzan en una muestra de sincronización.
Si ves que falta o se repite inesperadamente parte del contenido multimedia, intenta 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 establecer en un DefaultExtractorsFactory
con setMp4ExtractorFlags
o setFragmentedMp4ExtractorFlags
.
¿Por qué algunos streams fallan con el código de respuesta HTTP 301 o 302?
Los códigos de respuesta HTTP 301 y 302 indican redireccionamiento. En Wikipedia, puedes encontrar descripciones breves. Cuando ExoPlayer realiza una solicitud y recibe una respuesta con el código de estado 301 o 302, normalmente seguirá el redireccionamiento y comenzará la reproducción con normalidad. El único caso en el que esto no sucede de forma predeterminada es en 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, por lo que es un redireccionamiento entre protocolos. ExoPlayer no seguirá este redireccionamiento en su configuración predeterminada, lo que significa que fallará la reproducción.
Si es necesario, puedes configurar ExoPlayer para que siga los redireccionamientos entre protocolos cuando se creen instancias de DefaultHttpDataSource.Factory
que se usan en tu aplicación. Obtén más 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 del siguiente tipo:
UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.
Este error puede deberse a dos motivos: La causa más común es que intentas reproducir contenido de DASH (mpd), HLS (m3u8) o SmoothStreaming (ism, isml), pero el reproductor intenta reproducirlo como una transmisión progresiva. Para reproducir estos flujos, debes depender del módulo de ExoPlayer correspondiente. En los casos en los que el URI de la 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 del contenedor del contenido multimedia que intentas reproducir. En este caso, el error funciona según lo previsto. Sin embargo, puedes enviar una solicitud de función a nuestro seguimiento de problemas, 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 ejecutes una compilación de depuración de tu app en Android M y versiones anteriores, es posible que experimentes un rendimiento inestable, 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 de "Se accedió al reproductor en el subproceso incorrecto"?
Consulta Una nota sobre el subprocesamiento 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 ICY están obsoletas y no se deben usar, por lo que, si controlas el servidor, debes actualizarlo para que proporcione una respuesta compatible con HTTP. Si no puedes hacerlo, usar la biblioteca de ExoPlayer OkHttp resolverá el problema, ya que puede controlar las líneas de estado ICY correctamente.
¿Cómo puedo consultar si el contenido que se reproduce es una transmisión en vivo?
Puedes consultar el método isCurrentWindowLive
del reproductor. Además, puedes consultar isCurrentWindowDynamic
para saber si la ventana es dinámica (es decir, si se sigue actualizando con el tiempo).
¿Cómo puedo mantener la reproducción de audio cuando mi app se ejecuta en segundo plano?
Sigue estos pasos para garantizar la reproducción continua de audio cuando tu app se ejecute 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
WifiLock
y unWakeLock
. Esto garantiza que el sistema mantenga activas la radio Wi-Fi y la CPU. Esto se puede hacer fácilmente si se usaExoPlayer
llamando 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 tan pronto como deje de reproducirse el audio.
¿Por qué ExoPlayer admite mi contenido, pero la biblioteca de ExoPlayer Cast 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 para poder reproducirlo.
¿Por qué no se reproduce el contenido, pero no aparece ningún error?
Es posible que el dispositivo en el que reproduces el contenido no admita un formato específico de muestra de medios. Puedes confirmar esto fácilmente agregando un EventLogger
como un 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 medios especificado por mimeType
. Consulta la documentación sobre los formatos de medios de Android para obtener información sobre los formatos de muestras compatibles. También puede ser útil How can I get a decoding library to load and be used for playback?.
¿Cómo puedo obtener una biblioteca de decodificación para cargarla y usarla en la reproducción?
- La mayoría de las bibliotecas de decodificación tienen pasos manuales para extraer y compilar las dependencias, así que asegúrate de haber seguido los pasos del archivo README de la biblioteca pertinente. Por ejemplo, para la biblioteca de FFmpeg de ExoPlayer, es necesario seguir las instrucciones en libraries/decoder_ffmpeg/README.md, lo que incluye pasar marcas de configuración para habilitar decodificadores para cualquier formato que desees 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 archivos
.so
en el subdirectoriolibs
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 en la aplicación de demostración, consulta cómo habilitar los decodificadores incluidos. 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
LibraryLoader
en Logcat, esto indica que no se pudo cargar el componente nativo de la biblioteca. Si esto sucede, verifica que hayas seguido los pasos del README de la biblioteca correctamente y que no se hayan generado 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 relevantes. Si necesitas registrar un problema nuevo y se relaciona con la compilación de la parte nativa de la biblioteca, incluye el resultado completo de la línea de comandos de las instrucciones del 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 interrumpe
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 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 cola de búfer asíncrona.
Errores de lint de la API inestables
Media3 garantiza la compatibilidad binaria para un subconjunto de la superficie de la API. Las partes que no garantizan la compatibilidad binaria están marcadas 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 manualmente sitios de uso específicos en Kotlin:
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
@OptIn(UnstableApi::class)
fun functionUsingUnstableApi() { ... }
Y también en Java:
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
@OptIn(markerClass = UnstableApi.class)
private void methodUsingUnstableApis() { ... }
Para habilitar paquetes completos, agrega un archivo package-info.java
:
@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
Para habilitar proyectos completos, suprime 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
.