HLS

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

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

استفاده از MediaItem

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

کاتلین

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

گرووی

implementation "androidx.media3:media3-exoplayer-hls:1.8.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 تبدیل (cast) کنید. تابع 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.
val 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(
      MediaItem.AdsConfiguration.Builder("hls://interstitials".toUri())
        .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 استفاده کند و آن را با استفاده از API لیست پخش مبتنی بر منبع رسانه در اختیار ExoPlayer قرار دهد:

کاتلین

hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(context)
// Create a MediaSource.Factory for HLS streams with interstitials.
val hlsMediaSourceFactory =
  HlsInterstitialsAdsLoader.AdsMediaSourceFactory(hlsInterstitialsAdsLoader, playerView, context)

// Build player with default media source factory.
player = 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("hls://interstitials".toUri())
          .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.
  }
}

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

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

کاتلین

val 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 ایجاد کرد و سپس آن را برای چندین نمونه بازیکن دوباره استفاده کرد. این کار تا زمانی که همزمان توسط یک نمونه بازیکن واحد در حال استفاده باشد، کار می‌کند. این برای موارد استفاده رایج مفید است، زمانی که برنامه به پس‌زمینه برده می‌شود، نمونه بازیکن از بین می‌رود و سپس وقتی برنامه دوباره در پس‌زمینه قرار می‌گیرد، یک نمونه جدید ایجاد می‌شود.

از سرگیری پخش با حالت پخش آگهی

برای جلوگیری از تماشای مجدد تبلیغات توسط کاربران، وضعیت پخش تبلیغات می‌تواند ذخیره و پس از ایجاد مجدد پخش‌کننده بازیابی شود. این کار با فراخوانی getAdsResumptionStates() هنگام انتشار پخش‌کننده و ذخیره اشیاء AdsResumptionState برگردانده شده انجام می‌شود. هنگامی که پخش‌کننده دوباره ایجاد می‌شود، وضعیت را می‌توان با فراخوانی addAdResumptionState() روی نمونه بارگذاری تبلیغات بازیابی کرد. AdsResumptionState قابل بسته‌بندی است، بنابراین می‌توان آن را در بسته onSaveInstanceState یک Activity ذخیره کرد. توجه داشته باشید که از سرگیری تبلیغات فقط برای جریان‌های VOD پشتیبانی می‌شود.

کاتلین

companion object {
  const val ADS_RESUMPTION_STATE_KEY = "ads_resumption_state"
}

private var hlsInterstitialsAdsLoader: HlsInterstitialsAdsLoader? = null
private var playerView: PlayerView? = null
private var player: ExoPlayer? = null
private var adsResumptionStates: List<HlsInterstitialsAdsLoader.AdsResumptionState>? = null

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  // Create the ads loader instance.
  hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(this)
  // Restore ad resumption states.
  savedInstanceState?.getParcelableArrayList<Bundle>(ADS_RESUMPTION_STATE_KEY)?.let { bundles ->
    adsResumptionStates =
      bundles.map { HlsInterstitialsAdsLoader.AdsResumptionState.fromBundle(it) }
  }
}

override fun onStart() {
  super.onStart()
  // Build a player and set it on the ads loader.
  initializePlayer()
  hlsInterstitialsAdsLoader?.setPlayer(player)
  // Add any stored ad resumption states to the ads loader.
  adsResumptionStates?.forEach { hlsInterstitialsAdsLoader?.addAdResumptionState(it) }
  adsResumptionStates = null // Consume the states
}

override fun onStop() {
  super.onStop()
  // Get ad resumption states.
  adsResumptionStates = hlsInterstitialsAdsLoader?.adsResumptionStates
  releasePlayer()
}

override fun onDestroy() {
  // Release the ads loader when not used anymore.
  hlsInterstitialsAdsLoader?.release()
  hlsInterstitialsAdsLoader = null
  super.onDestroy()
}

override fun onSaveInstanceState(outState: Bundle) {
  super.onSaveInstanceState(outState)
  // Store the ad resumption states.
  adsResumptionStates?.let {
    outState.putParcelableArrayList(
      ADS_RESUMPTION_STATE_KEY,
      ArrayList(it.map(HlsInterstitialsAdsLoader.AdsResumptionState::toBundle)),
    )
  }
}

fun initializePlayer() {
  if (player == null) {
    // Create a media source factory for HLS streams.
    val hlsMediaSourceFactory =
      HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
        checkNotNull(hlsInterstitialsAdsLoader),
        playerView!!,
        /* context= */ this,
      )
    // Build player with interstitials media source
    player =
      ExoPlayer.Builder(/* context= */ this).setMediaSourceFactory(hlsMediaSourceFactory).build()
    // Set the player on the ads loader.
    hlsInterstitialsAdsLoader?.setPlayer(player)
    playerView?.player = player
  }

  // Use a media item with an HLS stream URI, an ad tag URI and ads ID.
  player?.setMediaItem(
    MediaItem.Builder()
      .setUri("https://www.example.com/media.m3u8")
      .setMimeType(MimeTypes.APPLICATION_M3U8)
      .setAdsConfiguration(
        MediaItem.AdsConfiguration.Builder("hls://interstitials".toUri())
          .setAdsId("ad-tag-0") // must be unique within ExoPlayer playlist
          .build()
      )
      .build()
  )
  player?.prepare()
  player?.play()
}

fun releasePlayer() {
  player?.release()
  player = null
  hlsInterstitialsAdsLoader?.setPlayer(null)
  playerView?.setPlayer(null)
}

جاوا

public static final String ADS_RESUMPTION_STATE_KEY = "ads_resumption_state";

@Nullable private HlsInterstitialsAdsLoader hlsInterstitialsAdsLoader;
@Nullable private PlayerView playerView;
@Nullable private ExoPlayer player;

private List<HlsInterstitialsAdsLoader.AdsResumptionState> adsResumptionStates;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // Create the ads loader instance.
  hlsInterstitialsAdsLoader = new HlsInterstitialsAdsLoader(this);
  // Restore ad resumption states.
  if (savedInstanceState != null) {
    ArrayList<Bundle> bundles =
        savedInstanceState.getParcelableArrayList(ADS_RESUMPTION_STATE_KEY);
    if (bundles != null) {
      adsResumptionStates = new ArrayList<>();
      for (Bundle bundle : bundles) {
        adsResumptionStates.add(
            HlsInterstitialsAdsLoader.AdsResumptionState.fromBundle(bundle));
      }
    }
  }
}

@Override
protected void onStart() {
  super.onStart();
  // Build a player and set it on the ads loader.
  initializePlayer();
  // Add any stored ad resumption states to the ads loader.
  if (adsResumptionStates != null) {
    for (HlsInterstitialsAdsLoader.AdsResumptionState state : adsResumptionStates) {
      hlsInterstitialsAdsLoader.addAdResumptionState(state);
    }
    adsResumptionStates = null; // Consume the states
  }
}

@Override
protected void onStop() {
  super.onStop();
  // Get ad resumption states before releasing the player.
  adsResumptionStates = hlsInterstitialsAdsLoader.getAdsResumptionStates();
  releasePlayer();
}

@Override
protected void onDestroy() {
  // Release the ads loader when not used anymore.
  if (hlsInterstitialsAdsLoader != null) {
    hlsInterstitialsAdsLoader.release();
    hlsInterstitialsAdsLoader = null;
  }
  super.onDestroy();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  // Store the ad resumption states.
  if (adsResumptionStates != null) {
    ArrayList<Bundle> bundles = new ArrayList<>();
    for (HlsInterstitialsAdsLoader.AdsResumptionState state : adsResumptionStates) {
      bundles.add(state.toBundle());
    }
    outState.putParcelableArrayList(ADS_RESUMPTION_STATE_KEY, bundles);
  }
}

private void initializePlayer() {
  if (player == null) {
    // Create a media source factory for HLS streams.
    MediaSource.Factory hlsMediaSourceFactory =
        new HlsInterstitialsAdsLoader.AdsMediaSourceFactory(
            checkNotNull(hlsInterstitialsAdsLoader), playerView, /* context= */ this);
    // Build player with interstitials media source
    player =
        new ExoPlayer.Builder(/* context= */ this)
            .setMediaSourceFactory(hlsMediaSourceFactory)
            .build();
    // Set the player on the ads loader.
    hlsInterstitialsAdsLoader.setPlayer(player);
    playerView.setPlayer(player);
  }

  // Use a media item with an HLS stream URI, an ad tag URI and ads ID.
  player.setMediaItem(
      new MediaItem.Builder()
          .setUri("https://www.example.com/media.m3u8")
          .setMimeType(MimeTypes.APPLICATION_M3U8)
          .setAdsConfiguration(
              new MediaItem.AdsConfiguration.Builder(Uri.parse("hls://interstitials"))
                  .setAdsId("ad-tag-0") // must be unique within ExoPlayer playlist
                  .build())
          .build());
  player.prepare();
  player.play();
}

private void releasePlayer() {
  if (player != null) {
    player.release();
    player = null;
  }
  if (hlsInterstitialsAdsLoader != null) {
    hlsInterstitialsAdsLoader.setPlayer(null);
  }
  if (playerView != null) {
    playerView.setPlayer(null);
  }
}

همچنین می‌توانید حالت‌های از سرگیری را به صورت تکی با removeAdResumptionState(Object adsId) حذف کنید یا همه را با clearAllAdResumptionStates() پاک کنید.

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

سفارشی‌سازی پخش

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

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

به طور پیش‌فرض، ExoPlayer از آماده‌سازی بدون قطعه‌بندی (chunkless) استفاده می‌کند. این بدان معناست که 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 استفاده کنید.
  • استریم‌های بدون فایل (demuxed) را به فایل‌هایی که شامل ویدیو و صدا هستند ترجیح دهید.
  • تمام اطلاعاتی را که می‌توانید در لیست پخش چند متغیره قرار دهید.

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

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