ExoPlayer از HLS با قالبهای چندگانه محتوا پشتیبانی میکند. قالبهای نمونه صوتی و ویدیویی موجود در آن نیز باید پشتیبانی شوند (برای جزئیات، به بخش قالبهای نمونه مراجعه کنید). ما بهشدت تولیدکنندگان محتوای HLS را تشویق میکنیم که جاریسازیهای HLS با کیفیت بالا تولید کنند، همانطور که در این پست وبلاگ توضیح داده شده است.
| ویژگی | پشتیبانی میشود | نظرات |
|---|---|---|
| محتویها | ||
| MPEG-TS | بله | |
| FMP4/CMAF | بله | |
| ADTS (AAC) | بله | |
| MP3 | بله | |
| زیرنویس ناشنوایان / زیرنویس | ||
| CEA-608 | بله | |
| CEA-708 | بله | |
| WebVTT | بله | |
| فراداده | ||
| ID3 | بله | |
| SCTE-35 | نه | |
| حفاظت از محتوا | ||
| اِیایاس-۱۲۸ | بله | |
| نمونه AES-128 | نه | |
| Widevine | بله | API 19+ (طرح «cenc») و 25+ (طرح «cbcs») |
| PlayReady SL2000 | بله | فقط Android TV |
| کنترل سرور | ||
| بهروزرسانیهای دلتا | بله | |
| جلوگیری از بارگیری مجدد فهرست پخش | بله | |
| درحال مسدود کردن بار کردن اشارههای پیشبارگیری | بله | بهجز برای محدودههای بایت با طولهای تعریفنشده |
| درج آگهی | ||
| درج آگهی با هدایت سرور (بینابینیها) | تاحدودی | فقط ویدیو بهدرخواست با X-ASSET-URI.
جاریسازیهای زنده و
X-ASSET-LIST بعداً اضافه خواهند شد. |
| آگهیهای سمت سرور و سمت مشتری IMA | بله | راهنمای درج آگهی |
| بازپخش زنده | ||
| بازپخش زنده معمولی | بله | |
| HLS با تأخیر کم (Apple) | بله | |
| HLS با تأخیر کم (انجمن) | نه | |
| دادههای مشترک کارخواه رسانه CMCD | بله | راهنمای یکپارچهسازی CMCD |
درحال استفاده از MediaItem
برای پخش جاریسازی HLS، باید به واحد HLS وابسته باشید.
کاتلین
implementation("androidx.media3:media3-exoplayer-hls:1.11.1")
شیک
implementation "androidx.media3:media3-exoplayer-hls:1.11.1"
سپس میتوانید یک MediaItem برای نشانی وب فهرست پخش 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();
اگر شناسه منبع یکنواخت شما با .m3u8 تمام نمیشود، میتوانید MimeTypes.APPLICATION_M3U8
را به setMimeType از MediaItem.Builder منتقل کنید تا نوع محتوا را بهطور صریح مشخص کنید.
نشانی وب عنصر رسانهای ممکن است به فهرست پخش رسانهای یا فهرست پخش چندمتغیره اشاره کند. اگر شناسه منبع یکنواخت به فهرست پخش چندمتغیره که چندین برچسب #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, @Player.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 به ما اطلاع دهید و
نشانی وب جاریسازیتان را برای ما ارسال کنید تا بتوانیم پشتیبانی از جاریسازیتان را اضافه کنیم.
استفاده از MediaItem با API فهرست پخش
راحتترین راه برای پخش جاریسازیهای HLS با میانآگهیها، ساختن نمونه ExoPlayer با HlsInterstitialsAdsLoader.AdsMediaSourceFactory است.
این امکان استفاده از MediaItem مبتنی بر API فهرست پخش از Player
واسط را برای پخش میانآگهیهای HLS فراهم میکند.
MediaSource.Factory ExoPlayer میتواند هنگام ساختن نمونه پخشکننده به سازنده تزریق شود:
کاتلین
val 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 val player = ExoPlayer.Builder(context).setMediaSourceFactory(hlsMediaSourceFactory).build() // Set the player on the ads loader. hlsInterstitialsAdsLoader.setPlayer(player) playerView.setPlayer(player)
جاوا
HlsInterstitialsAdsLoader 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 ExoPlayer player = new ExoPlayer.Builder(context).setMediaSourceFactory(hlsMediaSourceFactory).build(); // Set the player on the ads loader. hlsInterstitialsAdsLoader.setPlayer(player); playerView.setPlayer(player);
با چنین تنظیم پخشکنندهای، پخش میانآگهیهای HLS فقط به تنظیم یک عنصر رسانهای با یک AdsConfiguration در پخشکننده مربوط میشود:
کاتلین
// Build an HLS media item with ads configuration to be played. 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()
جاوا
// Build an HLS media item with ads configuration to be played. 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 ارائه دهد:
کاتلین
val 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. val 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. ExoPlayer player = new ExoPlayer.Builder(context).build(); // Create a 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. player.setMediaSource(mediaSource); player.prepare(); player.play();
گوش دادن به رویدادهای آگهی
یک Listener میتواند به HlsInterstitialsAdsLoader اضافه شود تا رویدادهای مربوط به تغییرات وضعیت پخش میانآگهیهای HLS را نظارت کند. این کار به برنامه یا کیت توسعه نرمافزار اجازه میدهد آگهیهای پخششده، فهرستهای دارایی بارگیریشده، منابع رسانهای آگهی درحال آمادهسازی را ردیابی کند یا خطاهای آمادهسازی آگهی و بارگیری فهرست دارایی را شناسایی کند. علاوهبراین، فراداده منتشرشده توسط منابع رسانهای آگهی میتواند برای تأیید دقیق پخش آگهی یا برای پیگیری پیشرفت پخش آگهی دریافت شود.
کاتلین
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. } }
جاوا
@OptIn(markerClass = UnstableApi.class) private static 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 را ببینید.
سپس شنونده میتواند به بارکننده آگهیها اضافه شود:
کاتلین
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 ذخیره شود. توجه داشته باشید که ازسرگیری آگهی فقط برای جاریسازیهای «ویدیو بهدرخواست» پشتیبانی میشود
کاتلین
class HlsInterstitialsActivity : Activity() { 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 @Suppress("DEPRECATION") // getParcelableArrayList without class type is deprecated in API 33+ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Create the ads loader instance. hlsInterstitialsAdsLoader = HlsInterstitialsAdsLoader(this) // Restore ad resumption states. val bundles = if (Build.VERSION.SDK_INT >= 33) { savedInstanceState?.getParcelableArrayList(ADS_RESUMPTION_STATE_KEY, Bundle::class.java) } else { savedInstanceState?.getParcelableArrayList(ADS_RESUMPTION_STATE_KEY) } adsResumptionStates = bundles?.map(HlsInterstitialsAdsLoader.AdsResumptionState::fromBundle) } 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?.player = null } }
جاوا
@OptIn(markerClass = UnstableApi.class) public static class HlsInterstitialsActivity extends Activity { 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; @SuppressWarnings( "deprecation") // getParcelableArrayList without class type is deprecated in API 33+ @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; if (Build.VERSION.SDK_INT >= 33) { bundles = savedInstanceState.getParcelableArrayList(ADS_RESUMPTION_STATE_KEY, Bundle.class); } else { 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. if (hlsInterstitialsAdsLoader != null) { 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); } } }
سفارشیسازی بازپخش
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استفاده کنید. - یک پنجره طولانی برای پخش زنده ارائه دهید. یک دقیقه یا بیشتر عالی است.