Risoluzione dei problemi


Correggere gli errori "Traffico HTTP in chiaro non consentito"

Questo errore si verifica se la tua app richiede traffico HTTP in chiaro (ovvero http:// anziché https://), quando la relativa configurazione della sicurezza di rete non lo consente. Se la tua app ha come target Android 9 (livello API 28) o versioni successive, il traffico HTTP in chiaro viene disattivato per impostazione predefinita.

Se l'app deve funzionare con traffico HTTP in chiaro, devi utilizzare una configurazione di sicurezza di rete che lo consenta. Per dettagli, consulta la documentazione sulla sicurezza della rete di Android. Per attivare tutto il traffico HTTP in chiaro, puoi semplicemente aggiungere android:usesCleartextTraffic="true" all'elemento application del AndroidManifest.xml della tua app.

L'app demo ExoPlayer utilizza la configurazione di sicurezza di rete predefinita, pertanto non consente traffico HTTP con testo in chiaro. Puoi attivarlo seguendo le istruzioni sopra riportate.

Correzione degli errori "SSLHandshakeException", "CertPathValidatorException" ed "ERR_CERT_AUTHORITY_INVALID"

SSLHandshakeException, CertPathValidatorException e ERR_CERT_AUTHORITY_INVALID indicano tutti un problema con il certificato SSL del server. Questi errori non sono specifici di ExoPlayer. Per ulteriori dettagli, consulta la documentazione su SSL di Android.

Perché non è possibile cercare alcuni file multimediali?

Per impostazione predefinita, ExoPlayer non supporta la ricerca nei contenuti multimediali dove l'unico metodo per eseguire operazioni di ricerca accurate prevede la scansione e l'indicizzazione dell'intero file da parte del player. ExoPlayer considera questi file non visualizzabili. La maggior parte dei formati di container multimediali moderni include metadati per la ricerca (come un indice di esempio), hanno un algoritmo di ricerca ben definito (ad esempio la ricerca a bisezione interpolata per Ogg) o indicano che i loro contenuti sono a velocità in bit costante. ExoPlayer può contare su operazioni di ricerca efficienti in questi casi, supportate e supportate.

Se devi eseguire la ricerca, ma disponi di contenuti multimediali non ricercabili, ti consigliamo di convertire i contenuti in modo da utilizzare un formato contenitore più appropriato. Per i file MP3, ADTS e AMR, puoi anche attivare la ricerca partendo dal presupposto che i file abbiano una velocità in bit costante, come descritto qui.

Perché la ricerca non è accurata in alcuni file MP3?

I file MP3 con velocità in bit variabile (VBR) sono fondamentalmente inadatti per i casi d'uso che richiedono la ricerca esatta. I motivi sono due:

  1. Per la ricerca esatta, un formato container fornirà idealmente un mapping tempo per byte preciso in un'intestazione. Questa mappatura consente a un player di mappare un tempo di ricerca richiesto all'offset di byte corrispondente e di iniziare a richiedere, analizzare e riprodurre contenuti multimediali da quell'offset. Sfortunatamente, le intestazioni disponibili per specificare questa mappatura in MP3 (come le intestazioni XING) sono spesso imprecise.
  2. Per i formati di container che non forniscono una mappatura tempo-byte precisa (o qualsiasi mappatura tempo-byte), è comunque possibile eseguire una ricerca esatta se il container include timestamp di esempio assoluti nel flusso. In questo caso, un player può mappare il tempo di ricerca su una stima migliore dell'offset di byte corrispondente, iniziare a richiedere contenuti multimediali da quell'offset, analizzare il primo timestamp assoluto del campione ed eseguire in modo efficace una ricerca binaria guidata nei contenuti multimediali finché non trova il campione giusto. Purtroppo MP3 non include timestamp di esempio assoluti nello stream, quindi questo approccio non è possibile.

Per questi motivi, l'unico modo per eseguire una ricerca esatta in un file VBR MP3 è analizzare l'intero file e creare manualmente un mapping time-to-byte nel player. Questa strategia può essere attivata utilizzando FLAG_ENABLE_INDEX_SEEKING, che può essere impostato su un DefaultExtractorsFactory utilizzando setMp3ExtractorFlags. Tieni presente che non si adatta bene ai file MP3 di grandi dimensioni, in particolare se l'utente cerca di avvicinarsi alla fine dello stream poco dopo l'avvio della riproduzione, il che richiede al player di attendere che venga scaricato e indicizzato l'intero stream prima di eseguire la ricerca. In ExoPlayer, abbiamo deciso di ottimizzare la velocità piuttosto che la precisione, pertanto FLAG_ENABLE_INDEX_SEEKING è disattivato per impostazione predefinita.

Se controlli i contenuti multimediali che stai riproducendo, ti consigliamo vivamente di utilizzare un formato contenitore più appropriato, ad esempio MP4. Non siamo a conoscenza di casi d'uso in cui MP3 sia la scelta migliore per il formato multimediale.

Perché la ricerca nel video è lenta?

Quando il player cerca una nuova posizione di riproduzione in un video, deve eseguire due operazioni:

  1. Carica nel buffer i dati corrispondenti alla nuova posizione di riproduzione (questa operazione potrebbe non essere necessaria se questi dati sono già presenti nel buffer).
  2. Elimina il decodificatore video e inizia la decodifica dall'I-frame (frame chiave) prima della nuova posizione di riproduzione, a causa della codifica intra-frame utilizzata dalla maggior parte dei formati di compressione video. Per garantire che la ricerca sia accurata (ovvero, la riproduzione inizia esattamente nella posizione di ricerca), tutti i frame tra l'I-frame precedente e la posizione di ricerca devono essere decodificati e immediatamente annullati (senza essere mostrati sullo schermo).

La latenza introdotta da (1) può essere mitigata aumentando la quantità di dati archiviati nel buffer in memoria dal player o tramite la pre-memorizzazione dei dati nella cache su disco.

La latenza introdotta da (2) può essere mitigata riducendo l'accuratezza della ricerca utilizzando ExoPlayer.setSeekParameters, oppure ricodificando il video per avere frame I più frequenti, il che comporterà un file di output più grande.

Perché alcuni file MPEG-TS non vengono riprodotti?

Alcuni file MPEG-TS non contengono delimitatori di unità di accesso (AUD). Per impostazione predefinita, ExoPlayer si affida ad AUD per rilevare in modo economico i limiti dei frame. Analogamente, alcuni file MPEG-TS non contengono fotogrammi chiave IDR. Per impostazione predefinita, questi sono l'unico tipo di fotogrammi chiave preso in considerazione da ExoPlayer.

ExoPlayer sembrerà bloccato nello stato di buffering quando viene chiesto di riprodurre un file MPEG-TS privo di fotogrammi chiave AUD o IDR. Se devi riprodurre questi file, puoi farlo utilizzando rispettivamente FLAG_DETECT_ACCESS_UNITS e FLAG_ALLOW_NON_IDR_KEYFRAMES. Questi flag possono essere impostati su una DefaultExtractorsFactory utilizzando setTsExtractorFlags o su un DefaultHlsExtractorFactory utilizzando il costruttore. L'utilizzo di FLAG_DETECT_ACCESS_UNITS non ha effetti collaterali, a parte i costi di calcolo rispetto al rilevamento dei limiti dei frame basato su AUD. L'utilizzo di FLAG_ALLOW_NON_IDR_KEYFRAMES potrebbe causare un danneggiamento temporaneo della visualizzazione all'avvio della riproduzione e subito dopo le ricerche durante la riproduzione di alcuni file MPEG-TS.

Perché in alcuni file MPEG-TS non sono disponibili i sottotitoli?

Alcuni file MPEG-TS includono tracce CEA-608 ma non le dichiarano nei metadati del container, quindi ExoPlayer non è in grado di rilevarle. Puoi specificare manualmente qualsiasi traccia di sottotitoli fornendo a DefaultExtractorsFactory un elenco di formati di sottotitoli previsti, inclusi i canali di accessibilità che possono essere utilizzati per identificarli nello 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();

Perché alcuni file MP4/FMP4 vengono riprodotti in modo errato?

Alcuni file MP4/FMP4 contengono elenchi di modifica che riscrivono la sequenza temporale dei contenuti multimediali saltando, spostando o ripetendo gli elenchi di campioni. ExoPlayer supporta parzialmente l'applicazione di elenchi di modifica. Ad esempio, può ritardare o ripetere gruppi di campioni che iniziano su un campione di sincronizzazione, ma non tronca i campioni audio o i contenuti multimediali pre-roll per le modifiche che non iniziano su un campione di sincronizzazione.

Se noti che quella parte dei contenuti multimediali manca inaspettatamente o è ripetuta, prova a impostare Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS o FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS. In questo modo l'estrattore ignora completamente gli elenchi di modifica. Possono essere impostate su una DefaultExtractorsFactory utilizzando setMp4ExtractorFlags o setFragmentedMp4ExtractorFlags.

Perché alcuni flussi hanno esito negativo con il codice di risposta HTTP 301 o 302?

I codici di risposta HTTP 301 e 302 indicano entrambi il reindirizzamento. Le brevi descrizioni sono disponibili su Wikipedia. Quando ExoPlayer effettua una richiesta e riceve una risposta con il codice di stato 301 o 302, di solito segue il reindirizzamento e avvia la riproduzione normalmente. L'unico caso in cui questo non avviene per impostazione predefinita è per i reindirizzamenti multiprotocollo. Un reindirizzamento multiprotocollo è un reindirizzamento da HTTPS a HTTP o viceversa (o, meno spesso, tra un'altra coppia di protocolli). Puoi verificare se un URL causa un reindirizzamento multiprotocollo utilizzando lo strumento a riga di comando wget, nel seguente modo:

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

L'output dovrebbe essere simile al seguente:

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

In questo esempio sono presenti due reindirizzamenti. Il primo reindirizzamento è da https://yourserver.com/test.mp3 a https://second.com/test.mp3. Sono entrambi HTTPS, pertanto non si tratta di un reindirizzamento multiprotocollo. Il secondo reindirizzamento è da https://second.com/test.mp3 a http://third.com/test.mp3. Questo reindirizza da HTTPS a HTTP, così come il reindirizzamento multiprotocollo. ExoPlayer non seguirà questo reindirizzamento nella configurazione predefinita, il che significa che la riproduzione non andrà a buon fine.

Se necessario, puoi configurare ExoPlayer in modo che segua i reindirizzamenti multiprotocollo durante la creazione di un'istanza delle istanze DefaultHttpDataSource.Factory utilizzate nella tua applicazione. Scopri di più su come selezionare e configurare lo stack di rete qui.

Perché alcuni flussi di dati non vengono riconosciuti con un'eccezione UnRecognitionInputFormatException?

Questa domanda riguarda gli errori di riproduzione nel formato seguente:

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

Le cause possibili di questo errore sono due. La causa più comune è il tentativo di riprodurre contenuti DASH (mpd), HLS (m3u8) o UniformStreaming (ism, isml), ma il player tenta di riprodurli come stream progressivo. Per riprodurre questi stream, devi dipendere dal rispettivo modulo ExoPlayer. Nei casi in cui l'URI del flusso non termina con l'estensione del file standard, puoi anche passare MimeTypes.APPLICATION_MPD, MimeTypes.APPLICATION_M3U8 o MimeTypes.APPLICATION_SS a setMimeType di MediaItem.Builder per specificare esplicitamente il tipo di flusso.

La seconda, meno comune, è che ExoPlayer non supporta il formato container dei contenuti multimediali che stai tentando di riprodurre. In questo caso, l'errore funziona come previsto, ma ti invitiamo a inviare una richiesta di funzionalità al nostro Issue Tracker, includendo i dettagli sul formato del container e uno stream di prova. Cerca una richiesta di funzionalità esistente prima di inviarne una nuova.

Perché setPlaybackParameters non funziona correttamente su alcuni dispositivi?

Quando esegui una build di debug della tua app su Android M e versioni precedenti, potresti riscontrare prestazioni discontinua, artefatti udibili e un elevato utilizzo della CPU quando utilizzi l'API setPlaybackParameters. Questo perché un'ottimizzazione importante per questa API è disabilitata per le build di debug in esecuzione su queste versioni di Android.

È importante tenere presente che questo problema riguarda solo le build di debug. Non influisce sulle build di release, per le quali l'ottimizzazione è sempre abilitata. Di conseguenza, le release che fornisci agli utenti finali non dovrebbero essere interessate da questo problema.

Che cosa significano l'errore "Accesso al player sul thread sbagliato"?

Vedi Nota sull'organizzazione in thread nella pagina iniziale.

Come faccio a risolvere il problema "Riga di stato non prevista: ICY 200 OK"?

Questo problema può verificarsi se la risposta del server include una riga di stato ICY anziché una conforme a HTTP. Le righe di stato ICY sono deprecate e non devono essere utilizzate, quindi se controlli il server devi aggiornarlo in modo da fornire una risposta conforme HTTP. Se non riesci a farlo, utilizza la libreria OkHttp di ExoPlayer per risolvere il problema, poiché è in grado di gestire correttamente le righe di stato ICY.

Come posso chiedere se lo stream in riproduzione è un live streaming?

Puoi eseguire una query sul metodo isCurrentWindowLive del player. Inoltre, puoi controllare isCurrentWindowDynamic per scoprire se la finestra è dinamica (ovvero, deve essere ancora in fase di aggiornamento nel tempo).

Come faccio a mantenere la riproduzione audio quando la mia app viene riprodotta in background?

Per garantire la riproduzione continua dell'audio quando l'app è in background, procedi nel seguente modo:

  1. Devi disporre di un servizio in primo piano in esecuzione. In questo modo il sistema non termina il processo per liberare risorse.
  2. Devi contenere una WifiLock e una WakeLock. Questi assicurano che il sistema mantenga attivi la radio Wi-Fi e la CPU. Questa operazione può essere eseguita facilmente se usi ExoPlayer chiamando setWakeMode, che acquisterà e rilascerà automaticamente i blocchi richiesti al momento giusto.

È importante rilasciare i blocchi (se non utilizzi setWakeMode) e interrompere il servizio non appena l'audio non viene più riprodotto.

Perché ExoPlayer supporta i miei contenuti ma non la raccolta Cast di ExoPlayer?

È possibile che i contenuti che stai tentando di riprodurre non siano abilitati per CORS. Il framework Cast richiede che i contenuti siano abilitati per CORS per poter essere riprodotti.

Perché i contenuti non vengono riprodotti, ma non vengono rilevati errori?

È possibile che il dispositivo su cui stai riproducendo i contenuti non supporti un formato di esempio multimediale specifico. Questa operazione può essere facilmente confermata aggiungendo un EventLogger come listener per il player e cercando una riga simile a questa in Logcat:

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

NO_UNSUPPORTED_TYPE significa che il dispositivo non è in grado di decodificare il formato di esempio multimediale specificato da mimeType. Per informazioni sui formati di esempio supportati, consulta la documentazione relativa ai formati multimediali Android. Potrebbe essere utile anche ottenere una libreria di decodifica da caricare e utilizzare per la riproduzione?.

Come posso fare in modo che una libreria di decodifica sia caricata e usata per la riproduzione?

  • La maggior parte delle librerie decoder prevede passaggi manuali per eseguire il check-out e creare le dipendenze, quindi assicurati di aver seguito i passaggi nel file README della libreria pertinente. Ad esempio, per la libreria FFmpeg ExoPlayer è necessario seguire le istruzioni riportate in libraries/decoder_ffmpeg/README.md, incluso il passaggio di flag di configurazione per abilitare i decoder per tutti i formati che vuoi riprodurre.
  • Per le librerie che hanno codice nativo, assicurati di utilizzare la versione corretta dell'NDK di Android come specificato nel file README e fai attenzione a eventuali errori visualizzati durante la configurazione e la creazione. Dopo aver seguito i passaggi del file README, dovresti vedere i file .so nella sottodirectory libs del percorso della libreria per ogni architettura supportata.
  • Per provare la riproduzione utilizzando la libreria nell'applicazione demo, consulta la sezione sull'attivazione dei decoder in bundle. Per istruzioni su come usare la libreria dalla tua app, consulta il file README della libreria.
  • Se utilizzi DefaultRenderersFactory, quando viene caricato il decoder, dovresti vedere una riga di log a livello di informazioni come "Loaded FfmpegAudioRenderer" in Logcat. Se manca, assicurati che l'applicazione abbia una dipendenza dalla libreria di decodifica.
  • Se in Logcat vengono visualizzati log a livello di avviso da LibraryLoader, significa che il caricamento del componente nativo della libreria non è riuscito. Se ciò accade, verifica di aver seguito correttamente i passaggi nel file README della libreria e che non siano stati restituiti errori mentre segui le istruzioni.

Se i problemi riscontrati ancora durante l'utilizzo delle librerie di decodifica, controlla l'Issue Tracker di Media3 per individuare eventuali problemi recenti pertinenti. Se devi segnalare un nuovo problema relativo alla creazione della parte nativa della libreria, includi l'output completo della riga di comando dall'esecuzione delle istruzioni README, per aiutarci a diagnosticare il problema.

Posso riprodurre i video di YouTube direttamente con ExoPlayer?

No, ExoPlayer non può riprodurre video di YouTube, come gli URL nel modulo https://www.youtube.com/watch?v=.... Dovresti utilizzare invece l'API IFrame Player di YouTube, che è il modo ufficiale per riprodurre i video di YouTube su Android.

La riproduzione del video si interrompe

Il dispositivo potrebbe non essere in grado di decodificare abbastanza velocemente i contenuti se, ad esempio, la velocità in bit o la risoluzione dei contenuti superano le capacità del dispositivo. Potresti dover utilizzare contenuti di qualità inferiore per ottenere buone prestazioni su questi dispositivi.

Se riscontri problemi di stuttering dei video su un dispositivo con una versione di Android da Android 6.0 (livello API 23) fino ad Android 11 (livello API 30 incluso), in particolare durante la riproduzione di contenuti protetti da DRM o con frequenza fotogrammi elevata, puoi provare ad attivare la coda del buffer asincrona.