Analytics

ExoPlayer는 다양한 재생 분석 요구사항을 지원합니다. 결국 애널리틱스는 데이터를 수집, 해석, 집계 및 요약하는 것입니다. 있습니다. 이 데이터는 기기(예: 알 수 있게 하거나 또는 향후 재생 결정을 알리는 데 사용되거나 모든 기기의 재생을 모니터링할 수 있습니다.

일반적으로 분석 시스템은 이벤트를 먼저 수집한 다음 처리해야 합니다. 더욱 의미 있게 만들 수 있습니다.

  • 이벤트 수집: ExoPlayerAnalyticsListener를 등록하면 됩니다. 인스턴스를 만들 수 있습니다 등록된 애널리틱스 리스너는 이벤트 발생 시 이벤트를 수신합니다. 지정할 수 있습니다. 각 이벤트는 해당 미디어와 연결됩니다. 재생 위치 및 타임스탬프 메타데이터도 확인할 수 있습니다.
  • 이벤트 처리: 일부 애널리틱스 시스템은 모든 이벤트와 함께 원시 이벤트를 서버에 업로드 kube-apiserver와 통신하는 역할을 합니다 또한 서버에서 이벤트를 그렇게 하는 것이 훨씬 간단할 수도 있고, 이동 중에 받는 정보의 양을 업로드해야 합니다. ExoPlayer는 PlaybackStatsListener를 제공합니다. 를 사용하면 다음 처리 단계를 수행할 수 있습니다. <ph type="x-smartling-placeholder">
      </ph>
    1. 이벤트 해석: 분석 목적으로 유용하려면 단일 재생 컨텍스트에서 해석됩니다. 예를 들어 원시 플레이어 상태가 STATE_BUFFERING로 변경되는 이벤트는 탐색 후에 발생하는 초기 버퍼링, 리버퍼링 또는 버퍼링이 있을 수 있습니다.
    2. 상태 추적: 이 단계는 이벤트를 카운터로 변환합니다. 예를 들어 상태 변경 이벤트는 현재 상태와 남은 시간을 추적하는 카운터로 각 재생 상태에서 소비될 수 있습니다 그 결과 기본적인 분석 데이터 세트는 값을 설정할 수 있습니다.
    3. 집계: 이 단계에서는 여러 분석 데이터를 일반적으로 카운터를 더하는 방식으로 이루어집니다.
    4. 요약 측정항목 계산: 가장 유용한 측정항목 대부분은 평균을 계산하거나 기본 분석 데이터 값을 결합하는 사용할 수 있습니다 요약 측정항목은 하나 또는 여러 개를 기준으로 계산할 수 있습니다. 있습니다.

AnalyticsListener를 사용한 이벤트 수집

플레이어의 원시 재생 이벤트가 AnalyticsListener에 보고됩니다. 있습니다. 손쉽게 자체 리스너를 추가하고 관심 있는 방법:

Kotlin

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, currentMediaPeriodIdcurrentPlaybackPositionMs: 위와 같지만 현재 재생 중인 항목에 적용됩니다. 이 현재 재생 중인 항목은 이벤트가 재생된 항목과 다를 수 있습니다. 예를 들어 이벤트가 다음 있습니다.

PlaybackStatsListener를 통한 이벤트 처리

PlaybackStatsListener는 기기 내를 구현하는 AnalyticsListener입니다. 이벤트를 처리합니다. 카운터 및 파생 함수를 사용하여 PlaybackStats를 계산합니다. 측정항목:

  • 요약 측정항목(예: 총 재생 시간)
  • 적응형 재생 품질 측정항목(예: 평균 동영상 해상도)
  • 품질 측정항목 렌더링(예: 드롭된 프레임 속도)
  • 리소스 사용량 측정항목(예: 네트워크를 통해 읽은 바이트 수)

사용 가능한 개수 및 파생 측정항목의 전체 목록은 PlaybackStats Javadoc

PlaybackStatsListener는 각 미디어 항목에 대해 별도의 PlaybackStats를 계산합니다. 이러한 항목에 삽입된 각 클라이언트측 광고도 포함됩니다. 나 PlaybackStatsListener에 콜백을 제공하여 완료에 관해 알릴 수 있습니다. 콜백에 전달된 EventTime를 사용하여 재생이 완료됩니다. 여러 목적에 대해 애널리틱스 데이터를 집계하여 여러 번 재생할 수 있습니다 PlaybackStats에서 현재 재생 세션을 언제든지 PlaybackStatsListener.getPlaybackStats()입니다.

Kotlin

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 JOINING_BACKGROUND NOT_STARTED
활성 재생 PLAYING
재생 중단됨 SEEKING BUFFERING PAUSED, PAUSED_BUFFERING, SUPPRESSED, SUPPRESSED_BUFFERING, INTERRUPTED_BY_AD
종료 상태 ENDED, STOPPED, FAILED, ABANDONED

사용자가 플레이하고자 했던 시간을 구별하는 데 수동적 대기 시간에서 재생이 계속되기를 적극적으로 기다리는 중입니다. 예를 들어 PlaybackStats.getTotalWaitTimeMsJOINING_FOREGROUND, BUFFERING, SEEKING 상태이지만 시간이 재생이 일시중지되었습니다. 마찬가지로 PlaybackStats.getTotalPlayAndWaitTimeMs는 사용자가 플레이할 의도가 있는 전체 시간, 즉 총 활성 시간인 대기 시간 및 PLAYING 상태에서 소요된 총 시간입니다.

처리되고 해석된 이벤트

PlaybackStatsListener를 사용하여 처리 및 해석된 이벤트를 기록할 수 있습니다. keepHistory=true. 결과 PlaybackStats에는 다음이 포함됩니다. 이벤트 목록:

  • playbackStateHistory: 확장 재생 상태의 순서가 지정된 목록이며 적용하기 시작한 EventTime 또한 PlaybackStats.getPlaybackStateAtTime: 지정된 월에서 상태 조회 확인할 수 있습니다.
  • mediaTimeHistory: 벽시계 시간 및 미디어 시간 쌍의 기록을 통해 미디어의 어떤 부분이 언제 재생되었는지 재구성할 수 있습니다. 다음과 같은 작업을 할 수 있습니다. PlaybackStats.getMediaTimeMsAtRealtimeMs를 사용하여 재생을 찾습니다. 특정 벽시계 시간의 위치를 나타냅니다.
  • videoFormatHistoryaudioFormatHistory: 동영상 및 재생을 시작한 EventTime로 재생하는 동안 사용된 오디오 형식 있습니다.
  • fatalErrorHistorynonFatalErrorHistory: 심각한 문제 및 발생한 EventTime의 치명적이지 않은 오류를 반환합니다. 치명적인 오류는 치명적이지 않은 오류는 복구 가능할 수도 있습니다.

단일 재생 분석 데이터

이 데이터는 PlaybackStatsListener을(를) 사용하면 자동으로 수집됩니다. keepHistory=false. 최종 값은 PlaybackStats Javadoc에서 찾을 수 있으며, 재생 상태 지속 시간도 getPlaybackStateDurationMs에서 반환함 편의를 위해 getTotalPlayTimeMsgetTotalWaitTimeMs와 같은 메서드는 특정 재생 상태 조합의 지속 시간을 측정합니다.

Kotlin

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를 결합할 수 있습니다. PlaybackStats.merge입니다. 결과 PlaybackStats에는 집계된 데이터를 생성합니다. 포드의 이전 기록은 포함되지 않습니다. 집계할 수 없기 때문입니다.

PlaybackStatsListener.getCombinedPlaybackStats를 사용하면 전체 기간 동안 수집된 모든 애널리틱스 데이터를 PlaybackStatsListener입니다.

계산된 요약 측정항목

PlaybackStats는 기본 애널리틱스 데이터 외에도 다양한 메서드를 제공합니다. 요약 측정항목을 계산합니다.

Kotlin

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가 완료되었으므로 해당되는 분석 데이터:

Kotlin

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 인스턴스를 생성하고 이미 등록된 리스너에 전달합니다.

Kotlin

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()

Java

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();