ExoPlayer obsługuje szeroki zakres potrzeb w zakresie analiz odtwarzania. Ostatecznie Analytics polega na gromadzeniu, interpretowaniu, agregowaniu i podsumowywaniu danych od odtworzeń. Tych danych można używać na urządzeniu, na przykład w przypadku: rejestrowania, debugowania ani na potrzeby podejmowania przyszłych decyzji dotyczących odtwarzania do monitorowania odtworzeń na wszystkich urządzeniach.
System analityczny zwykle najpierw musi zebrać zdarzenia, a potem je przetworzyć nadając im sens:
- Kolekcja zdarzeń:
Możesz to zrobić, rejestrując
AnalyticsListener
naExoPlayer
instancji. Zarejestrowani detektory statystyk odbierają zdarzenia w momencie, w którym występują korzystania z odtwarzacza. Każde zdarzenie jest powiązane z odpowiednimi multimediami pozycję na playliście, a także metadane pozycji odtwarzania i sygnatury czasowej. - Przetwarzanie zdarzeń:
Niektóre systemy analityczne przesyłają na serwer nieprzetworzone zdarzenia ze wszystkimi
po stronie serwera. Można również przetwarzać zdarzenia na
urządzeń, co może być prostsze lub zmniejszyć ilość informacji
musi zostać przesłany. ExoPlayer udostępnia pakiet
PlaybackStatsListener
, który umożliwia wykonanie tych czynności:- Interpretacja zdarzeń: aby zdarzenia były przydatne w celach analitycznych,
należy interpretować w kontekście pojedynczego odtworzenia. Na przykład surowe
zdarzenie zmiany stanu odtwarzacza na
STATE_BUFFERING
może odpowiadać początkowym buforowaniu, ponownym buforowaniu lub buforowaniu, które mają miejsce po wyszukiwaniu. - Śledzenie stanu: ten krok przekształca zdarzenia na liczniki. Przykład: zdarzenia zmiany stanu można przekonwertować na liczniki śledzące, w każdym stanie odtwarzania. W efekcie powstaje podstawowy zbiór danych analitycznych dla pojedynczego odtworzenia.
- Agregacja: ten krok łączy dane analityczne z różnych źródeł. do odtwarzania strumieniowego, zwykle przez zsumowanie liczników zdarzeń.
- Obliczanie danych podsumowujących: wiele najbardziej przydatnych danych to: które obliczają średnie lub łączą podstawowe wartości danych analitycznych w w inny sposób. Podsumowanie danych można obliczać dla pojedynczych lub wielu odtworzeniach.
- Interpretacja zdarzeń: aby zdarzenia były przydatne w celach analitycznych,
należy interpretować w kontekście pojedynczego odtworzenia. Na przykład surowe
zdarzenie zmiany stanu odtwarzacza na
Zbieranie zdarzeń za pomocą AnalyticsListener
Nieprzetworzone zdarzenia odtwarzania pochodzące z odtwarzacza są zgłaszane do AnalyticsListener
implementacji. Możesz łatwo dodać własnego detektora i zastąpić tylko
Interesujące Cię metody:
Kotlin
exoPlayer.addAnalyticsListener( object : AnalyticsListener { override fun onPlaybackStateChanged( eventTime: EventTime, @Player.State state: Int ) {} override fun onDroppedVideoFrames( eventTime: EventTime, droppedFrames: Int, elapsedMs: Long, ) {} } )
Java
exoPlayer.addAnalyticsListener( new AnalyticsListener() { @Override public void onPlaybackStateChanged( EventTime eventTime, @Player.State int state) {} @Override public void onDroppedVideoFrames( EventTime eventTime, int droppedFrames, long elapsedMs) {} });
Pole EventTime
przekazywane do każdego wywołania zwrotnego wiąże zdarzenie z mediami
elementu na playliście oraz metadanych pozycji odtwarzania i sygnatury czasowej:
realtimeMs
: zegar zegarowy zdarzenia.timeline
,windowIndex
imediaPeriodId
: definiuje playlistę oraz elementu playlisty, do której należy wydarzenie.mediaPeriodId
zawiera opcjonalne informacje dodatkowe, wskazujące na przykład, czy należy do reklamy w danym elemencie.eventPlaybackPositionMs
: pozycja odtwarzania w elemencie, gdy zdarzenie .currentTimeline
,currentWindowIndex
,currentMediaPeriodId
icurrentPlaybackPositionMs
: jak wyżej, ale z odtwarzanym elementem. obecnie odtwarzany element może się różnić od elementu, na którym jest powiązane zdarzenie na przykład gdy zdarzenie odpowiada wstępnemu buforowaniu kolejnego element, który ma zostać odtworzony.
Przetwarzanie zdarzeń za pomocą funkcji OdtwarzanieStatsListener
PlaybackStatsListener
to AnalyticsListener
, który implementuje na urządzeniu
Przetwarzanie zdarzeń. Oblicza ono wartość PlaybackStats
, korzystając z liczników i wyprowadzonych
dane, w tym:
- Dane podsumowujące, np. łączny czas odtwarzania.
- Wskaźniki jakości odtwarzania adaptacyjnego, np. średnia rozdzielczość wideo.
- dane o jakości renderowania, np. liczba pominiętych klatek.
- Wskaźniki wykorzystania zasobów, na przykład liczba bajtów odczytanych przez sieć.
Pełną listę dostępnych liczników i wygenerowanych danych znajdziesz w sekcji
PlaybackStats
Javadoc.
PlaybackStatsListener
oblicza osobne wartości PlaybackStats
dla każdego elementu multimedialnego
oraz wszystkich reklam po stronie klienta wstawionych do tych produktów. Ty
może oddzwonić do PlaybackStatsListener
, by otrzymać informację o zakończeniu
i użyj parametru EventTime
przekazanego do wywołania zwrotnego, aby określić,
Zakończono odtwarzanie. Możesz zagregować dane analityczne dotyczące:
wiele odtworzeń. Możesz też wysłać zapytanie do parametru PlaybackStats
, aby
bieżącej sesji odtwarzania w dowolnym momencie przy użyciu
PlaybackStatsListener.getPlaybackStats()
Kotlin
exoPlayer.addAnalyticsListener( PlaybackStatsListener(/* keepHistory= */ true) { eventTime: EventTime?, playbackStats: PlaybackStats?, -> // Analytics data for the session started at `eventTime` is ready. } )
Java
exoPlayer.addAnalyticsListener( new PlaybackStatsListener( /* keepHistory= */ true, (eventTime, playbackStats) -> { // Analytics data for the session started at `eventTime` is ready. }));
Konstruktor PlaybackStatsListener
umożliwia zachowanie pełnej
historii przetworzonych zdarzeń. Pamiętaj, że może to spowodować nieznane obciążenie pamięci.
w zależności od czasu trwania odtwarzania i liczby zdarzeń. Dlatego warto
należy włączać tylko wtedy, gdy potrzebujesz dostępu do pełnej historii przetworzonych plików
zdarzeń, a nie tylko
ostatecznych danych analitycznych.
Zwróć uwagę, że PlaybackStats
używa rozszerzonego zestawu stanów, aby wskazać, że nie tylko
od stanu multimediów, ale także od intencji użytkownika,
informacje o przyczynach przerwania lub zakończenia odtwarzania:
Stan odtwarzania | Zamiar użytkownika chcący zagrać | Brak zamiaru grania |
---|---|---|
Przed rozpoczęciem odtwarzania | JOINING_FOREGROUND |
NOT_STARTED , JOINING_BACKGROUND |
Aktywne odtwarzanie | PLAYING |
|
Odtwarzanie przerwane | BUFFERING , SEEKING |
PAUSED , PAUSED_BUFFERING , SUPPRESSED , SUPPRESSED_BUFFERING , INTERRUPTED_BY_AD |
Stany końcowe | ENDED , STOPPED , FAILED , ABANDONED |
Zamiar użytkownika, który chce zagrać, jest ważny, aby rozróżniać, kiedy użytkownik
aktywne oczekiwanie na kontynuowanie odtwarzania po pasywnym czasie oczekiwania. Przykład:
PlaybackStats.getTotalWaitTimeMs
zwraca łączny czas spędzony w
JOINING_FOREGROUND
, BUFFERING
i SEEKING
, ale nie czas, gdy
odtwarzanie zostało wstrzymane. Podobnie PlaybackStats.getTotalPlayAndWaitTimeMs
będzie
zwraca łączny czas gry z zamiarem użytkownika, czyli łączny czas
czas oczekiwania i łączny czas w stanie PLAYING
.
Przetworzone i zinterpretowane zdarzenia
Przetworzone i interpretowane zdarzenia możesz rejestrować za pomocą funkcji PlaybackStatsListener
dzięki keepHistory=true
. Wynikowa wartość PlaybackStats
będzie zawierać
te listy zdarzeń:
playbackStateHistory
: uporządkowana lista rozszerzonych stanów odtwarzania zawierające ciągEventTime
, w którym zaczęły obowiązywać. Możesz też użyćPlaybackStats.getPlaybackStateAtTime
, aby sprawdzić stan danej ściany na zegarze.mediaTimeHistory
: historia par zegarów ściennych i czasu multimediów, która umożliwia pozwala zrekonstruować fragmenty multimediów, które były odtwarzane w danym momencie. Dostępne opcje użyj teżPlaybackStats.getMediaTimeMsAtRealtimeMs
do wyszukania odtworzenia w określonym czasie.videoFormatHistory
iaudioFormatHistory
: uporządkowane listy filmów i formaty audio używane podczas odtwarzania na kontrolerze (EventTime
), od którego został on rozpoczęty do wykorzystania.fatalErrorHistory
inonFatalErrorHistory
: uporządkowane listy błędów krytycznych iEventTime
, na których wystąpiły błędy niekrytyczne. Błędy krytyczne: tych, które zakończyły odtwarzanie, podczas gdy niekrytyczne błędy da się naprawić.
Dane analityczne pojedynczego odtworzenia
Te dane są zbierane automatycznie, jeśli używasz PlaybackStatsListener
, nawet
dzięki keepHistory=false
. Wartości końcowe to pola publiczne, w których możesz
w PlaybackStats
Javadoc oraz czasie trwania stanu odtwarzania.
zwrócone przez getPlaybackStateDurationMs
. Dla wygody znajdziesz też
takie jak getTotalPlayTimeMs
i getTotalWaitTimeMs
, które zwracają
czas trwania określonych kombinacji stanu odtwarzania.
Kotlin
Log.d( "DEBUG", "Playback summary: " + "play time = " + playbackStats.totalPlayTimeMs + ", rebuffers = " + playbackStats.totalRebufferCount )
Java
Log.d( "DEBUG", "Playback summary: " + "play time = " + playbackStats.getTotalPlayTimeMs() + ", rebuffers = " + playbackStats.totalRebufferCount);
Zbiorcze dane analityczne dotyczące wielu odtworzeń
Możesz połączyć kilka PlaybackStats
, dzwoniąc
PlaybackStats.merge
Wynik PlaybackStats
będzie zawierać zagregowane wartości
danych wszystkich połączonych odtworzeń. Pamiętaj, że nie zawiera on historii
poszczególnych zdarzeń związanych z odtwarzaniem, bo nie można ich sumować.
PlaybackStatsListener.getCombinedPlaybackStats
może zostać użyte, aby uzyskać:
zagregowany widok wszystkich danych analitycznych zebranych od początku istnienia usługi
PlaybackStatsListener
Obliczone dane podsumowania
Oprócz podstawowych danych analitycznych PlaybackStats
udostępnia wiele metod
do obliczania danych podsumowujących.
Kotlin
Log.d( "DEBUG", "Additional calculated summary metrics: " + "average video bitrate = " + playbackStats.meanVideoFormatBitrate + ", mean time between rebuffers = " + playbackStats.meanTimeBetweenRebuffers )
Java
Log.d( "DEBUG", "Additional calculated summary metrics: " + "average video bitrate = " + playbackStats.getMeanVideoFormatBitrate() + ", mean time between rebuffers = " + playbackStats.getMeanTimeBetweenRebuffers());
Tematy zaawansowane
Powiązanie danych analitycznych z metadanymi odtwarzania
Podczas zbierania danych analitycznych o poszczególnych odtworzeniach możesz: kojarzyć dane statystyk odtwarzania z metadanymi dotyczącymi multimediów odtworzonej przez grę.
Zalecamy skonfigurowanie metadanych związanych z multimediami za pomocą parametru MediaItem.Builder.setTag
.
Tag mediów jest częścią elementu EventTime
, który jest raportowany w przypadku nieprzetworzonych zdarzeń oraz gdy
PlaybackStats
są już zakończone, więc można je łatwo pobrać podczas obsługi
odpowiadające im dane analityczne:
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. }
Java
new PlaybackStatsListener( /* keepHistory= */ false, (eventTime, playbackStats) -> { Object mediaTag = eventTime.timeline.getWindow(eventTime.windowIndex, new Timeline.Window()) .mediaItem .localConfiguration .tag; // Report playbackStats with mediaTag metadata. });
Raportowanie zdarzeń niestandardowych Analytics
Jeśli do danych analitycznych chcesz dodać zdarzenia niestandardowe, musisz zapisać plik
zdarzenia w Twojej strukturze danych i połącz je z raportowanymi
PlaybackStats
później. Jeśli to pomoże, możesz przedłużyć termin DefaultAnalyticsCollector
aby móc generować instancje EventTime
dla zdarzeń niestandardowych
do zarejestrowanych już detektorów, jak pokazano w przykładzie poniżej.
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();