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 בזמן אחזור קצר (קהילתי) לא
Common Media Client Data‏ (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, צריך להמיר את האובייקט המוחזר ל-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 באיכות גבוהה

כדי להפיק את המקסימום מ-ExoPlayer, יש הנחיות מסוימות שאפשר לפעול לפיהן כדי לשפר את התוכן ב-HLS. בפוסט שלנו ב-Medium על הפעלת HLS ב-ExoPlayer מוסבר בהרחבה על הנושא. הנקודות העיקריות הן:

  • להשתמש באורך מדויק של פלחים.
  • שימוש בזרם מדיה רציף, הימנעות משינויים במבנה המדיה בין קטעים.
  • משתמשים בתג #EXT-X-INDEPENDENT-SEGMENTS.
  • עדיף להשתמש בשידורים שהופרדו (demuxed) במקום בקבצים שכוללים גם וידאו וגם אודיו.
  • מומלץ לכלול את כל המידע האפשרי בפלייליסט עם וריאציות מרובות.

ההנחיות הבאות רלוונטיות במיוחד לשידורים חיים:

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