ExoPlayer mendukung HLS dengan beberapa format penampung. Format sampel audio dan video yang disertakan juga harus didukung (lihat bagian format sampel untuk mengetahui detailnya). Sebaiknya produser 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 | |
AES-128 Sampel | 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 rentang byte dengan panjang yang tidak ditentukan |
Penyisipan iklan | ||
Penyisipan iklan yang dipandu 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 | |
Data Klien Media Umum 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.7.1")
Groovy
implementation "androidx.media3:media3-exoplayer-hls:1.7.1"
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 Anda tidak diakhiri dengan .m3u8
, Anda dapat meneruskan MimeTypes.APPLICATION_M3U8
ke setMimeType
dari MediaItem.Builder
untuk menunjukkan jenis
konten secara eksplisit.
URI item media dapat mengarah ke playlist media atau playlist
multivariasi. Jika URI mengarah ke playlist multivarian yang mendeklarasikan beberapa tag #EXT-X-STREAM-INF
, ExoPlayer akan otomatis beradaptasi antar-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 melakukan transmisi objek yang ditampilkan ke HlsManifest
. Callback
onTimelineChanged
dari Player.Listener
juga dipanggil setiap kali
manifes dimuat. Hal ini akan terjadi satu kali 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 iklan interstisial
Spesifikasi HLS menentukan iklan interstisial HLS yang dapat digunakan untuk menyertakan informasi iklan interstisial dalam playlist media. Secara default, ExoPlayer mengabaikan iklan
interstitial ini. Dukungan dapat ditambahkan menggunakan HlsInterstitialsAdsLoader
. Kami tidak mendukung semua fitur spesifikasi sejak awal. Jika Anda tidak mendapatkan dukungan untuk
streaming Anda, beri tahu kami dengan melaporkan masalah di GitHub dan kirimkan URI
streaming Anda, agar kami dapat menambahkan dukungan untuk streaming Anda.
Menggunakan MediaItem
dengan playlist API
Cara paling mudah untuk memutar streaming HLS dengan iklan interstisial adalah dengan membuat 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 disuntikkan ke builder saat
membangun 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 iklan interstisial HLS hanya perlu menyetel 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 iklan interstisial, aplikasi kemudian dapat menggunakan HlsInterstitialsAdsLoader.AdsMediaSourceFactory
secara langsung untuk membuat MediaSource
dan memberikannya 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
mengenai perubahan status terkait pemutaran iklan interstisial HLS. Hal ini memungkinkan
aplikasi atau SDK melacak iklan yang diputar, daftar aset yang dimuat, sumber media iklan yang
disiapkan, atau mendeteksi error pemuatan daftar aset dan penyiapan iklan. Selain itu, metadata
yang dikeluarkan oleh sumber media iklan dapat diterima untuk verifikasi pemutaran iklan yang lebih mendetail
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
@Override
public void onStop(MediaItem mediaItem, Object adsId, AdPlaybackState adPlaybackState) {
// Do something with the resulting ad playback state when stopped.
}
}
Lihat JavaDoc HlsInterstitialsAdsLoader.Listener
untuk mengetahui dokumentasi mendetail semua callback yang tersedia.
Kemudian, pemroses dapat ditambahkan ke pemuat 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.
Misalnya, instance dapat dibuat dalam metode onCreate
dari Activity
lalu digunakan kembali untuk beberapa instance pemain. Hal ini berfungsi selama digunakan oleh satu instance pemain pada waktu yang sama. Hal ini berguna untuk kasus penggunaan umum saat aplikasi dibawa ke latar belakang, instance pemutar dihancurkan, lalu instance baru dibuat saat aplikasi dibawa ke latar depan lagi.
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();
Secara umum, pastikan untuk melepaskan instance pemutar lama sebelum menyetel instance pemutar berikutnya di pemuat iklan. Setelah pemuat iklan itu sendiri dirilis, pemuat iklan tidak dapat digunakan lagi.
Menyesuaikan pemutaran
ExoPlayer menyediakan beberapa cara bagi Anda untuk menyesuaikan pengalaman pemutaran dengan kebutuhan aplikasi Anda. Lihat Halaman penyesuaian untuk melihat contoh.
Menonaktifkan persiapan tanpa potongan
Secara default, ExoPlayer akan menggunakan persiapan tanpa potongan. Artinya, ExoPlayer
hanya akan menggunakan informasi dalam playlist multivariasi 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 dan 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 penyiapan tanpa potongan 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 lebih baik mendeklarasikan trek teks tertutup dalam 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 mengoptimalkan ExoPlayer, ada pedoman tertentu yang dapat Anda ikuti untuk meningkatkan kualitas konten HLS Anda. Baca postingan Medium kami tentang pemutaran HLS di ExoPlayer untuk mengetahui penjelasan selengkapnya. Poin utamanya adalah:
- Gunakan durasi segmen yang presisi.
- Gunakan aliran media berkelanjutan; hindari perubahan struktur media di seluruh segmen.
- Gunakan tag
#EXT-X-INDEPENDENT-SEGMENTS
. - Lebih memilih aliran yang sudah di-demux, bukan file yang menyertakan video dan audio.
- Sertakan semua informasi yang dapat Anda berikan di Playlist Multivarian.
Panduan berikut berlaku khusus untuk live stream:
- Gunakan tag
#EXT-X-PROGRAM-DATE-TIME
. - Gunakan tag
#EXT-X-DISCONTINUITY-SEQUENCE
. - Menyediakan jendela live yang panjang. Satu menit atau lebih sudah cukup.