- Correggere gli errori "Traffico HTTP in chiaro non consentito"
- Correzione degli errori "SSLHandshakeException", "CertPathValidatorException" ed "ERR_CERT_AUTHORITY_INVALID"
- Perché non è possibile cercare alcuni file multimediali?
- Perché in alcuni file MP3 la ricerca non è accurata?
- Perché la ricerca nel video è lenta?
- Perché alcuni file MPEG-TS non vengono riprodotti?
- Perché in alcuni file MPEG-TS non sono disponibili i sottotitoli?
- Perché alcuni file MP4/FMP4 vengono riprodotti in modo errato?
- Perché alcuni flussi hanno esito negativo con il codice di risposta HTTP 301 o 302?
- Perché alcuni flussi di dati non vengono riconosciuti con un'eccezione "UnRecognitionInputFormatException"?
- Perché setPlaybackParameters non funziona correttamente su alcuni dispositivi?
- Che cosa significano gli errori "Accesso al player sul thread sbagliato"?
- Come faccio a risolvere il problema "Riga di stato non prevista: ICY 200 OK"?
- Come posso chiedere se lo stream in riproduzione è un live streaming?
- Come faccio a continuare a riprodurre l'audio quando la mia app viene riprodotta in background?
- Perché ExoPlayer supporta i miei contenuti ma non la raccolta Cast di ExoPlayer?
- Perché i contenuti non vengono riprodotti, ma non vengono visualizzati errori?
- Come faccio a far caricare una libreria di decodifica da caricare e usarla per la riproduzione?
- Posso riprodurre i video di YouTube direttamente con ExoPlayer?
- La riproduzione del video si interrompe
- Errori lint dell'API instabili
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:
- 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.
- 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:
- 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).
- 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:
- Devi disporre di un servizio in primo piano in esecuzione. In questo modo il sistema non termina il processo per liberare risorse.
- Devi contenere una
WifiLock
e unaWakeLock
. Questi assicurano che il sistema mantenga attivi la radio Wi-Fi e la CPU. Questa operazione può essere eseguita facilmente se usiExoPlayer
chiamandosetWakeMode
, 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 sottodirectorylibs
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.
Errori lint dell'API instabili
Media3 garantisce la compatibilità binaria per un sottoinsieme della piattaforma API. Le parti che non garantiscono la compatibilità binaria sono contrassegnate con @UnstableApi
. Per fare questa distinzione, gli utilizzi di simboli API instabili generano un errore lint a meno che non siano annotati con @OptIn
.
L'annotazione @UnstableApi
non implica nulla sulla qualità o le prestazioni di un'API, ma solo il fatto che non sia "bloccata dall'API".
Hai a disposizione due opzioni per gestire gli errori di lint dell'API instabile:
- Passa a un'API stabile che ottenga lo stesso risultato.
- Continua a utilizzare l'API unstable e annota l'utilizzo con
@OptIn
, come mostrato in seguito.
Aggiungi l'annotazione @OptIn
Android Studio può aiutarti ad aggiungere l'annotazione:
![Screenshot: come aggiungere l'annotazione di attivazione](https://developer.android.com/static/media/media3/exoplayer/images/unstable-api.png?authuser=9&hl=it)
Puoi anche annotare manualmente siti di utilizzo specifici in Kotlin:
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
@OptIn(UnstableApi::class)
fun functionUsingUnstableApi() { ... }
E anche in Java:
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
@OptIn(markerClass = UnstableApi.class)
private void methodUsingUnstableApis() { ... }
È possibile attivare interi pacchetti aggiungendo un file package-info.java
:
@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
È possibile attivare interi progetti eliminando l'errore lint specifico nel
file 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>
È presente anche un'annotazione kotlin.OptIn
che non deve essere utilizzata. È importante utilizzare l'annotazione androidx.annotation.OptIn
.