ExoPlayer תומך ב-HLS עם כמה פורמטים של קונטיינרים. את האודיו הכלולים חייבת להיות תמיכה גם בפורמטים של דגימות וידאו (עיינו ב פורמטים לדוגמה לקבלת פרטים). אנחנו ממליצים מאוד ליוצרי תוכן ב-HLS ליצור שידורי HLS באיכות גבוהה, כפי שמתואר כאן.
תכונה | נתמך | תגובות |
---|---|---|
קונטיינרים | ||
MPEG-TS | כן | |
FMP4/CMAF | כן | |
ADTS (AAC) | כן | |
MP3 | כן | |
כתוביות | ||
CEA-608 | כן | |
CEA-708 | כן | |
WebVTT | כן | |
מטא-נתונים | ||
ID3 | כן | |
SCTE-35 | לא | |
הגנה על תוכן | ||
AES-128 | כן | |
דוגמה AES-128 | לא | |
Widevine | כן | API 19+ (סכימת cenc) וסכימת 25 + ('cbcs') |
PlayReady SL2000 | כן | Android TV בלבד |
שליטה דרך שרת | ||
עדכוני Delta | כן | |
חסימת הטעינה מחדש של פלייליסט | כן | |
חסימת הטעינה של רמזים לטעינה מראש | כן | מלבד טווחי בייטים עם אורך לא מוגדר |
הפעלה בשידור חי | ||
הפעלה רגילה בשידור חי | כן | |
HLS עם זמן אחזור קצר (Apple) | כן | |
זמן אחזור קצר של HLS (קהילה) | לא | |
נתוני לקוח מדיה נפוצים (CMCD) | כן | מדריך לשילוב |
שימוש ב-MediaItem
כדי להפעיל שידור בפרוטוקול HLS, צריך להסתמך על מודול HLS.
Kotlin
implementation("androidx.media3:media3-exoplayer-hls:1.4.1")
Groovy
implementation "androidx.media3:media3-exoplayer-hls:1.4.1"
לאחר מכן תוכלו ליצור MediaItem
עבור URI של פלייליסט HLS ולהעביר אותו לנגן.
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();
אם כתובת ה-URI לא מסתיימת ב-.m3u8
, אפשר להעביר את MimeTypes.APPLICATION_M3U8
אל setMimeType
של MediaItem.Builder
כדי לציין במפורש את סוג התוכן.
ה-URI של פריט המדיה עשוי להפנות לפלייליסט מדיה או לפלייליסט עם וריאנטים מרובים. אם ה-URI מפנה לפלייליסט רב-משתנים שמצהיר על מספר פריטים
#EXT-X-STREAM-INF
תגים, ולאחר מכן ExoPlayer יתאים באופן אוטומטי בין
שונים, תוך התייחסות גם לרוחב הפס הזמין וגם ליכולות המכשיר.
שימוש ב-HlsMediaSource
לאפשרויות התאמה אישית נוספות, אפשר ליצור HlsMediaSource
ולהעביר אותו ישירות לנגן במקום 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();
גישה למניפסט
אפשר לאחזר את המניפסט הנוכחי על ידי שליחת קריאה ל-Player.getCurrentManifest
.
ל-HLS, צריך להפעיל Cast של האובייקט שהוחזר אל HlsManifest
. הקריאה החוזרת onTimelineChanged
של Player.Listener
נקראת גם בכל פעם שהמניפסט נטען. זה יקרה פעם אחת עבור תוכן על פי דרישה,
כפעמים רבות לתוכן בשידור חי. קטע הקוד הבא מראה איך אפליקציה
אפשרות לבצע פעולה כלשהי בכל פעם שהמניפסט נטען.
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. } } });
התאמה אישית של ההפעלה
ב-ExoPlayer יש כמה דרכים להתאים אישית את חוויית ההפעלה לצרכים של האפליקציה. דוגמאות מופיעות בדף ההתאמה האישית.
השבתת הכנה ללא קטעים
כברירת מחדל, מערכת ExoPlayer תשתמש בהכנה ללא מקטעים. המשמעות היא ש-ExoPlayer ישתמש במידע בפלייליסט עם הווריאציות השונות רק כדי להכין את הסטרימינג. הפעולה הזו תתבצע אם התגים #EXT-X-STREAM-INF
מכילים את המאפיין CODECS
.
יכול להיות שתצטרכו להשבית את התכונה הזו אם פלחי המדיה שלכם מכילים תוכן מיושן
טראקים בכתוביות שלא הוצהרו בפלייליסט רב-המשתנים עם
תג #EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS
. אחרת, הטראקים האלה עם כתוביות
לא יזוהה ולא יופעלו. אפשר להשבית את ההכנה ללא קטעים ב-HlsMediaSource.Factory
, כפי שמתואר בקטע הקוד הבא. חשוב לזכור שהפעולה הזו תגדיל את זמן ההפעלה, כי ExoPlayer צריך להוריד קטע מדיה כדי לזהות את הטראקים הנוספים האלה. לכן, עדיף להצהיר על הטראקים של הכתוביות בפלייליסט עם הווריאנטים השונים.
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));
יצירת תוכן HLS באיכות גבוהה
כדי להפיק את המרב מ-ExpoPlayer, יש מספר הנחיות שניתן כדי לשפר את תוכן ה-HLS. הסבר מלא זמין בפוסט ב-Medium בנושא הפעלת HLS ב-ExoPlayer. הנקודות העיקריות הן:
- משתמשים במשכי זמן מדויקים של מקטעים.
- להשתמש בסטרימינג מדיה רציף. להימנע משינויים במבנה המדיה פלחים.
- משתמשים בתג
#EXT-X-INDEPENDENT-SEGMENTS
. - עדיף להשתמש בשידורים שהופרדו (demuxed) במקום בקבצים שכוללים גם וידאו וגם אודיו.
- כדאי לכלול את כל המידע האפשרי בפלייליסט עם וריאציות מרובות.
ההנחיות הבאות רלוונטיות במיוחד לשידורים חיים:
- משתמשים בתג
#EXT-X-PROGRAM-DATE-TIME
. - משתמשים בתג
#EXT-X-DISCONTINUITY-SEQUENCE
. - לספק חלון זמן ארוך לשידור החי. דקה אחת או יותר הן מצוינות.