ExoPlayer תומך במגוון רחב של צורכי ניתוח נתוני הפעלה. בסופו של דבר, ניתוח נתונים מבוסס על איסוף, פירוש, צבירה וסיכום של נתונים מההפעלות. ניתן להשתמש בנתונים האלה במכשיר – לדוגמה, רישום ביומן, ניפוי באגים או כדי לקבל החלטות עתידיות לגבי ההפעלה - או דיווח שרת למעקב אחר הפעלות בכל המכשירים.
בדרך כלל, מערכת ניתוח הנתונים צריכה לאסוף קודם אירועים ואז לעבד אותם כדי שיהיו משמעותיים:
- אוסף אירועים:
כדי לעשות זאת, אפשר לרשום
AnalyticsListener
ב-ExoPlayer
מכונה. מאזינים רשומים של Analytics מקבלים אירועים בזמן שהם מתרחשים במהלך בשימוש בנגן. כל אירוע משויך למדיה המתאימה פריט בפלייליסט, וגם את מיקום ההפעלה ואת המטא-נתונים של חותמת הזמן. - עיבוד אירועים:
חלק ממערכות ניתוח הנתונים מעלה אירועים גולמיים לשרת, כולל כל נתוני האירועים
מבוצע בצד השרת. אפשר גם לעבד אירועים
במכשיר, וכל זה עשוי להיות פשוט יותר או להפחית את כמות המידע
צריך להעלות את הקובץ. ExoPlayer מספק
PlaybackStatsListener
, מאפשרת לבצע את שלבי העיבוד הבאים:- פרשנות של אירועים: כדי להפיק תועלת מניתוח נתונים, אירועים צריכים
כדי שאפשר יהיה לפרש אותו בהקשר של הפעלה אחת. לדוגמה, המוצרים הגולמיים
אירוע של שינוי מצב נגן ל-
STATE_BUFFERING
עשוי להתאים אגירת נתונים ראשונית, מאגר נתונים זמני או אגירת נתונים שמתרחשת אחרי חיפוש. - מעקב אחרי מצב: השלב הזה ממיר אירועים למוניים. לדוגמה, ניתן להמיר אירועי שינוי מצב למוניים שעוקבים אחר משך הזמן שהיו פעילים בכל אחד ממצבי ההפעלה. התוצאה היא קבוצה בסיסית של נתוני ניתוח נתונים לערכים של הפעלה יחידה.
- צבירה: השלב הזה משלב את הנתונים של ניתוח הנתונים בדרך כלל על ידי הוספת מונה.
- חישוב מדדי הסיכום: רבים מהמדדים השימושיים ביותר הם שמחשבים ממוצעים או משלבים את הערכים הבסיסיים של ניתוח הנתונים בדרכים אחרות. ניתן לחשב מדדי סיכום עבור יחיד או עבור מספר מדדי סיכום והפעלות.
- פרשנות של אירועים: כדי להפיק תועלת מניתוח נתונים, אירועים צריכים
כדי שאפשר יהיה לפרש אותו בהקשר של הפעלה אחת. לדוגמה, המוצרים הגולמיים
אירוע של שינוי מצב נגן ל-
איסוף אירועים באמצעות 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, ) {} } )
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) {} });
ה-EventTime
שמועבר לכל קריאה חוזרת משייך את האירוע למדיה
של הפריט בפלייליסט, וגם את מיקום ההפעלה והמטא-נתונים של חותמת הזמן:
realtimeMs
: השעה בשעון הקיר של האירוע.timeline
,windowIndex
ו-mediaPeriodId
: מגדיר את הפלייליסט ואת פריט בפלייליסט שאליו האירוע שייך.mediaPeriodId
מכיל מידע אופציונלי נוסף, כמו ציון אם האירוע שייך למודעה בתוך הפריט.eventPlaybackPositionMs
: נקודת ההפעלה בפריט בזמן האירוע אירעה שגיאה.currentTimeline
,currentWindowIndex
,currentMediaPeriodId
וגםcurrentPlaybackPositionMs
: כמו למעלה, אבל לגבי הפריט שפועל כרגע. הפריט שמופעל כרגע עשוי להיות שונה מהפריט שבו האירוע שייך. לדוגמה, אם האירוע תואם לאגירת נתונים מראש של האירוע הבא הפריט להפעלה.
עיבוד אירועים באמצעות 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. } )
Java
exoPlayer.addAnalyticsListener( new PlaybackStatsListener( /* keepHistory= */ true, (eventTime, playbackStats) -> { // Analytics data for the session started at `eventTime` is ready. }));
ה-constructor של PlaybackStatsListener
מאפשר לשמור את כל
היסטוריה של אירועים שעובדו. הערה: הפעולות האלה עלולות לגרום לתקורה לא ידועה של הזיכרון
בהתאם למשך ההפעלה ולמספר האירועים. לכן אתם
צריך להפעיל אותה רק אם נדרשת גישה לכל ההיסטוריה של העיבוד
אירועים, במקום רק לנתוני הניתוח הסופיים.
חשוב לשים לב ש-PlaybackStats
משתמש בקבוצה מורחבת של מצבים כדי לציין לא רק
את מצב המדיה, אלא גם את כוונת המשתמש להפעיל ולהציג באופן מפורט יותר
כמו הסיבה להפסקה או לסיום של ההפעלה:
מצב ההפעלה | כוונת המשתמש לשחק | אין לי כוונה לשחק |
---|---|---|
לפני ההפעלה | JOINING_FOREGROUND |
NOT_STARTED , JOINING_BACKGROUND |
הפעלה פעילה | PLAYING |
|
ההפעלה נקטעת | BUFFERING , SEEKING |
PAUSED , PAUSED_BUFFERING , SUPPRESSED , SUPPRESSED_BUFFERING , INTERRUPTED_BY_AD |
מדינות (States) סיום | 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
שמחזירות את
משך הזמן של שילובים ספציפיים של מצבי הפעלה.
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);
ניתוח נתונים מצטברים של כמה הפעלות
אפשר לשלב כמה 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 )
Java
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. }
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. });
דיווח על אירועים בהתאמה אישית של ניתוח נתונים
אם צריך להוסיף אירועים מותאמים אישית לנתוני ניתוח הנתונים, צריך לשמור
את האירועים האלה במבנה הנתונים שלכם, ולשלב אותם עם הנתונים
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();