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
استفاده کنید. - یک پنجره زنده فراهم کنید. یک دقیقه یا بیشتر عالی است.