- Como corrigir erros "Tráfego HTTP de texto não criptografado não permitido"
- Como corrigir erros "SSLHandshakeException", "CertPathValidatorException" e "ERR_CERT_AUTHORITY_INVALID"
- Por que alguns arquivos de mídia não podem ser buscados?
- Por que a busca é imprecisa em alguns arquivos MP3?
- Por que a busca no meu vídeo é lenta?
- Por que alguns arquivos MPEG-TS não são reproduzidos?
- Por que as legendas não são encontradas em alguns arquivos MPEG-TS?
- Por que alguns arquivos MP4/FMP4 são reproduzidos incorretamente?
- Por que alguns streams falham com o código de resposta HTTP 301 ou 302?
- Por que alguns streams falham com UnrecognizedInputFormatException?
- Por que setPlaybackParameters não funciona corretamente em alguns dispositivos?
- O que significam os erros "O player é acessado na linha de execução errada"?
- Como posso corrigir "Linha de status inesperada: ICY 200 OK"?
- Como posso consultar se o stream que está sendo reproduzido é um stream ao vivo?
- Como faço para manter o áudio sendo reproduzido quando meu app está em segundo plano?
- Por que o ExoPlayer oferece suporte ao meu conteúdo, mas a biblioteca ExoPlayer Cast não?
- Por que o conteúdo não é reproduzido, mas nenhum erro é exibido?
- Como posso fazer com que uma biblioteca de decodificação seja carregada e usada para reprodução?
- Posso reproduzir vídeos do YouTube diretamente com o ExoPlayer?
- A reprodução de vídeo está instável
- Erros de lint de API instável
Como corrigir erros "Tráfego HTTP de texto não criptografado não permitido"
Esse erro ocorre se o app solicitar tráfego HTTP de texto não criptografado (ou seja, http:// em vez de https://) quando a configuração de segurança de rede não permitir. Se o app for direcionado ao Android 9 (nível 28 da API) ou mais recente, o tráfego HTTP de texto não criptografado será desativado pela configuração padrão.
Se o app precisar funcionar com tráfego HTTP de texto não criptografado, use uma configuração de segurança de rede que permita isso. Consulte a documentação de segurança de rede do Android
para mais detalhes. Para ativar todo o tráfego HTTP de texto não criptografado, basta adicionar
android:usesCleartextTraffic="true" ao elemento application do
AndroidManifest.xml do app.
O app de demonstração do ExoPlayer usa a configuração de segurança de rede padrão e, portanto, não permite tráfego HTTP de texto não criptografado. Você pode ativá-lo usando as instruções acima.
Como corrigir erros "SSLHandshakeException", "CertPathValidatorException" e "ERR_CERT_AUTHORITY_INVALID"
SSLHandshakeException, CertPathValidatorException e ERR_CERT_AUTHORITY_INVALID indicam um problema com o certificado SSL do servidor. Esses erros não são específicos do ExoPlayer. Consulte
a documentação SSL do Android
para mais detalhes.
Por que alguns arquivos de mídia não podem ser buscados?
Por padrão, o ExoPlayer não oferece suporte à busca em mídias em que o único método para realizar operações de busca precisas é o player verificar e indexar o arquivo inteiro. O ExoPlayer considera esses arquivos como não buscáveis. A maioria dos formatos de contêiner de mídia modernos inclui metadados para busca (como um índice de amostra), tem um algoritmo de busca bem definido (por exemplo, pesquisa de bisseção interpolada para Ogg) ou indica que o conteúdo é de taxa de bits constante. Operações de busca eficientes são possíveis e compatíveis com o ExoPlayer nesses casos.
Se você precisar de busca, mas tiver mídia não buscável, sugerimos converter o conteúdo para usar um formato de contêiner mais adequado. Para arquivos MP3, ADTS e AMR, também é possível ativar a busca supondo que os arquivos tenham uma taxa de bits constante, conforme descrito aqui.
Por que a busca é imprecisa em alguns arquivos MP3?
Arquivos MP3 de taxa de bits variável (VBR) são fundamentalmente inadequados para casos de uso que exigem busca exata. Há duas razões para isso:
- Para uma busca exata, um formato de contêiner precisa fornecer um mapeamento preciso de tempo para byte em um cabeçalho. Esse mapeamento permite que um player mapeie um tempo de busca solicitado para o deslocamento de byte correspondente e comece a solicitar, analisar e reproduzir mídia desse deslocamento. Os cabeçalhos disponíveis para especificar esse mapeamento em MP3 (como cabeçalhos XING) são, infelizmente, muitas vezes imprecisos.
- Para formatos de contêiner que não fornecem um mapeamento preciso de tempo para byte (ou qualquer mapeamento de tempo para byte), ainda é possível realizar uma busca exata se o contêiner incluir carimbos de data/hora de amostra absolutos no stream. Nesse caso, um player pode mapear o tempo de busca para uma melhor estimativa do deslocamento de byte correspondente, começar a solicitar mídia desse deslocamento, analisar o primeiro carimbo de data/hora de amostra absoluto e realizar uma pesquisa binária guiada na mídia até encontrar a amostra certa. Infelizmente, o MP3 não inclui carimbos de data/hora de amostra absolutos no stream, então essa abordagem não é possível.
Por esses motivos, a única maneira de realizar uma busca exata em um arquivo MP3 VBR é verificar o arquivo inteiro e criar manualmente um mapeamento de tempo para byte no player. Essa estratégia pode ser ativada usando FLAG_ENABLE_INDEX_SEEKING,
que pode ser definida em uma DefaultExtractorsFactory usando
setMp3ExtractorFlags. Observe que ela não é bem escalonada para arquivos MP3 grandes, principalmente se o usuário tentar buscar perto do final do stream logo após iniciar a reprodução, o que exige que o player espere até que todo o stream seja baixado e indexado antes de realizar a busca. No ExoPlayer, decidimos otimizar a velocidade em vez da precisão nesse caso, e
FLAG_ENABLE_INDEX_SEEKING é desativada por padrão.
Se você controla a mídia que está reproduzindo, recomendamos usar um formato de contêiner mais adequado, como MP4. Não conhecemos nenhum caso de uso em que o MP3 seja a melhor opção de formato de mídia.
Por que a busca no meu vídeo é lenta?
Quando o player busca uma nova posição de reprodução em um vídeo, ele precisa fazer duas coisas:
- Carregar os dados correspondentes à nova posição de reprodução no buffer. Isso pode não ser necessário se esses dados já estiverem em buffer.
- Limpar o decodificador de vídeo e começar a decodificar do I-frame (quadro-chave) antes da nova posição de reprodução, devido à codificação intraquadro usada pela maioria dos formatos de compactação de vídeo. Para garantir que a busca seja precisa (ou seja, a reprodução começa exatamente na posição de busca), todos os frames entre o I-frame anterior e a posição de busca precisam ser decodificados e descartados imediatamente (sem serem mostrados na tela).
A latência introduzida por (1) pode ser atenuada aumentando a quantidade de dados armazenados em buffer na memória pelo player ou pré-armazenamento em cache dos dados em disco.
A latência introduzida por (2) pode ser atenuada reduzindo a precisão da busca usando ExoPlayer.setSeekParameters ou recodificando o vídeo para ter I-frames mais frequentes (o que resultará em um arquivo de saída maior).
Por que alguns arquivos MPEG-TS não são reproduzidos?
Alguns arquivos MPEG-TS não contêm delimitadores de unidade de acesso (AUDs). Por padrão, o ExoPlayer depende de AUDs para detectar limites de frames de forma barata. Da mesma forma, alguns arquivos MPEG-TS não contêm quadros-chave IDR. Por padrão, esses são os únicos tipos de quadros-chave considerados pelo ExoPlayer.
O ExoPlayer vai parecer preso no estado de buffer quando solicitado a reproduzir um arquivo MPEG-TS que não tem AUDs ou quadros-chave IDR. Se você precisar reproduzir esses arquivos,
use FLAG_DETECT_ACCESS_UNITS e
FLAG_ALLOW_NON_IDR_KEYFRAMES, respectivamente. Essas flags podem ser definidas em uma
DefaultExtractorsFactory usando setTsExtractorFlags ou em uma
DefaultHlsExtractorFactory usando o
construtor.
O uso de FLAG_DETECT_ACCESS_UNITS não tem efeitos colaterais, além de ser computacionalmente caro em relação à detecção de limite de frames com base em AUD. O uso de FLAG_ALLOW_NON_IDR_KEYFRAMES pode resultar em corrupção visual temporária no início da reprodução e imediatamente após as buscas ao reproduzir alguns arquivos MPEG-TS.
Por que as legendas não são encontradas em alguns arquivos MPEG-TS?
Alguns arquivos MPEG-TS incluem faixas CEA-608, mas não as declaram nos metadados do contêiner. Assim, o ExoPlayer não consegue detectá-las. É possível especificar manualmente as faixas de legenda fornecendo uma lista de formatos de legenda esperados para a DefaultExtractorsFactory, incluindo os canais de acessibilidade que podem ser usados para identificá-las no stream 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 que alguns arquivos MP4/FMP4 são reproduzidos incorretamente?
Alguns arquivos MP4/FMP4 contêm listas de edição que reescrevem a linha do tempo de mídia ignorando, movendo ou repetindo listas de amostras. O ExoPlayer tem suporte parcial para aplicar listas de edição. Por exemplo, ele pode atrasar ou repetir grupos de amostras começando em uma amostra de sincronização, mas não trunca amostras de áudio ou mídia de pré-rolagem para edições que não começam em uma amostra de sincronização.
Se você notar que parte da mídia está faltando ou repetida inesperadamente,
tente definir Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS ou
FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS, o que fará com que
o extrator ignore as listas de edição completamente. Elas podem ser definidas em uma
DefaultExtractorsFactory usando setMp4ExtractorFlags ou
setFragmentedMp4ExtractorFlags.
Por que alguns streams falham com o código de resposta HTTP 301 ou 302?
Os códigos de resposta HTTP 301 e 302 indicam redirecionamento. Breves descrições podem ser encontradas na Wikipédia. Quando o ExoPlayer faz uma solicitação e recebe uma resposta com o código de status 301 ou 302, ele normalmente segue o redirecionamento e inicia a reprodução normalmente. O único caso em que isso não acontece por padrão é para redirecionamentos entre protocolos. Um redirecionamento entre protocolos é aquele que redireciona de HTTPS para HTTP ou vice-versa (ou, menos comumente, entre outro par de protocolos). É possível testar se um URL causa um redirecionamento entre protocolos usando a ferramenta de linha de comando wget da seguinte maneira:
wget "https://yourserver.example.com/test.mp3" 2>&1 | grep Location
A resposta será semelhante a esta:
Location: https://secondserver.example.net/test.mp3 [following]
Location: http://thirdserver.example.org/test.mp3 [following]
Neste exemplo, há dois redirecionamentos. O primeiro redirecionamento é de https://yourserver.example.com/test.mp3 para https://secondserver.example.net/test.mp3. Ambos são HTTPS, então esse não é um redirecionamento entre protocolos. O segundo redirecionamento é de https://secondserver.example.net/test.mp3 para http://thirdserver.example.org/test.mp3. Isso redireciona de HTTPS para HTTP e, portanto, é um redirecionamento entre protocolos. O ExoPlayer não vai seguir esse redirecionamento na configuração padrão, o que significa que a reprodução vai falhar.
Se necessário, você pode configurar o ExoPlayer para seguir redirecionamentos entre protocolos
ao instanciar DefaultHttpDataSource.Factory instâncias usadas no seu
aplicativo. Saiba como selecionar e configurar a pilha de rede
aqui.
Por que alguns streams falham com UnrecognizedInputFormatException?
Essa pergunta se refere a falhas de reprodução do seguinte formato:
UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.
Há duas causas possíveis para essa falha. A causa mais comum é que você está tentando reproduzir conteúdo DASH (mpd), HLS (m3u8) ou SmoothStreaming (ism, isml), mas o player tenta reproduzi-lo como um stream progressivo. Para reproduzir esses
streams, é necessário depender do módulo ExoPlayer respectivo. Nos casos em que o URI do stream não termina com a extensão de arquivo padrão, também é possível transmitir MimeTypes.APPLICATION_MPD, MimeTypes.APPLICATION_M3U8 ou MimeTypes.APPLICATION_SS para setMimeType de MediaItem.Builder para especificar explicitamente o tipo de stream.
A segunda causa, menos comum, é que o ExoPlayer não oferece suporte ao formato de contêiner da mídia que você está tentando reproduzir. Nesse caso, a falha está funcionando conforme o esperado. No entanto, envie uma solicitação de recurso ao nosso rastreador de problemas, incluindo detalhes do formato do contêiner e um stream de teste. Pesquise uma solicitação de recurso existente antes de enviar uma nova.
Por que setPlaybackParameters não funciona corretamente em alguns dispositivos?
Ao executar um build de depuração do app no Android M e versões anteriores, você pode
ter desempenho instável, artefatos audíveis e alta utilização da CPU ao
usar a API setPlaybackParameters. Isso ocorre porque uma otimização importante para essa API está desativada para builds de depuração executados nessas versões do Android.
É importante observar que esse problema afeta apenas builds de depuração. Ele não afeta builds de lançamento, para os quais a otimização está sempre ativada. Portanto, as versões que você fornece aos usuários finais não devem ser afetadas por esse problema.
O que significam os erros "O player é acessado na linha de execução errada"?
Consulte Uma observação sobre linhas de execução na página de introdução.
Como posso corrigir "Linha de status inesperada: ICY 200 OK"?
Esse problema pode ocorrer se a resposta do servidor incluir uma linha de status ICY, em vez de uma compatível com HTTP. As linhas de status ICY estão obsoletas e não devem ser usadas. Portanto, se você controla o servidor, atualize-o para fornecer uma resposta compatível com HTTP. Se você não conseguir fazer isso, o uso da biblioteca ExoPlayer OkHttp vai resolver o problema, já que ela consegue processar linhas de status ICY corretamente.
Como posso consultar se o stream que está sendo reproduzido é um stream ao vivo?
Você pode consultar o método isCurrentWindowLive do player. Além disso, é possível
verificar isCurrentWindowDynamic para saber se a janela é dinâmica
(ou seja, ainda está sendo atualizada ao longo do tempo).
Como faço para manter o áudio sendo reproduzido quando meu app está em segundo plano?
Siga estas etapas para garantir a reprodução contínua de áudio quando o app estiver em segundo plano:
- É necessário ter um serviço em primeiro plano em execução. Isso impede que o sistema encerre o processo para liberar recursos.
- É necessário manter um
WifiLocke umWakeLock. Eles garantem que o sistema mantenha o rádio Wi-Fi e a CPU ativos. Isso pode ser feito facilmente se você usarExoPlayerchamandosetWakeMode, que vai adquirir e liberar automaticamente os bloqueios necessários nos momentos corretos.
É importante liberar os bloqueios (se não estiver usando setWakeMode) e interromper o serviço assim que o áudio não estiver mais sendo reproduzido.
Por que o ExoPlayer oferece suporte ao meu conteúdo, mas a biblioteca ExoPlayer Cast não?
É possível que o conteúdo que você está tentando reproduzir não esteja ativado para CORS. O framework Cast exige que o conteúdo seja ativado para CORS para ser reproduzido.
Por que o conteúdo não é reproduzido, mas nenhum erro é exibido?
É possível que o dispositivo em que você está reproduzindo o conteúdo não ofereça suporte a um formato de amostra de mídia específico. Isso pode ser facilmente confirmado adicionando
um EventLogger como listener ao player e procurando uma linha
semelhante a esta no Logcat:
[ ] Track:x, id=x, mimeType=mime/type, ... , supported=NO_UNSUPPORTED_TYPE
NO_UNSUPPORTED_TYPE significa que o dispositivo não consegue decodificar o formato de amostra de mídia especificado pelo mimeType. Consulte a documentação
de formatos de mídia do Android para informações sobre formatos de amostra compatíveis. Como posso fazer com que
uma biblioteca de decodificação seja carregada e usada para reprodução? também pode ser útil.
Como posso fazer com que uma biblioteca de decodificação seja carregada e usada para reprodução?
- A maioria das bibliotecas de decodificador tem etapas manuais para fazer o check-out e criar as dependências. Portanto, siga as etapas no README da biblioteca relevante. Por exemplo, para a biblioteca ExoPlayer FFmpeg, é necessário seguir as instruções em libraries/decoder_ffmpeg/README.md, incluindo a transmissão de flags de configuração para ativar decodificadores para todos os formatos que você quer reproduzir.
- Para bibliotecas que têm código nativo, verifique se você está usando a versão correta do Android NDK, conforme especificado no README, e procure erros que apareçam durante a configuração e a criação. Os arquivos
.sovão aparecer no subdiretóriolibsdo caminho da biblioteca para cada arquitetura compatível depois de seguir as etapas no README. - Para testar a reprodução usando a biblioteca no aplicativo de demonstração, consulte Como ativar decodificadores agrupados. Consulte o README da biblioteca para instruções sobre como usar a biblioteca no seu próprio app.
- Se você estiver usando
DefaultRenderersFactory, uma linha de registro de nível de informação como "Loaded FfmpegAudioRenderer" vai aparecer no Logcat quando o decodificador for carregado. Se isso estiver faltando, verifique se o aplicativo tem uma dependência na biblioteca de decodificação. - Se você encontrar registros de nível de aviso de
LibraryLoaderno Logcat, isso indica que o carregamento do componente nativo da biblioteca falhou. Se isso acontecer, verifique se você seguiu as etapas no README da biblioteca corretamente e se nenhum erro foi gerado ao seguir as instruções.
Se você ainda estiver com problemas para usar bibliotecas de decodificação, consulte o Media3 rastreador de problemas para conferir problemas recentes relevantes. Se você precisar registrar um novo problema e ele estiver relacionado à criação da parte nativa da biblioteca, inclua a saída completa da linha de comando da execução das instruções do README para nos ajudar a diagnosticar o problema.
Posso reproduzir vídeos do YouTube diretamente com o ExoPlayer?
Não, o ExoPlayer não pode reproduzir vídeos do YouTube, como URLs do formato https://www.youtube.com/watch?v=.... Em vez disso, use a API YouTube iFrame Player,
que é a maneira oficial de reproduzir vídeos do YouTube no Android.
A reprodução de vídeo está instável
O dispositivo pode não conseguir decodificar o conteúdo com rapidez suficiente se, por exemplo, a taxa de bits ou a resolução do conteúdo excederem os recursos do dispositivo. Talvez seja necessário usar conteúdo de qualidade inferior para ter um bom desempenho nesses dispositivos.
Se você estiver com problemas de renderização lenta de vídeo em um dispositivo que executa uma versão do Android do Android 6.0 (nível 23 da API) até o Android 11 (nível 30 da API), inclusive, principalmente ao reproduzir conteúdo protegido por DRM ou de alta taxa de frames, tente ativar o enfileiramento de buffer assíncrono.
Erros de lint de API instável
O Media3 garante a compatibilidade binária para um subconjunto da plataforma de API. The
partes que não garantem a compatibilidade binária são marcadas com
@UnstableApi. Para deixar essa distinção clara, os usos de símbolos de API instáveis geram um erro de lint, a menos que sejam anotados com @OptIn.
A anotação @UnstableApi não implica nada sobre a qualidade ou o desempenho de uma API, apenas o fato de que ela não está "congelada".
Você tem duas opções para processar erros de lint de API instáveis:
- Mude para uma API estável que alcance o mesmo resultado.
- Continue usando a API instável e anote o uso com
@OptIn, conforme mostrado mais adiante.
Adicionar a anotação @OptIn
O Android Studio pode ajudar você a adicionar a anotação:
Também é possível anotar manualmente sites 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() { ... }
Pacotes inteiros podem ser ativados adicionando um arquivo 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;
Projetos inteiros podem ser ativados suprimindo o erro de lint específico no arquivo
lint.xml file:
<?xml version="1.0" encoding="utf-8"?>
<lint>
<issue id="UnsafeOptInUsageError">
<option name="opt-in" value="androidx.media3.common.util.UnstableApi" />
</issue>
</lint>
Há também uma anotação kotlin.OptIn que não deve ser usada. É importante usar a anotação androidx.annotation.OptIn.