HLS

ב-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.0")

מגניב

implementation "androidx.media3:media3-exoplayer-hls:1.4.0"

לאחר מכן אפשר ליצור 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.
  • עדיף להשתמש בשידורים מטושטשים על פני קבצים שכוללים גם וידאו וגם אודיו.
  • כלול את כל המידע שניתן להציג בפלייליסט מרובה המשתנים.

ההנחיות הבאות חלות באופן ספציפי על שידורים חיים:

  • משתמשים בתג #EXT-X-PROGRAM-DATE-TIME.
  • משתמשים בתג #EXT-X-DISCONTINUITY-SEQUENCE.
  • ליצור חלון זמן ארוך. דקה אחת או יותר זה מעולה.