ExoPlayer mendukung HLS dengan beberapa format penampung. Format contoh audio dan video yang disertakan juga harus didukung (lihat bagian format contoh untuk mengetahui detailnya). Sebaiknya produsen konten HLS membuat streaming HLS berkualitas tinggi, seperti yang dijelaskan dalam postingan blog ini.
Fitur | Didukung | Komentar |
---|---|---|
Container | ||
MPEG-TS | YA | |
FMP4/CMAF | YA | |
ADTS (AAC) | YA | |
MP3 | YA | |
Teks tertutup / subtitel | ||
CEA-608 | YA | |
CEA-708 | YA | |
WebVTT | YA | |
Metadata | ||
ID3 | YA | |
SCTE-35 | TIDAK | |
Perlindungan konten | ||
AES-128 | YA | |
Contoh AES-128 | TIDAK | |
Widevine | YA | API 19+ ("skema cenc") dan 25+ ("skema cbcs") |
PlayReady SL2000 | YA | Khusus Android TV |
Kontrol server | ||
Update delta | YA | |
Memblokir pemuatan ulang playlist | YA | |
Memblokir pemuatan petunjuk pramuat | YA | Kecuali untuk byterange dengan panjang yang tidak ditentukan |
Penyisipan iklan | ||
Penyisipan iklan terpandu server (Interstisial) | Sebagian | Hanya VOD dengan X-ASSET-URI .
Live stream dan
X-ASSET-LIST akan ditambahkan
nanti. |
Iklan sisi server dan sisi klien IMA | YA | Panduan penyisipan iklan |
Pemutaran live | ||
Pemutaran live reguler | YA | |
HLS latensi rendah (Apple) | YA | |
HLS latensi rendah (Komunitas) | TIDAK | |
Common Media Client Data CMCD | YA | Panduan integrasi CMCD |
Menggunakan MediaItem
Untuk memutar streaming HLS, Anda harus bergantung pada modul HLS.
Kotlin
implementation("androidx.media3:media3-exoplayer-hls:1.6.0")
Groovy
implementation "androidx.media3:media3-exoplayer-hls:1.6.0"
Kemudian, Anda dapat membuat MediaItem
untuk URI playlist HLS dan meneruskannya ke
pemutar.
Kotlin
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri))
// Prepare the player.
player.prepare()
Java
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri));
// Prepare the player.
player.prepare();
Jika URI tidak diakhiri dengan .m3u8
, Anda dapat meneruskan MimeTypes.APPLICATION_M3U8
ke setMimeType
dari MediaItem.Builder
untuk secara eksplisit menunjukkan jenis
konten.
URI item media dapat mengarah ke playlist media atau playlist
multivarian. Jika URI mengarah ke playlist multivarian yang mendeklarasikan beberapa
tag #EXT-X-STREAM-INF
, ExoPlayer akan otomatis beradaptasi di antara
varian, dengan mempertimbangkan bandwidth yang tersedia dan kemampuan perangkat.
Menggunakan HlsMediaSource
Untuk opsi penyesuaian lainnya, Anda dapat membuat HlsMediaSource
dan meneruskannya
langsung ke pemutar, bukan MediaItem
.
Kotlin
// Create a data source factory.
val dataSourceFactory: DataSource.Factory = DefaultHttpDataSource.Factory()
// Create a HLS media source pointing to a playlist uri.
val hlsMediaSource =
HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(hlsUri))
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the HLS media source as the playlist with a single media item.
player.setMediaSource(hlsMediaSource)
// Prepare the player.
player.prepare()
Java
// Create a data source factory.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
// Create a HLS media source pointing to a playlist uri.
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(MediaItem.fromUri(hlsUri));
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the HLS media source as the playlist with a single media item.
player.setMediaSource(hlsMediaSource);
// Prepare the player.
player.prepare();
Mengakses manifes
Anda dapat mengambil manifes saat ini dengan memanggil Player.getCurrentManifest
.
Untuk HLS, Anda harus mentransmisikan objek yang ditampilkan ke HlsManifest
. Callback
onTimelineChanged
dari Player.Listener
juga dipanggil setiap kali
manifes dimuat. Hal ini akan terjadi sekali untuk konten on demand dan
mungkin berkali-kali untuk konten live. Cuplikan kode berikut menunjukkan cara aplikasi
dapat melakukan sesuatu setiap kali manifes dimuat.
Kotlin
player.addListener(
object : Player.Listener {
override fun onTimelineChanged(timeline: Timeline, @TimelineChangeReason reason: Int) {
val manifest = player.currentManifest
if (manifest is HlsManifest) {
// Do something with the manifest.
}
}
}
)
Java
player.addListener(
new Player.Listener() {
@Override
public void onTimelineChanged(
Timeline timeline, @Player.TimelineChangeReason int reason) {
Object manifest = player.getCurrentManifest();
if (manifest != null) {
HlsManifest hlsManifest = (HlsManifest) manifest;
// Do something with the manifest.
}
}
});
Memutar streaming HLS dengan interstisial
Spesifikasi HLS menentukan interstisial HLS yang dapat digunakan untuk menyertakan
informasi interstisial dalam playlist media. ExoPlayer secara default mengabaikan
interstisial ini. Dukungan dapat ditambahkan menggunakan HlsInterstitialsAdsLoader
. Kami
tidak mendukung semua fitur spesifikasi sejak awal. Jika Anda tidak mendapatkan dukungan untuk streaming, beri tahu kami dengan melaporkan masalah di GitHub dan kirimkan URI streaming Anda, sehingga kami dapat menambahkan dukungan untuk streaming Anda.
Menggunakan MediaItem
dengan playlist API
Cara paling praktis untuk memutar streaming HLS dengan interstisial adalah dengan mem-build
instance ExoPlayer dengan HlsInterstitialsAdsLoader.AdsMediaSourceFactory
.
Hal ini memungkinkan penggunaan playlist API berbasis MediaItem
dari antarmuka
Player
untuk memutar interstisial HLS.
MediaSource.Factory
dari ExoPlayer
dapat dimasukkan ke builder saat
mem-build instance pemutar:
Kotlin
hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(context)
// Create a MediaSource.Factory for HLS streams with interstitials.
var hlsMediaSourceFactory =
HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
hlsInterstitialsAdsLoader,
playerView,
DefaultMediaSourceFactory(context),
)
// Build player with interstitials media source factory
player =
ExoPlayer.Builder(context)
.setMediaSourceFactory(hlsMediaSourceFactory)
.build()
// Set the player on the ads loader.
hlsInterstitialsAdsLoader.setPlayer(player)
playerView.setPlayer(player)
Java
hlsInterstitialsAdsLoader = new HlsInterstitialsAdsLoader(context);
// Create a MediaSource.Factory for HLS streams with interstitials.
MediaSource.Factory hlsMediaSourceFactory =
new HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
hlsInterstitialsAdsLoader, playerView, new DefaultMediaSourceFactory(context));
// Build player with interstitials media source factory
player =
new ExoPlayer.Builder(context)
.setMediaSourceFactory(hlsMediaSourceFactory)
.build();
// Set the player on the ads loader.
hlsInterstitialsAdsLoader.setPlayer(player);
playerView.setPlayer(player);
Dengan penyiapan pemutar seperti itu, memutar interstisial HLS hanya dengan menetapkan
item media dengan AdsConfiguration
di pemutar:
Kotlin
player.setMediaItem(
MediaItem.Builder()
.setUri("https://www.example.com/media.m3u8")
.setAdsConfiguration(
AdsConfiguration.Builder(Uri.parse("hls://interstitials"))
.setAdsId("ad-tag-0") // must be unique within playlist
.build())
.build())
player.prepare();
player.play();
Java
player.setMediaItem(
new MediaItem.Builder()
.setUri("https://www.example.com/media.m3u8")
.setAdsConfiguration(
new AdsConfiguration.Builder(Uri.parse("hls://interstitials"))
.setAdsId("ad-tag-0") // must be unique within playlist
.build())
.build());
player.prepare();
player.play();
Menggunakan API berbasis sumber media
Atau, instance ExoPlayer dapat dibuat tanpa mengganti
factory sumber media default. Untuk mendukung interstisial, aplikasi kemudian dapat
menggunakan HlsInterstitialsAdsLoader.AdsMediaSourceFactory
secara langsung untuk membuat
MediaSource
dan menyediakannya ke ExoPlayer menggunakan API playlist
berbasis sumber media:
Kotlin
hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(context)
// Create a MediaSource.Factory for HLS streams with interstitials.
var hlsMediaSourceFactory =
HlsInterstitialsAdsLoader.AdsMediaSourceFactory(hlsInterstitialsAdsLoader, playerView, context)
// Build player with default media source factory.
player = new ExoPlayer.Builder(context).build();
// Create an media source from an HLS media item with ads configuration.
val mediaSource =
hlsMediaSourceFactory.createMediaSource(
MediaItem.Builder()
.setUri("https://www.example.com/media.m3u8")
.setAdsConfiguration(
MediaItem.AdsConfiguration.Builder(Uri.parse("hls://interstitials"))
.setAdsId("ad-tag-0")
.build()
)
.build()
)
// Set the media source on the player.
player.setMediaSource(mediaSource)
player.prepare()
player.play()
Java
HlsInterstitialsAdsLoader hlsInterstitialsAdsLoader = new HlsInterstitialsAdsLoader(context);
// Create a MediaSource.Factory for HLS streams with interstitials.
MediaSource.Factory hlsMediaSourceFactory =
new HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
hlsInterstitialsAdsLoader, playerView, context);
// Build player with default media source factory.
player = new ExoPlayer.Builder(context).build();
// Create an media source from an HLS media item with ads configuration.
MediaSource mediaSource =
hlsMediaSourceFactory.createMediaSource(
new MediaItem.Builder()
.setUri("https://www.example.com/media.m3u8")
.setAdsConfiguration(
new MediaItem.AdsConfiguration.Builder(Uri.parse("hls://interstitials"))
.setAdsId("ad-tag-0")
.build())
.build());
// Set the media source on the player.
exoPlayer.setMediaSource(mediaSource);
exoPlayer.prepare();
exoPlayer.play();
Memproses peristiwa iklan
Listener
dapat ditambahkan ke HlsInterstitialsAdsLoader
untuk memantau peristiwa
terkait perubahan status terkait pemutaran interstisial HLS. Hal ini memungkinkan
aplikasi atau SDK melacak iklan yang diputar, daftar aset yang dimuat, sumber media iklan yang
disiapkan, atau mendeteksi pemuatan daftar aset dan error penyiapan iklan. Selain itu, metadata
yang dipancarkan oleh sumber media iklan dapat diterima untuk verifikasi pemutaran iklan
yang terperinci atau untuk melacak progres pemutaran iklan.
Kotlin
class AdsLoaderListener : HlsInterstitialsAdsLoader.Listener {
override fun onStart(mediaItem: MediaItem, adsId: Any, adViewProvider: AdViewProvider) {
// Do something when HLS media item with interstitials is started.
}
override fun onMetadata(
mediaItem: MediaItem,
adsId: Any,
adGroupIndex: Int,
adIndexInAdGroup: Int,
metadata: Metadata,
) {
// Do something with metadata that is emitted by the ad media source of the given ad.
}
override fun onAdCompleted(
mediaItem: MediaItem,
adsId: Any,
adGroupIndex: Int,
adIndexInAdGroup: Int,
) {
// Do something when ad completed playback.
}
// ... See JavaDoc for further callbacks of HlsInterstitialsAdsLoader.Listener.
override fun onStop(mediaItem: MediaItem, adsId: Any, adPlaybackState: AdPlaybackState) {
// Do something with the resulting ad playback state when stopped.
}
}
Java
private class AdsLoaderListener
implements HlsInterstitialsAdsLoader.Listener {
// implement HlsInterstitialsAdsLoader.Listener
@Override
public void onStart(MediaItem mediaItem, Object adsId, AdViewProvider adViewProvider) {
// Do something when HLS media item with interstitials is started.
}
@Override
public void onMetadata(
MediaItem mediaItem,
Object adsId,
int adGroupIndex,
int adIndexInAdGroup,
Metadata metadata) {
// Do something with metadata that is emitted by the ad media source of the given ad.
}
@Override
public void onAdCompleted(
MediaItem mediaItem, Object adsId, int adGroupIndex, int adIndexInAdGroup) {
// Do something when ad completed playback.
}
// ... See JavaDoc for further callbacks of HlsInterstitialsAdsLoader.Listener.
@Override
public void onStop(MediaItem mediaItem, Object adsId, AdPlaybackState adPlaybackState) {
// Do something with the resulting ad playback state when stopped.
}
}
Pemroses kemudian dapat ditambahkan ke loader iklan:
Kotlin
var listener = AdsLoaderListener();
// Add the listener to the ads loader to receive ad loader events.
hlsInterstitialsAdsLoader.addListener(listener);
Java
AdsLoaderListener listener = new AdsLoaderListener();
// Add the listener to the ads loader to receive ad loader events.
hlsInterstitialsAdsLoader.addListener(listener);
Siklus proses HlsInterstitialsAdsLoader
Instance HlsInterstitialsAdsLoader
atau
HlsInterstitialsAdsLoader.AdsMediaSourceFactory
dapat digunakan kembali untuk beberapa
instance pemutar yang membuat beberapa sumber media yang iklannya harus
dimuat.
Instance dapat dibuat, misalnya dalam metode onCreate
dari Activity
,
lalu digunakan kembali untuk beberapa instance pemain. Hal ini berfungsi selama
digunakan oleh satu instance pemain secara bersamaan. Hal ini berguna untuk
kasus penggunaan umum saat aplikasi dipindahkan ke latar belakang, instance pemain
akan dihancurkan, lalu instance baru akan dibuat saat aplikasi kembali
ke latar depan.
Kotlin
// Create the ads loader instance (for example onCreate).
hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(context);
// Build a player and set it on the ads loader (for example onStart).
player = ExoPlayer.Builder(context).build();
hlsInterstitialsAdsLoader.setPlayer(player);
// Release the player and unset it on the ads loader (for example onStop).
player.release();
hlsInterstitialsAdsLoader.setPlayer(null);
// Build another player and set it on the ads loader (for example onStart).
player = ExoPlayer.Builder(context).build();
hlsInterstitialsAdsLoader.setPlayer(player);
// Release the player and unset it on the ads loader (for example onStop).
player.release();
hlsInterstitialsAdsLoader.setPlayer(null);
// Release the ads loader when not used anymore (for example onDestroy).
hlsInterstitialsAdsLoader.release();
Java
// Create the ads loader instance (for example onCreate).
hlsInterstitialsAdsLoader = new HlsInterstitialsAdsLoader(context);
// Build a player and set it on the ads loader (for example onStart).
player = new ExoPlayer.Builder(context).build();
hlsInterstitialsAdsLoader.setPlayer(player);
// Release the player and unset it on the ads loader (for example onStop).
player.release();
hlsInterstitialsAdsLoader.setPlayer(null);
// Build another player and set it on the ads loader (for example onStart).
player = new ExoPlayer.Builder(context).build();
hlsInterstitialsAdsLoader.setPlayer(player);
// Release the player and unset it on the ads loader (for example onStop).
player.release();
hlsInterstitialsAdsLoader.setPlayer(null);
// Release the ads loader when not used anymore (for example onDestroy).
hlsInterstitialsAdsLoader.release();
Umumnya, pastikan untuk merilis instance pemutar lama sebelum menetapkan instance pemutar berikutnya di loader iklan. Setelah loader iklan itu sendiri dirilis, loader iklan tidak dapat digunakan lagi.
Menyesuaikan pemutaran
ExoPlayer menyediakan beberapa cara bagi Anda untuk menyesuaikan pengalaman pemutaran dengan kebutuhan aplikasi. Lihat Halaman penyesuaian untuk mengetahui contohnya.
Menonaktifkan persiapan tanpa bagian
Secara default, ExoPlayer akan menggunakan persiapan tanpa potongan. Artinya, ExoPlayer
hanya akan menggunakan informasi dalam playlist multivarian untuk menyiapkan
streaming, yang berfungsi jika tag #EXT-X-STREAM-INF
berisi atribut
CODECS
.
Anda mungkin perlu menonaktifkan fitur ini jika segmen media Anda berisi trek teks tertutup
yang di-mux yang tidak dideklarasikan dalam playlist multivarian dengan
tag #EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS
. Jika tidak, trek teks tertutup ini
tidak akan terdeteksi dan diputar. Anda dapat menonaktifkan persiapan tanpa bagian di
HlsMediaSource.Factory
seperti yang ditunjukkan dalam cuplikan berikut. Perhatikan bahwa hal ini
akan meningkatkan waktu mulai karena ExoPlayer perlu mendownload segmen media untuk
menemukan trek tambahan ini dan sebaiknya deklarasikan
trek teks tertutup di playlist multivarian.
Kotlin
val hlsMediaSource =
HlsMediaSource.Factory(dataSourceFactory)
.setAllowChunklessPreparation(false)
.createMediaSource(MediaItem.fromUri(hlsUri))
Java
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(dataSourceFactory)
.setAllowChunklessPreparation(false)
.createMediaSource(MediaItem.fromUri(hlsUri));
Membuat konten HLS berkualitas tinggi
Untuk mendapatkan hasil maksimal dari ExoPlayer, ada panduan tertentu yang dapat Anda ikuti untuk meningkatkan kualitas konten HLS. Baca postingan Medium tentang pemutaran HLS di ExoPlayer untuk mengetahui penjelasan selengkapnya. Poin utamanya adalah:
- Gunakan durasi segmen yang tepat.
- Gunakan streaming media berkelanjutan; hindari perubahan pada struktur media di seluruh segmen.
- Gunakan tag
#EXT-X-INDEPENDENT-SEGMENTS
. - Pilih streaming yang telah didemux, bukan file yang menyertakan video dan audio.
- Sertakan semua informasi yang dapat Anda sertakan dalam Playlist Multivarian.
Panduan berikut berlaku khusus untuk live stream:
- Gunakan tag
#EXT-X-PROGRAM-DATE-TIME
. - Gunakan tag
#EXT-X-DISCONTINUITY-SEQUENCE
. - Berikan periode aktif yang lama. Satu menit atau lebih akan sangat bagus.