@newrelic/video-core 4.1.7 → 4.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.LICENSE.txt +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.LICENSE.txt +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/umd/nrvideo.min.js +1 -1
- package/dist/umd/nrvideo.min.js.LICENSE.txt +1 -1
- package/dist/umd/nrvideo.min.js.map +1 -1
- package/package.json +1 -1
- package/src/videotracker.js +33 -16
- package/src/videotrackerstate.js +86 -12
package/package.json
CHANGED
package/src/videotracker.js
CHANGED
|
@@ -289,7 +289,7 @@ class VideoTracker extends Tracker {
|
|
|
289
289
|
* saving the current rendition and thus preventing interferences with RENDITION_CHANGE events.
|
|
290
290
|
*/
|
|
291
291
|
getRenditionShift(saveNewRendition) {
|
|
292
|
-
let current = this.
|
|
292
|
+
let current = this.getManifestBitrate();
|
|
293
293
|
let last;
|
|
294
294
|
if (this.isAd()) {
|
|
295
295
|
last = this._lastAdRendition;
|
|
@@ -544,26 +544,24 @@ class VideoTracker extends Tracker {
|
|
|
544
544
|
|
|
545
545
|
if(this.state.isStarted && !this.isAd()) {
|
|
546
546
|
this.state.trackContentBitrateState(att.contentBitrate);
|
|
547
|
+
this.state.trackDownloadRate(att.contentNetworkDownloadBitrate);
|
|
548
|
+
this.state.addPlayedRendition(att.contentRenditionHeight, att.contentRenditionWidth);
|
|
547
549
|
}
|
|
548
550
|
|
|
549
551
|
for (let key in this.customData) {
|
|
550
552
|
att[key] = this.customData[key];
|
|
551
553
|
}
|
|
552
554
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
this.addQoeAttributes(att);
|
|
557
|
-
|
|
558
|
-
return att;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
addQoeAttributes(att) {
|
|
562
|
-
att = this.state.getQoeAttributes(att);
|
|
555
|
+
// Add QOE v1.1 attributes (for content only, not ads)
|
|
556
|
+
if (!this.isAd()) {
|
|
557
|
+
this.state.getQoeAttributes(att);
|
|
563
558
|
const qoe = att.qoe;
|
|
564
559
|
for (let key in this.customData) {
|
|
565
|
-
|
|
560
|
+
qoe[key] = this.customData[key];
|
|
566
561
|
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return att;
|
|
567
565
|
}
|
|
568
566
|
|
|
569
567
|
/**
|
|
@@ -669,7 +667,10 @@ class VideoTracker extends Tracker {
|
|
|
669
667
|
ev = VideoTracker.Events.AD_END;
|
|
670
668
|
att.timeSinceAdRequested = this.state.timeSinceRequested.getDeltaTime();
|
|
671
669
|
att.timeSinceAdStarted = this.state.timeSinceStarted.getDeltaTime();
|
|
672
|
-
if (this.parentTracker)
|
|
670
|
+
if (this.parentTracker) {
|
|
671
|
+
this.parentTracker.state.isPlaying = true;
|
|
672
|
+
this.parentTracker.state.timeSincePaused.reset();
|
|
673
|
+
}
|
|
673
674
|
this.state.stopAdsTime();
|
|
674
675
|
} else {
|
|
675
676
|
ev = VideoTracker.Events.CONTENT_END;
|
|
@@ -713,8 +714,6 @@ class VideoTracker extends Tracker {
|
|
|
713
714
|
this.isAd()
|
|
714
715
|
? this.sendVideoAdAction(ev, att)
|
|
715
716
|
: this.sendVideoAction(ev, att);
|
|
716
|
-
|
|
717
|
-
//this.send(ev, att);
|
|
718
717
|
}
|
|
719
718
|
}
|
|
720
719
|
|
|
@@ -899,7 +898,25 @@ class VideoTracker extends Tracker {
|
|
|
899
898
|
att = att || {};
|
|
900
899
|
att.timeSinceLastRenditionChange =
|
|
901
900
|
this.state.timeSinceLastRenditionChange.getDeltaTime();
|
|
902
|
-
|
|
901
|
+
|
|
902
|
+
const {oldBitrate, newBitrate} = att;
|
|
903
|
+
|
|
904
|
+
if (!this.isAd() && oldBitrate !== undefined && newBitrate !== undefined) {
|
|
905
|
+
if (newBitrate > oldBitrate) {
|
|
906
|
+
att.shift = "up";
|
|
907
|
+
this.state.totalSwitchUps += 1;
|
|
908
|
+
} else if (newBitrate < oldBitrate) {
|
|
909
|
+
att.shift = "down";
|
|
910
|
+
this.state.totalSwitchDowns += 1;
|
|
911
|
+
} else {
|
|
912
|
+
att.shift = null;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// Remove internal tracking fields before sending to analytics
|
|
917
|
+
delete att.oldBitrate;
|
|
918
|
+
delete att.newBitrate;
|
|
919
|
+
|
|
903
920
|
let ev;
|
|
904
921
|
if (this.isAd()) {
|
|
905
922
|
ev = VideoTracker.Events.AD_RENDITION_CHANGE;
|
package/src/videotrackerstate.js
CHANGED
|
@@ -89,24 +89,45 @@ class VideoTrackerState {
|
|
|
89
89
|
this.peakBitrate = 0;
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
*
|
|
92
|
+
* Time-weighted bitrate calculation accumulators
|
|
93
93
|
*/
|
|
94
|
+
this.partialAverageBitrate = 0;
|
|
95
|
+
this._totalBitrateDuration = 0;
|
|
96
|
+
this.weightedBitrate = 0;
|
|
94
97
|
this._lastBitrate = null;
|
|
98
|
+
this._lastBitrateChangeTimestamp = null;
|
|
95
99
|
|
|
96
100
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
|
|
101
|
+
* Array of changed network download bitrate values (only values that differ from previous).
|
|
102
|
+
* Used for calculating simple mean, min, max (not time-weighted).
|
|
103
|
+
*/
|
|
104
|
+
this._downloadBitrates = [];
|
|
100
105
|
|
|
101
106
|
/**
|
|
102
|
-
*
|
|
107
|
+
* Previous download bitrate value to detect changes.
|
|
103
108
|
*/
|
|
104
|
-
this.
|
|
109
|
+
this._lastDownloadBitrate = null;
|
|
105
110
|
|
|
106
111
|
/**
|
|
107
|
-
* Total
|
|
112
|
+
* QOE v1.1: Total number of rendition/quality switches where bitrate increased.
|
|
108
113
|
*/
|
|
109
|
-
this.
|
|
114
|
+
this.totalSwitchUps = 0;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* QOE v1.1: Total number of rendition/quality switches where bitrate decreased.
|
|
118
|
+
*/
|
|
119
|
+
this.totalSwitchDowns = 0;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* QOE v1.1: Total time in milliseconds spent in paused state (intentional pauses only).
|
|
123
|
+
* Calculated from timeSincePaused chrono accumulation.
|
|
124
|
+
*/
|
|
125
|
+
this.totalPauseTime = 0;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* QOE v1.1: Set of distinct renditions played, keyed by "heightxwidth" (e.g., "1080x1920").
|
|
129
|
+
*/
|
|
130
|
+
this._playedRenditions = new Set();
|
|
110
131
|
|
|
111
132
|
/**
|
|
112
133
|
* Had Startup Error: TRUE if CONTENT_ERROR occurs before CONTENT_START.
|
|
@@ -352,7 +373,7 @@ class VideoTrackerState {
|
|
|
352
373
|
const kpi = {};
|
|
353
374
|
|
|
354
375
|
try {
|
|
355
|
-
// QoE KPIs
|
|
376
|
+
// QoE v1 KPIs
|
|
356
377
|
if (this.startupTime !== null) {
|
|
357
378
|
kpi["startupTime"] = this.startupTime;
|
|
358
379
|
}
|
|
@@ -362,13 +383,35 @@ class VideoTrackerState {
|
|
|
362
383
|
kpi["hadStartupError"] = this.hadStartupError;
|
|
363
384
|
kpi["hadPlaybackError"] = this.hadPlaybackError;
|
|
364
385
|
kpi["totalRebufferingTime"] = this.totalRebufferingTime;
|
|
365
|
-
// Calculate rebuffering ratio as percentage (avoid division by zero)
|
|
366
386
|
kpi["rebufferingRatio"] = this.totalPlaytime > 0
|
|
367
387
|
? (this.totalRebufferingTime / this.totalPlaytime) * 100
|
|
368
388
|
: 0;
|
|
369
389
|
kpi["totalPlaytime"] = this.totalPlaytime;
|
|
370
390
|
kpi["averageBitrate"] = this.weightedBitrate;
|
|
371
391
|
kpi["numberOfErrors"] = this.numberOfErrors;
|
|
392
|
+
|
|
393
|
+
// QoE v1.1 KPIs - Download rate (simple mean of changed values)
|
|
394
|
+
if (this._downloadBitrates.length > 0) {
|
|
395
|
+
const sum = this._downloadBitrates.reduce((a, b) => a + b, 0);
|
|
396
|
+
kpi["avgDownloadRate"] = Math.round(sum / this._downloadBitrates.length);
|
|
397
|
+
kpi["minDownloadRate"] = Math.min(...this._downloadBitrates);
|
|
398
|
+
kpi["maxDownloadRate"] = Math.max(...this._downloadBitrates);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// QoE v1.1 KPIs - Rendition switching
|
|
402
|
+
kpi["totalSwitchUps"] = this.totalSwitchUps;
|
|
403
|
+
kpi["totalSwitchDowns"] = this.totalSwitchDowns;
|
|
404
|
+
|
|
405
|
+
// QoE v1.1 KPIs - Pause and session timing
|
|
406
|
+
kpi["totalPauseTime"] = this.timeSincePaused.getDuration();
|
|
407
|
+
kpi["totalViewSessionTime"] = this.totalPlaytime;
|
|
408
|
+
|
|
409
|
+
// QoE v1.1 KPIs - Renditions
|
|
410
|
+
kpi["totalRenditions"] = this._playedRenditions.size;
|
|
411
|
+
|
|
412
|
+
// Version tag
|
|
413
|
+
kpi["qoeAggregateVersion"] = "1.1.0";
|
|
414
|
+
|
|
372
415
|
} catch (error) {
|
|
373
416
|
Log.error("Failed to add attributes for QOE KPIs", error.message);
|
|
374
417
|
}
|
|
@@ -696,7 +739,7 @@ class VideoTrackerState {
|
|
|
696
739
|
}
|
|
697
740
|
|
|
698
741
|
/**
|
|
699
|
-
* Updates peak bitrate
|
|
742
|
+
* Updates peak bitrate and time-weighted average bitrate (content only).
|
|
700
743
|
* @param {number} bitrate Current content bitrate in bps.
|
|
701
744
|
*/
|
|
702
745
|
trackContentBitrateState(bitrate) {
|
|
@@ -757,16 +800,47 @@ class VideoTrackerState {
|
|
|
757
800
|
}
|
|
758
801
|
}
|
|
759
802
|
|
|
803
|
+
/**
|
|
804
|
+
* Records network download bitrate observation. Only tracks values that differ from previous.
|
|
805
|
+
* @param {number} bps Network throughput in bits per second.
|
|
806
|
+
*/
|
|
807
|
+
trackDownloadRate(bps) {
|
|
808
|
+
if (!bps || typeof bps !== "number" || bps <= 0) return;
|
|
809
|
+
if (bps !== this._lastDownloadBitrate) {
|
|
810
|
+
this._downloadBitrates.push(bps);
|
|
811
|
+
this._lastDownloadBitrate = bps;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Records a rendition play event (height x width combination).
|
|
817
|
+
* @param {number} height Rendition height in pixels.
|
|
818
|
+
* @param {number} width Rendition width in pixels.
|
|
819
|
+
*/
|
|
820
|
+
addPlayedRendition(height, width) {
|
|
821
|
+
if (height && width) {
|
|
822
|
+
this._playedRenditions.add(`${height}x${width}`);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
|
|
760
827
|
/**
|
|
761
828
|
* Resets tracked variable for view id change
|
|
762
829
|
* */
|
|
763
830
|
resetViewIdTrackedState() {
|
|
764
831
|
this.peakBitrate = 0;
|
|
832
|
+
this.startupTime = null;
|
|
765
833
|
this.partialAverageBitrate = 0;
|
|
766
834
|
this._totalBitrateDuration = 0;
|
|
767
|
-
this.
|
|
835
|
+
this.weightedBitrate = 0;
|
|
768
836
|
this._lastBitrate = null;
|
|
769
837
|
this._lastBitrateChangeTimestamp = null;
|
|
838
|
+
this._downloadBitrates = [];
|
|
839
|
+
this._lastDownloadBitrate = null;
|
|
840
|
+
this.totalSwitchUps = 0;
|
|
841
|
+
this.totalSwitchDowns = 0;
|
|
842
|
+
this.timeSincePaused.reset();
|
|
843
|
+
this._playedRenditions = new Set();
|
|
770
844
|
}
|
|
771
845
|
|
|
772
846
|
/** Methods to manage total ads time chrono */
|