ExoPlayer је отворена медија плејер библиотека за Android, развијена од стране Google-а као алтернатива уграђеном MediaPlayer-у. ExoPlayer обезбеђује репродукцију аудио и видео записа у различитим форматима, укључујући DASH, HLS, SmoothStreaming и обичне медијске датотеке, кроз јединствени API са подршком за адаптивни стриминг. Према Google I/O (2024), ExoPlayer се користи у преко 60.000 Android апликација, укључујући YouTube, Google TV и Netflix.
Главне ствари
ExoPlayer је библиотека за репродукцију мултимедије на Android-у са отвореним кодом (Apache 2.0), чија је прва верзија објављена од стране Google-а 2014. године. За разлику од уграђеног MediaPlayer-а, који је танак слој изнад системског медија кодекса (MediaCodec), ExoPlayer је у потпуности имплементиран на Java/Kotlin нивоу, што програмерима даје потпуну контролу над сваком фазом репродукције.
Архитектонски, ExoPlayer је изграђен на модуларном принципу: сваки аспект репродукције имплементиран је засебном компонентом. Главни модул (exoplayer-core) садржи плејер, рендерере, селекторе трака и управљање бафером. Додатни модули (exoplayer-dash, exoplayer-hls, exoplayer-rtsp, exoplayer-smoothstreaming) додају подршку за одговарајуће протоколе стриминга. Ова архитектура омогућава апликацијама да повежу само потребне компоненте, минимизирајући величину APK-а.
ExoPlayer 2 (тренутна главна верзија) објављен је 2018. године и донео је темељну прераду API-ја: увођење Player Interface-а, подршку за Compose кроз AndroidX Media3, побољшану обраду грешака и адаптивне алгоритме за избор трака. Почевши од верзије 2.19 (2024), ExoPlayer је постао део библиотеке AndroidX Media, што је поједноставило интеграцију и ажурирање кроз стандардни Android менаџер зависности.
У основи ExoPlayer-а лежи компонента ExoPlayerImpl, која управља животним циклусом репродукције. Она садржи MediaSource (извор медија), TrackSelector (избор трака), LoadControl (управљање баферисањем) и листу Renderer (рендерере за видео, аудио, титлове и метаподатке). Свака компонента може се заменити сопственом имплементацијом кроз Builder или фабричке методе.
За рендеровање видеа, ExoPlayer користи SurfaceView, TextureView или SphericalSurfaceView (за 360-степени видео). Препоручује се SurfaceView јер обезбеђује хардверско убрзање и минималну потрошњу енергије. За Jetpack Compose, библиотека AndroidX Media3 пружа компоненту `AndroidView`, која облаже SurfaceView, и експериментални `Media3Compose` са изворном Compose интеграцијом.
ExoPlayer пружа широк скуп функција које превазилазе обичан медија плејер. Главне могућности укључују подршку за све популарне протоколе стриминга, флексибилан DRM систем, адаптивно пребацивање битрејта (ABR) и алатке за аналитику репродукције.
| Функција | Опис | Модул |
|---|---|---|
| DASH | Адаптивни стриминг по MPEG стандарду | exoplayer-dash |
| HLS | HTTP Live Streaming од Apple-а | exoplayer-hls |
| SmoothStreaming | Адаптивни стриминг од Microsoft-а | exoplayer-smoothstreaming |
| RTSP | Real-Time Streaming Protocol за уживо | exoplayer-rtsp |
| Widevine | DRM заштита садржаја | exoplayer-drm |
| Concatenation | Спајање више медијских датотека | exoplayer-core |
| Ads | IMA SDK интеграција за рекламе | exoplayer-ima |
ABR (Adaptive Bitrate) у ExoPlayer-у је имплементиран кроз интерфејс AdaptiveTrackSelection. Подразумевано се користи AdaptiveTrackSelectionFactory, који креира DefaultAdaptiveTrackSelection — уравнотежен алгоритам који узима у обзир пропусни опсег мреже и величину бафера. За специфичне сценарије могу се повезати алтернативне имплементације: BOLA (минимализација пребацивања), RandomAdaptiveTrackSelection (тестирање) или сопствена имплементација кроз интерфејс TrackSelection.
BandwidthMeter је још једна кључна компонента одговорна за мерење пропусног опсега мреже. Подразумевано се користи DefaultBandwidthMeter, који прикупља статистику са свих HTTP захтева плејера. Програмер га може проширити да узме у обзир додатне факторе: тип мреже (Wi-Fi, 4G, 5G), сигнал мобилног торња или цену саобраћаја за корисника.
ExoPlayer подржава Widevine (L1, L3), PlayReady и ClearKey DRM. Добављање лиценце се конфигурише кроз DrmSessionManager, који комуницира са сервером лиценци. За премиум видео (4K HDR) потребна је хардверска подршка Widevine L1, која обезбеђује заштиту на нивоу чипа и спречава снимање екрана. Избор DRM система зависи од циљне платформе: Widevine се користи на Android-у и Chromecast-у, PlayReady на Xbox-у и Windows-у, FairPlay на iOS-у и Apple TV-у. ExoPlayer аутоматски одређује доступни DRM систем на основу MPD датотеке и не захтева ручну конфигурацију за основне сценарије.
Повезивање ExoPlayer-а са Android пројектом врши се кроз Gradle зависности. Почевши од верзије 2.19, ExoPlayer је део AndroidX Media (androidx.media3), што обезбеђује компатибилност са Jetpack Compose и другим AndroidX компонентама. Размотримо интеграцију корак по корак у Kotlin-у.
Додајте ExoPlayer модуле у датотеку build.gradle (Module). Минимални скуп укључује core, ui и модул за потребан протокол стриминга. За репродукцију DASH садржаја потребан је exoplayer-dash, за HLS — exoplayer-hls.
dependencies {
implementation "androidx.media3:media3-exoplayer:1.5.0"
implementation "androidx.media3:media3-ui:1.5.0"
implementation "androidx.media3:media3-exoplayer-dash:1.5.0"
implementation "androidx.media3:media3-exoplayer-hls:1.5.0"
}
Креирање и подешавање плејера у Activity или Fragment-у. ExoPlayer користи PlayerView (или StyledPlayerView за прилагођавање) за приказ видеа и уграђених контрола. Минимална конфигурација укључује креирање плејера кроз ExoPlayer.Builder и прослеђивање MediaItem-а са URI извора.
class PlayerActivity : AppCompatActivity() {
private var player: ExoPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player)
player = ExoPlayer.Builder(this).build()
val playerView = findViewById<StyledPlayerView>(R.id.playerView)
playerView.player = player
val mediaItem = MediaItem
.Builder()
.setUri("https://example.com/video.mp4")
.build()
player?.setMediaItem(mediaItem)
player?.prepare()
}
override fun onDestroy() {
player?.release()
super.onDestroy()
}
}
За продукцијске апликације неопходна је обрада могућих грешака репродукције: мрежни кварови, неподржани формати, грешке DRM лиценцирања. ExoPlayer пружа интерфејс Player.Listener са методама onPlayerError, onPlaybackStateChanged и onPlayWhenReadyChanged. Препоручује се приказивање информативних порука о грешкама са могућношћу понављања.
Избор између ExoPlayer-а и уграђеног MediaPlayer-а је често питање при развоју Android апликација. MediaPlayer је део Android SDK-а од верзије 1.0, док је ExoPlayer библиотека која захтева повезивање кроз Gradle. Размотримо њихове разлике по кључним критеријумима.
| Критеријум | ExoPlayer | MediaPlayer |
|---|---|---|
| Архитектура | Модуларна, у потпуности на Java/Kotlin | Слој изнад системских C++ компоненти |
| Стриминг | DASH, HLS, SmoothStreaming, RTSP | Само локалне датотеке и HLS (Android 9+) |
| Прилагођавање | Потпуно (свака компонента замењива) | Минимално (само параметри) |
| Ажурирања | Кроз Google Play или APK (независно од ОС) | Само кроз ажурирање Android-а (OTA) |
| Величина APK | +1-3 MB (у зависности од модула) | 0 (део система) |
| Min SDK | API 16+ (Android 4.1) | API 1+ |
| DRM | Widevine, PlayReady, ClearKey | Widevine (ограничено) |
ExoPlayer побеђује у сценаријима који захтевају стриминг (DASH, HLS), прилагођавање UI-ја, подршку за DRM и независност од верзије Android-а. MediaPlayer је погодан за једноставне апликације које репродукују локалне медијске датотеке, где је величина APK-а критична и нема захтева за адаптивним стримингом. За модерне апликације са садржајем са мреже, ExoPlayer је несумњив избор.
Изузетак — апликације са минималним SDK-ом испод API 16 (Android 4.1), којих практично више нема на тржишту. За све апликације са targetSdk 33+ и минималним SDK 21+, ExoPlayer није само пожељан, већ и неопходан за подршку модерним форматима као што су AV1 и Dolby Vision кроз одговарајућа проширења.
За продукцијске апликације, основна интеграција ExoPlayer-а често захтева додатно подешавање: управљање кеширањем, оптимизацију баферисања за мобилне мреже, интеграцију са аналитиком и прилагођавање избора аудио трака. Размотримо напредне сценарије употребе.
CacheDataSourceFactory омогућава кеширање преузетих сегмената у локалном складишту, што штеди саобраћај при поновном гледању и обезбеђује офлајн репродукцију. ExoPlayer користи SimpleCache из библиотеке exoplayer-cas — кеширање датотека са подршком за LRU евакуацију и ограничењима величине.
val cache = SimpleCache(
cacheDir,
LeastRecentlyUsedCacheEvictor(50 * 1024 * 1024),
AppDatabaseProvider(this)
)
val cacheDataSourceFactory = CacheDataSource
.Factory()
.setCache(cache)
val player = ExoPlayer.Builder(this)
.setMediaSourceFactory(
DefaultMediaSourceFactory(cacheDataSourceFactory)
)
.build()
У мобилним апликацијама, обрада пребацивања између Wi-Fi-ја и мобилне мреже је кључна. ExoPlayer пружа ConnectivityManager за праћење стања мреже. При губитку конекције, препоручује се да не заустављате плејер, већ да га пребаците у стање PAUSED са чувањем позиције. Након успостављања конекције, наставите репродукцију са поновним учитавањем сегмената.
Са изласком AndroidX Media3, библиотека је добила експерименталну подршку за Jetpack Compose. Компонента `AndroidView` облаже SurfaceView или PlayerView, обезбеђујући компатибилност са Compose хијерархијом. За дубљу интеграцију, користи се библиотека `androidx.media3:media3-ui-compose`, која пружа Compose-компатибилне контроле за плејер.
@Composable
fun VideoPlayer(uri: String) {
val context = LocalContext.current
val player = remember {
ExoPlayer.Builder(context).build()
.also { it.setMediaItem(MediaItem.fromUri(uri)) }
}
DisposableEffect(key = null) {
player.prepare()
onDispose { player.release() }
}
AndroidView(
factory = { StyledPlayerView(context).also { it.player = player } }
)
}
Често постављана питања
ExoPlayer подржава Android API 16+ (Android 4.1 Jelly Bean). Међутим, за DASH и HLS са fMP4 сегментима препоручује се API 21+ (Android 5.0 Lollipop). DRM модули (Widevine) захтевају API 19+, а хардверско декодирање HEVC доступно је од API 21.
Да, ExoPlayer је одличан за аудио. За репродукцију само звука није потребан SurfaceView ни PlayerView. ExoPlayer ће аутоматски изабрати аудио рендерер и радити у позадини. За позадинску репродукцију, препоручује се коришћење MediaSessionService за интеграцију са системским контролама.
TrackSelector у ExoPlayer-у управља избором аудио трака. За пребацивање користите player.getCurrentTracks().groups и player.setTrackSelectionParameters() са навођењем жељеног језика аудија. За DASH и HLS стримове са више аудио трака, пребацивање се врши без прекида репродукције.
Да, ExoPlayer подржава уграђене (у контејнеру MP4, WebM) и спољне титлове у форматима TTML, SRT, VTT и CEA-608. За спољне титлове користи се SingleSampleMediaSource или MergingMediaSource за спајање са видео током. Приказ стилизованих титлова подешава се кроз CaptionStyleCompat.
За Low-Latency стриминг, подесите LoadControl са мањим циљним вредностима бафера: користите DefaultLoadControl.Builder().setTargetBufferBytes(1024 * 512).setBufferDurationsMs(500, 2000, 500, 1000) за HLS LL и DASH LL. Такође, подесите minPlaybackSpeed = 1.02 за убрзано пуњење бафера при заостајању за уживо преносом.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође