HLS

ExoPlayer از HLS با چندین فرمت کانتینر پشتیبانی می کند. فرمت‌های نمونه صوتی و تصویری موجود نیز باید پشتیبانی شوند (برای جزئیات به بخش قالب‌های نمونه مراجعه کنید). ما قویاً تولیدکنندگان محتوای HLS را تشویق می‌کنیم که جریان‌های HLS با کیفیت بالا تولید کنند، همانطور که در این پست وبلاگ توضیح داده شده است.

ویژگی پشتیبانی می شود نظرات
ظروف
MPEG-TS بله
FMP4/CMAF بله
ADTS (AAC) بله
MP3 بله
زیرنویس / زیرنویس بسته
CEA-608 بله
CEA-708 بله
WebVTT بله
فراداده
ID3 بله
SCTE-35 نه
حفاظت از محتوا
AES-128 بله
نمونه AES-128 نه
وایدواین بله API 19+ (طرح "cenc") و 25+ (طرح "cbcs")
PlayReady SL2000 بله فقط Android TV
کنترل سرور
به روز رسانی دلتا بله
مسدود کردن بارگیری مجدد لیست پخش بله
مسدود کردن بار نکات پیش بارگذاری بله به جز فرگهای فرعی با طول نامشخص
درج آگهی
درج آگهی با هدایت سرور (Interstitials) تا حدی فقط VOD با X-ASSET-URI . پخش‌های زنده و X-ASSET-LIST بعداً اضافه خواهند شد.
تبلیغات سمت سرور و سمت سرویس گیرنده IMA بله راهنمای درج آگهی
پخش زنده
پخش زنده منظم بله
HLS کم تاخیر (Apple) بله
HLS با تأخیر کم (انجمن) نه
Common Media Client Data CMCD بله راهنمای ادغام CMCD

با استفاده از MediaItem

برای پخش جریان HLS، باید به ماژول HLS وابسته باشید.

کاتلین

implementation("androidx.media3:media3-exoplayer-hls:1.6.0")

شیار

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

سپس می توانید یک MediaItem برای URI لیست پخش HLS ایجاد کنید و آن را به پخش کننده ارسال کنید.

کاتلین

// 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()

جاوا

// 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 مستقیماً به پخش‌کننده ارسال کنید.

کاتلین

// 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()

جاوا

// 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 نیز هر زمان که مانیفست بارگیری می شود فراخوانی می شود. این یک بار برای محتوای درخواستی و احتمالاً بارها برای محتوای زنده اتفاق می افتد. قطعه کد زیر نشان می دهد که چگونه یک برنامه می تواند هر زمان که مانیفست بارگیری می شود کاری انجام دهد.

کاتلین

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.
      }
    }
  }
)

جاوا

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.
        }
      }
    });

پخش جریانی HLS با موارد بینابینی

مشخصات HLS، بینابینی‌های HLS را تعریف می‌کند که می‌تواند برای گنجاندن اطلاعات بین‌ابینی در فهرست پخش رسانه‌ای مورد استفاده قرار گیرد. ExoPlayer به طور پیش فرض این موارد بینابینی را نادیده می گیرد. پشتیبانی را می توان با استفاده از HlsInterstitialsAdsLoader اضافه کرد. ما از ابتدا از همه ویژگی های مشخصات پشتیبانی نمی کنیم. اگر پشتیبانی از جریان خود را از دست دادید، با ثبت مشکل در GitHub به ما اطلاع دهید و URI جریان خود را برای ما ارسال کنید، تا بتوانیم پشتیبانی برای جریان شما اضافه کنیم.

از MediaItem با API لیست پخش استفاده کنید

راحت‌ترین راه برای پخش جریان‌های HLS با موارد بینابینی، ساختن یک نمونه ExoPlayer با HlsInterstitialsAdsLoader.AdsMediaSourceFactory است. این اجازه می دهد تا از API لیست پخش مبتنی بر MediaItem در رابط Player برای پخش بینابینی های HLS استفاده کنید.

MediaSource.Factory ExoPlayer می توان در هنگام ساختن نمونه پخش کننده به سازنده تزریق کرد:

کاتلین

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)

جاوا

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);

با چنین تنظیمات پخش‌کننده، پخش میان‌افزارهای HLS فقط در مورد تنظیم یک آیتم رسانه با AdsConfiguration در پخش‌کننده است:

کاتلین

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();

جاوا

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();

از API مبتنی بر منبع رسانه استفاده کنید

متناوبا، نمونه ExoPlayer را می توان بدون نادیده گرفتن کارخانه منبع رسانه پیش فرض ایجاد کرد. برای پشتیبانی از موارد بینابینی، یک برنامه می‌تواند از HlsInterstitialsAdsLoader.AdsMediaSourceFactory مستقیماً برای ایجاد یک MediaSource و ارائه آن به ExoPlayer با استفاده از API فهرست پخش مبتنی بر منبع رسانه استفاده کند:

کاتلین

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()

جاوا

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();

به رویدادهای تبلیغاتی گوش دهید

Listener می توان به HlsInterstitialsAdsLoader اضافه کرد تا رویدادهای مربوط به تغییرات وضعیت مربوط به پخش بینابینی HLS را نظارت کند. این به یک برنامه یا SDK امکان می‌دهد آگهی‌های پخش‌شده، فهرست‌های دارایی در حال بارگیری، منابع رسانه تبلیغاتی در حال آماده‌سازی را ردیابی کند یا بارگذاری فهرست دارایی و خطاهای آماده‌سازی آگهی را شناسایی کند. علاوه بر این، ابرداده‌های منتشر شده توسط منابع رسانه‌های تبلیغاتی را می‌توان برای تأیید دقیق پخش آگهی یا ردیابی پیشرفت پخش آگهی دریافت کرد.

کاتلین

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.
  }
}

جاوا

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.
  }
}

برای مستندات دقیق همه تماس های موجود، به JavaDoc HlsInterstitialsAdsLoader.Listener مراجعه کنید.

سپس شنونده را می توان به لودر تبلیغات اضافه کرد:

کاتلین

var listener  = AdsLoaderListener();
// Add the listener to the ads loader to receive ad loader events.
hlsInterstitialsAdsLoader.addListener(listener);

جاوا

AdsLoaderListener listener = new AdsLoaderListener();
// Add the listener to the ads loader to receive ad loader events.
hlsInterstitialsAdsLoader.addListener(listener);

چرخه عمر HlsInterstitialsAdsLoader

نمونه‌ای از HlsInterstitialsAdsLoader یا HlsInterstitialsAdsLoader.AdsMediaSourceFactory را می‌توان برای نمونه‌های پخش‌کننده‌های متعددی که منابع رسانه‌ای متعددی ایجاد می‌کنند که تبلیغات باید برای آنها بارگیری شود، دوباره استفاده شود.

یک نمونه را می توان به عنوان مثال در متد onCreate یک Activity ایجاد کرد و سپس برای چندین نمونه بازیکن دوباره استفاده کرد. این تا زمانی کار می کند که به طور همزمان توسط یک نمونه تک پخش کننده استفاده شود. زمانی که برنامه در پس‌زمینه گرفته می‌شود، نمونه پخش‌کننده از بین می‌رود و پس از آن که برنامه دوباره در پیش‌زمینه قرار می‌گیرد، یک نمونه جدید ایجاد می‌شود، این مورد مفید است.

کاتلین

// 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();

جاوا

// 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();

به طور کلی، قبل از تنظیم نمونه پخش بعدی در بارکننده تبلیغات، حتماً نمونه پخش کننده قدیمی را آزاد کنید. هنگامی که خود بارکننده تبلیغات آزاد شد، دیگر نمی‌توان از لودر تبلیغات استفاده کرد.

سفارشی کردن پخش

ExoPlayer راه های متعددی را برای شما فراهم می کند تا تجربه پخش را مطابق با نیازهای برنامه خود تنظیم کنید. برای نمونه به صفحه سفارشی سازی مراجعه کنید.

غیرفعال کردن آماده سازی بدون تکه

به طور پیش فرض، ExoPlayer از آماده سازی بدون تکه استفاده می کند. این بدان معنی است که ExoPlayer تنها از اطلاعات موجود در لیست پخش چند متغیره برای آماده سازی جریان استفاده می کند، که در صورتی کار می کند که تگ های #EXT-X-STREAM-INF دارای ویژگی CODECS باشند.

اگر بخش‌های رسانه‌ای شما حاوی آهنگ‌های زیرنویس مختلطی هستند که با برچسب #EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS در فهرست پخش چند متغیره اعلام نشده‌اند، ممکن است لازم باشد این ویژگی را غیرفعال کنید. در غیر این صورت، این آهنگ‌های زیرنویس شناسایی و پخش نمی‌شوند. همانطور که در قطعه زیر نشان داده شده است، می توانید آماده سازی بدون تکه را در HlsMediaSource.Factory غیرفعال کنید. توجه داشته باشید که این امر زمان راه‌اندازی را افزایش می‌دهد زیرا ExoPlayer برای کشف این آهنگ‌های اضافی نیاز به دانلود یک بخش رسانه دارد و ترجیح داده می‌شود که به جای آن آهنگ‌های با شرح بسته در فهرست پخش چند متغیره اعلام شود.

کاتلین

val hlsMediaSource =
  HlsMediaSource.Factory(dataSourceFactory)
    .setAllowChunklessPreparation(false)
    .createMediaSource(MediaItem.fromUri(hlsUri))

جاوا

HlsMediaSource hlsMediaSource =
    new HlsMediaSource.Factory(dataSourceFactory)
        .setAllowChunklessPreparation(false)
        .createMediaSource(MediaItem.fromUri(hlsUri));

ایجاد محتوای HLS با کیفیت بالا

برای اینکه بیشترین بهره را از ExoPlayer ببرید، دستورالعمل‌های خاصی وجود دارد که می‌توانید برای بهبود محتوای HLS خود دنبال کنید. برای توضیح کامل پست Medium ما را در مورد پخش HLS در ExoPlayer بخوانید. نکات اصلی عبارتند از:

  • از مدت زمان دقیق قطعه استفاده کنید.
  • از یک جریان رسانه ای مداوم استفاده کنید. اجتناب از تغییرات در ساختار رسانه در سراسر بخش.
  • از تگ #EXT-X-INDEPENDENT-SEGMENTS استفاده کنید.
  • به جای فایل‌هایی که شامل ویدیو و صدا هستند، جریان‌های دموکس را ترجیح دهید.
  • تمام اطلاعاتی را که می توانید در لیست پخش چند متغیره قرار دهید.

دستورالعمل های زیر به طور خاص برای پخش جریانی زنده اعمال می شود:

  • از برچسب #EXT-X-PROGRAM-DATE-TIME استفاده کنید.
  • از تگ #EXT-X-DISCONTINUITY-SEQUENCE استفاده کنید.
  • یک پنجره زنده فراهم کنید. یک دقیقه یا بیشتر عالی است.