Analytics

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

یک سیستم تجزیه و تحلیل معمولاً باید ابتدا رویدادها را جمع آوری کند و سپس آنها را بیشتر پردازش کند تا آنها را معنی دار کند:

  • مجموعه رویداد : این کار را می توان با ثبت یک AnalyticsListener در یک نمونه ExoPlayer انجام داد. شنوندگان تجزیه و تحلیل ثبت شده رویدادها را همانطور که در طول استفاده از پخش کننده رخ می دهند، دریافت می کنند. هر رویداد با آیتم رسانه مربوطه در لیست پخش و همچنین موقعیت پخش و ابرداده مهر زمان مرتبط است.
  • پردازش رویداد : برخی از سیستم‌های تحلیلی رویدادهای خام را روی سرور آپلود می‌کنند و تمامی پردازش رویدادها در سمت سرور انجام می‌شود. پردازش رویدادها در دستگاه نیز امکان پذیر است، و انجام این کار ممکن است ساده تر باشد یا حجم اطلاعاتی که باید آپلود شود را کاهش دهد. ExoPlayer PlaybackStatsListener را ارائه می دهد که به شما امکان می دهد مراحل پردازش زیر را انجام دهید:
    1. تفسیر رویداد : برای اینکه برای اهداف تحلیلی مفید باشد، رویدادها باید در چارچوب یک پخش تفسیر شوند. برای مثال، رویداد خام تغییر وضعیت بازیکن به STATE_BUFFERING ممکن است مربوط به بافر اولیه، یک بافر مجدد یا بافری باشد که پس از جستجو اتفاق می‌افتد.
    2. ردیابی وضعیت : این مرحله رویدادها را به شمارنده تبدیل می کند. به عنوان مثال، رویدادهای تغییر حالت را می توان به شمارنده هایی تبدیل کرد که میزان زمان صرف شده در هر حالت پخش را ردیابی می کنند. نتیجه مجموعه ای اساسی از مقادیر داده های تحلیلی برای یک پخش است.
    3. جمع‌آوری : این مرحله داده‌های تجزیه و تحلیل را در چندین بازپخش ترکیب می‌کند، معمولاً با جمع کردن شمارنده‌ها.
    4. محاسبه معیارهای خلاصه : بسیاری از مفیدترین معیارها آنهایی هستند که میانگین ها را محاسبه می کنند یا مقادیر داده های تحلیلی پایه را به روش های دیگر ترکیب می کنند. معیارهای خلاصه را می توان برای پخش تک یا چندگانه محاسبه کرد.

مجموعه رویداد با 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();