ExoPlayer طیف گسترده ای از نیازهای تجزیه و تحلیل پخش را پشتیبانی می کند. در نهایت، تجزیه و تحلیل در مورد جمع آوری، تفسیر، جمع آوری، و خلاصه کردن داده ها از پخش است. این دادهها میتوانند در دستگاه مورد استفاده قرار گیرند - برای مثال برای ورود به سیستم، اشکالزدایی، یا اطلاعرسانی در تصمیمگیریهای پخش آینده - یا گزارش به سرور برای نظارت بر پخش در همه دستگاهها.
یک سیستم تجزیه و تحلیل معمولاً باید ابتدا رویدادها را جمع آوری کند و سپس آنها را بیشتر پردازش کند تا آنها را معنی دار کند:
- مجموعه رویداد : این کار را می توان با ثبت یک
AnalyticsListener
در یک نمونهExoPlayer
انجام داد. شنوندگان تجزیه و تحلیل ثبت شده رویدادها را همانطور که در طول استفاده از پخش کننده رخ می دهند، دریافت می کنند. هر رویداد با آیتم رسانه مربوطه در لیست پخش و همچنین موقعیت پخش و ابرداده مهر زمان مرتبط است. - پردازش رویداد : برخی از سیستمهای تحلیلی رویدادهای خام را روی سرور آپلود میکنند و تمامی پردازش رویدادها در سمت سرور انجام میشود. پردازش رویدادها در دستگاه نیز امکان پذیر است، و انجام این کار ممکن است ساده تر باشد یا حجم اطلاعاتی که باید آپلود شود را کاهش دهد. ExoPlayer
PlaybackStatsListener
را ارائه می دهد که به شما امکان می دهد مراحل پردازش زیر را انجام دهید:- تفسیر رویداد : برای اینکه برای اهداف تحلیلی مفید باشد، رویدادها باید در چارچوب یک پخش تفسیر شوند. برای مثال، رویداد خام تغییر وضعیت بازیکن به
STATE_BUFFERING
ممکن است مربوط به بافر اولیه، یک بافر مجدد یا بافری باشد که پس از جستجو اتفاق میافتد. - ردیابی وضعیت : این مرحله رویدادها را به شمارنده تبدیل می کند. به عنوان مثال، رویدادهای تغییر حالت را می توان به شمارنده هایی تبدیل کرد که میزان زمان صرف شده در هر حالت پخش را ردیابی می کنند. نتیجه مجموعه ای اساسی از مقادیر داده های تحلیلی برای یک پخش است.
- جمعآوری : این مرحله دادههای تجزیه و تحلیل را در چندین بازپخش ترکیب میکند، معمولاً با جمع کردن شمارندهها.
- محاسبه معیارهای خلاصه : بسیاری از مفیدترین معیارها آنهایی هستند که میانگین ها را محاسبه می کنند یا مقادیر داده های تحلیلی پایه را به روش های دیگر ترکیب می کنند. معیارهای خلاصه را می توان برای پخش تک یا چندگانه محاسبه کرد.
- تفسیر رویداد : برای اینکه برای اهداف تحلیلی مفید باشد، رویدادها باید در چارچوب یک پخش تفسیر شوند. برای مثال، رویداد خام تغییر وضعیت بازیکن به
مجموعه رویداد با AnalyticsListener
رویدادهای پخش خام از پخش کننده به پیاده سازی AnalyticsListener
گزارش می شود. شما به راحتی می توانید شنونده خود را اضافه کنید و فقط روش های مورد علاقه خود را لغو کنید:
کاتلین
exoPlayer.addAnalyticsListener( object : AnalyticsListener { override fun onPlaybackStateChanged( eventTime: EventTime, @Player.State state: Int ) {} override fun onDroppedVideoFrames( eventTime: EventTime, droppedFrames: Int, elapsedMs: Long, ) {} } )
جاوا
exoPlayer.addAnalyticsListener( new AnalyticsListener() { @Override public void onPlaybackStateChanged( EventTime eventTime, @Player.State int state) {} @Override public void onDroppedVideoFrames( EventTime eventTime, int droppedFrames, long elapsedMs) {} });
EventTime
که به هر تماس برگشتی ارسال میشود، رویداد را به یک مورد رسانه در لیست پخش و همچنین موقعیت پخش و ابرداده مهر زمان مرتبط میکند:
-
realtimeMs
: زمان ساعت دیواری رویداد. -
timeline
،windowIndex
وmediaPeriodId
: لیست پخش و موردی را در لیست پخش که رویداد به آن تعلق دارد، تعریف می کند.mediaPeriodId
حاوی اطلاعات اضافی اختیاری است، به عنوان مثال نشان می دهد که آیا رویداد متعلق به یک تبلیغ در مورد است یا خیر. -
eventPlaybackPositionMs
: موقعیت پخش در آیتم هنگام وقوع رویداد. -
currentTimeline
,currentWindowIndex
,currentMediaPeriodId
وcurrentPlaybackPositionMs
: مانند بالا اما برای آیتم در حال پخش. آیتم در حال پخش ممکن است با موردی که رویداد به آن تعلق دارد متفاوت باشد، برای مثال اگر رویداد مربوط به پیش بافر کردن آیتم بعدی باشد.
پردازش رویداد با PlaybackStatsListener
PlaybackStatsListener
یک AnalyticsListener
است که پردازش رویداد روی دستگاه را پیاده سازی می کند. PlaybackStats
را با شمارنده ها و معیارهای مشتق شده از جمله:
- معیارهای خلاصه، به عنوان مثال کل زمان پخش.
- معیارهای کیفیت پخش تطبیقی، به عنوان مثال وضوح متوسط ویدیو.
- ارائه معیارهای کیفیت، به عنوان مثال نرخ فریم های افت شده.
- معیارهای استفاده از منابع، به عنوان مثال تعداد بایت های خوانده شده در شبکه.
فهرست کاملی از تعداد موجود و معیارهای مشتق شده را در PlaybackStats
Javadoc خواهید دید.
PlaybackStatsListener
PlaybackStats
جداگانه را برای هر آیتم رسانه ای در لیست پخش، و همچنین هر تبلیغ سمت مشتری که در این موارد درج شده است، محاسبه می کند. میتوانید برای اطلاع از پخشهای تمامشده به PlaybackStatsListener
یک تماس پاسخ دهید و از EventTime
ارسال شده به تماس برای شناسایی پخششده استفاده کنید. امکان جمع آوری داده های تحلیلی برای پخش های متعدد وجود دارد. همچنین این امکان وجود دارد که PlaybackStats
برای جلسه پخش فعلی در هر زمان با استفاده از PlaybackStatsListener.getPlaybackStats()
پرس و جو کنید.
کاتلین
exoPlayer.addAnalyticsListener( PlaybackStatsListener(/* keepHistory= */ true) { eventTime: EventTime?, playbackStats: PlaybackStats?, -> // Analytics data for the session started at `eventTime` is ready. } )
جاوا
exoPlayer.addAnalyticsListener( new PlaybackStatsListener( /* keepHistory= */ true, (eventTime, playbackStats) -> { // Analytics data for the session started at `eventTime` is ready. }));
سازنده PlaybackStatsListener
این گزینه را می دهد تا تاریخچه کامل رویدادهای پردازش شده را حفظ کند. توجه داشته باشید که ممکن است بسته به مدت زمان پخش و تعداد رویدادها، این کار باعث سربار حافظه ناشناخته شود. بنابراین، تنها در صورتی باید آن را روشن کنید که نیاز به دسترسی به تاریخچه کامل رویدادهای پردازش شده دارید، نه فقط به داده های تجزیه و تحلیل نهایی.
توجه داشته باشید که PlaybackStats
از مجموعه ای گسترده از وضعیت ها استفاده می کند تا نه تنها وضعیت رسانه، بلکه همچنین قصد کاربر برای پخش و اطلاعات دقیق تر مانند علت قطع یا پایان پخش را نشان دهد:
وضعیت پخش | قصد کاربر برای بازی کردن | قصد بازی نداشتن |
---|---|---|
قبل از پخش | JOINING_FOREGROUND | NOT_STARTED ، JOINING_BACKGROUND |
پخش فعال | PLAYING | |
پخش قطع شد | BUFFERING ، SEEKING | PAUSED , PAUSED_BUFFERING , SUPPRESSED , SUPPRESSED_BUFFERING , INTERRUPTED_BY_AD |
حالات پایانی | ENDED ، STOPPED ، FAILED ، ABANDONED |
قصد کاربر برای بازی کردن برای تشخیص زمانهایی که کاربر فعالانه منتظر ادامه پخش بود از زمانهای انتظار غیرفعال مهم است. به عنوان مثال، PlaybackStats.getTotalWaitTimeMs
کل زمان صرف شده در وضعیتهای JOINING_FOREGROUND
، BUFFERING
و SEEKING
را برمیگرداند، اما نه زمانی که پخش متوقف شده است. به طور مشابه، PlaybackStats.getTotalPlayAndWaitTimeMs
کل زمان را با قصد کاربر برای بازی برمی گرداند، یعنی کل زمان انتظار فعال و کل زمان صرف شده در حالت PLAYING
.
وقایع پردازش و تفسیر شده است
می توانید رویدادهای پردازش شده و تفسیر شده را با استفاده از PlaybackStatsListener
با keepHistory=true
ضبط کنید. PlaybackStats
حاصل شامل لیست رویدادهای زیر خواهد بود:
-
playbackStateHistory
: فهرست مرتبی از حالتهای پخش گسترده باEventTime
که در آن شروع به اعمال کردند. همچنین میتوانید ازPlaybackStats.getPlaybackStateAtTime
برای جستجوی وضعیت در زمان معین ساعت دیواری استفاده کنید. -
mediaTimeHistory
: تاریخچه ای از زمان ساعت دیواری و جفت زمان رسانه ای که به شما امکان می دهد قسمت هایی از رسانه را در چه زمانی پخش شده بازسازی کنید. همچنین میتوانید ازPlaybackStats.getMediaTimeMsAtRealtimeMs
برای جستجوی موقعیت پخش در یک زمان معین ساعت دیواری استفاده کنید. -
videoFormatHistory
وaudioFormatHistory
: فهرستهای مرتب شده از فرمتهای ویدیویی و صوتی مورد استفاده در حین پخش باEventTime
زمانی که استفاده از آنها شروع شد. -
fatalErrorHistory
وnonFatalErrorHistory
: لیست های مرتب شده از خطاهای کشنده و غیرکشنده باEventTime
که در آن رخ داده اند. خطاهای مهلک آنهایی هستند که پخش را به پایان رساندند، در حالی که خطاهای غیر کشنده ممکن است قابل بازیابی باشند.
داده های تجزیه و تحلیل تک پخش
اگر از PlaybackStatsListener
استفاده میکنید، این دادهها بهطور خودکار جمعآوری میشوند، حتی با keepHistory=false
. مقادیر نهایی فیلدهای عمومی هستند که می توانید در PlaybackStats
Javadoc پیدا کنید و مدت زمان حالت پخش که توسط getPlaybackStateDurationMs
برگردانده شده است. برای راحتی، روشهایی مانند getTotalPlayTimeMs
و getTotalWaitTimeMs
را نیز خواهید یافت که مدت زمان ترکیبهای حالت پخش خاص را برمیگردانند.
کاتلین
Log.d( "DEBUG", "Playback summary: " + "play time = " + playbackStats.totalPlayTimeMs + ", rebuffers = " + playbackStats.totalRebufferCount )
جاوا
Log.d( "DEBUG", "Playback summary: " + "play time = " + playbackStats.getTotalPlayTimeMs() + ", rebuffers = " + playbackStats.totalRebufferCount);
جمع آوری داده های تجزیه و تحلیل چند پخش
می توانید با فراخوانی PlaybackStats.merge
چندین PlaybackStats
با هم ترکیب کنید. PlaybackStats
حاصل، حاوی دادههای جمعآوری شده از همه پخشهای ادغام شده است. توجه داشته باشید که تاریخچه رویدادهای پخش جداگانه را شامل نمی شود، زیرا نمی توان آنها را جمع کرد.
PlaybackStatsListener.getCombinedPlaybackStats
را می توان برای دریافت نمای جمعی از تمام داده های تحلیلی جمع آوری شده در طول عمر یک PlaybackStatsListener
استفاده کرد.
معیارهای خلاصه محاسبه شده
علاوه بر دادههای اصلی تجزیه و تحلیل، PlaybackStats
روشهای زیادی برای محاسبه معیارهای خلاصه ارائه میدهد.
کاتلین
Log.d( "DEBUG", "Additional calculated summary metrics: " + "average video bitrate = " + playbackStats.meanVideoFormatBitrate + ", mean time between rebuffers = " + playbackStats.meanTimeBetweenRebuffers )
جاوا
Log.d( "DEBUG", "Additional calculated summary metrics: " + "average video bitrate = " + playbackStats.getMeanVideoFormatBitrate() + ", mean time between rebuffers = " + playbackStats.getMeanTimeBetweenRebuffers());
موضوعات پیشرفته
ارتباط داده های تحلیلی با فراداده های پخش
هنگام جمعآوری دادههای تحلیلی برای پخشهای فردی، ممکن است بخواهید دادههای تجزیه و تحلیل بازپخش را با ابردادههای رسانه در حال پخش مرتبط کنید.
توصیه می شود ابرداده های خاص رسانه را با MediaItem.Builder.setTag
تنظیم کنید. تگ رسانه بخشی از EventTime
گزارش شده برای رویدادهای خام و زمانی است که PlaybackStats
به پایان می رسد، بنابراین هنگام مدیریت داده های تحلیلی مربوطه می توان آن را به راحتی بازیابی کرد:
کاتلین
PlaybackStatsListener(/* keepHistory= */ false) { eventTime: EventTime, playbackStats: PlaybackStats -> val mediaTag = eventTime.timeline .getWindow(eventTime.windowIndex, Timeline.Window()) .mediaItem .localConfiguration ?.tag // Report playbackStats with mediaTag metadata. }
جاوا
new PlaybackStatsListener( /* keepHistory= */ false, (eventTime, playbackStats) -> { Object mediaTag = eventTime.timeline.getWindow(eventTime.windowIndex, new Timeline.Window()) .mediaItem .localConfiguration .tag; // Report playbackStats with mediaTag metadata. });
گزارش رویدادهای تجزیه و تحلیل سفارشی
در صورت نیاز به افزودن رویدادهای سفارشی به داده های تجزیه و تحلیل، باید این رویدادها را در ساختار داده خود ذخیره کنید و بعداً آنها را با PlaybackStats
گزارش شده ترکیب کنید. اگر کمک کرد، میتوانید DefaultAnalyticsCollector
گسترش دهید تا بتوانید نمونههای EventTime
برای رویدادهای سفارشیتان ایجاد کرده و آنها را برای شنوندگان از قبل ثبتشده ارسال کنید، همانطور که در مثال زیر نشان داده شده است.
کاتلین
private interface ExtendedListener : AnalyticsListener { fun onCustomEvent(eventTime: EventTime) } private class ExtendedCollector : DefaultAnalyticsCollector(Clock.DEFAULT) { fun customEvent() { val eventTime = generateCurrentPlayerMediaPeriodEventTime() sendEvent(eventTime, CUSTOM_EVENT_ID) { listener: AnalyticsListener -> if (listener is ExtendedListener) { listener.onCustomEvent(eventTime) } } } } // Usage - Setup and listener registration. val player = ExoPlayer.Builder(context).setAnalyticsCollector(ExtendedCollector()).build() player.addAnalyticsListener( object : ExtendedListener { override fun onCustomEvent(eventTime: EventTime?) { // Save custom event for analytics data. } } ) // Usage - Triggering the custom event. (player.analyticsCollector as ExtendedCollector).customEvent()
جاوا
private interface ExtendedListener extends AnalyticsListener { void onCustomEvent(EventTime eventTime); } private static class ExtendedCollector extends DefaultAnalyticsCollector { public ExtendedCollector() { super(Clock.DEFAULT); } public void customEvent() { AnalyticsListener.EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); sendEvent( eventTime, CUSTOM_EVENT_ID, listener -> { if (listener instanceof ExtendedListener) { ((ExtendedListener) listener).onCustomEvent(eventTime); } }); } } // Usage - Setup and listener registration. ExoPlayer player = new ExoPlayer.Builder(context).setAnalyticsCollector(new ExtendedCollector()).build(); player.addAnalyticsListener( (ExtendedListener) eventTime -> { // Save custom event for analytics data. }); // Usage - Triggering the custom event. ((ExtendedCollector) player.getAnalyticsCollector()).customEvent();