@newrelic/video-core 5.0.0 → 5.0.1

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/CHANGELOG.md CHANGED
@@ -1,6 +1,62 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [5.0.1](https://github.com/newrelic/video-core-js/compare/v5.0.0...v5.0.1) (2026-08-05)
5
+
6
+ ### Bug Fixes
7
+ * Add JP region support for Vega
8
+
9
+ ## [5.0.0] - 2026/07/28
10
+
11
+ ### Feat
12
+
13
+ - **Vega (Connected Device) monitoring support**
14
+ Introduced a full Vega / connected-device analytics pipeline alongside the existing browser one. Adds `ConnectedDeviceHarvester` (`/v5/connect` + `/v3/data`), a `VegaAnalyticsAgent` singleton that mirrors `VideoAnalyticsAgent`, and a `ConnectedDeviceAgent` entry-point. Source routing is driven by a new `options.src` field: trackers that pass `src: 'Vega'` are dispatched to the Vega harvester; all others continue using the browser harvester unchanged.
15
+
16
+ - **Japan (JP) region collector endpoint**
17
+ Added `JP: "bam.jp.nr-data.net"` to `Constants.COLLECTOR` so applications targeting Japanese accounts can route to the correct regional collector.
18
+
19
+
20
+ ### Fix
21
+
22
+ - **GOV (FedRAMP) endpoint for connected-device harvester**
23
+ Added `MOBILE_ENDPOINT_GOV` (`gov-mobile-collector.newrelic.com`) and a `GOV` key to `NR_ENDPOINT` in `connectedDeviceConstants.js`, supporting US government accounts.
24
+
25
+ - **QoE enabled by default for connected-device agent**
26
+ `qoeAggregate` now defaults to `true` in `videoConfiguration.js`, matching the browser-side default set in v4.1.7.
27
+
28
+ - **Obfuscation applied to connected-device payloads**
29
+ Obfuscation rules are now enforced on harvest payloads sent by the connected-device harvester, keeping behaviour consistent with the browser harvester.
30
+
31
+ - **Connect retry capped at 3 attempts**
32
+ The `/v5/connect` exponential-backoff retry loop in `ConnectedDeviceHarvester` is now limited to `CD_CONNECT_MAX_ATTEMPTS` (3), preventing runaway retries on persistent failures.
33
+
34
+ - **Ad src routing**
35
+ Ad events now correctly propagate `att.src` through the tracker chain so they are dispatched to the right harvester.
36
+
37
+ ## [4.1.8] - 2026/07/07
38
+
39
+ ### Feat
40
+
41
+ - **New download QoE metrics**
42
+ Added download-throughput KPIs to `VideoTrackerState`: tracks bytes received and elapsed time per segment download to derive a per-session download bitrate signal for QoE reporting.
43
+
44
+ - **Additional QoE attributes**
45
+ Extended `videotrackerstate.js` and `videotracker.js` with new per-session QoE attributes (`weightedBitrate`, min/max bitrate, segment count, and related accumulators) emitted alongside existing QoE aggregate events.
46
+
47
+ ### Fix
48
+
49
+ - **Exclude mid-roll ad pause time from `timeSincePaused`**
50
+ When an ad ends and control returns to content, `parentTracker.state.timeSincePaused` is now reset so that the pause time accumulated during the ad break is not incorrectly attributed to a subsequent content pause.
51
+
52
+ - **Initialize `weightedBitrate` to `0` in `VideoTrackerState`**
53
+ `weightedBitrate` is now explicitly set to `0` in both the constructor and `resetValues()`, preventing `undefined` from being emitted as an attribute value before the first bitrate sample arrives.
54
+
55
+ ### Refactor
56
+
57
+ - **Inline `WeightedAverage` helper**
58
+ Removed the standalone `WeightedAverage.js` module and folded the time-weighted average logic directly into `trackContentBitrateState` in `videotrackerstate.js`, reducing indirection without changing behaviour.
59
+
4
60
  ## [4.1.7] - 2026/06/11
5
61
 
6
62
  ### Changed
@@ -1,3 +1,3 @@
1
1
  /*! For license information please see index.js.LICENSE.txt */
2
- (()=>{"use strict";const t={d:(e,i)=>{if(Array.isArray(i))for(var s=0;s<i.length;){var r=i[s++],a=i[s++];t.o(e,r)?0===a&&s++:0===a?Object.defineProperty(e,r,{enumerable:!0,value:i[s++]}):Object.defineProperty(e,r,{enumerable:!0,get:a})}else for(var r in i)t.o(i,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:i[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}};let e={};t.r(e),t.d(e,{Chrono:()=>u,Constants:()=>h,Core:()=>w,Emitter:()=>l,HarvestScheduler:()=>q,Log:()=>n,NrVideoEventAggregator:()=>P,OptimizedHttpClient:()=>F,RetryQueueHandler:()=>H,Tracker:()=>m,VideoTracker:()=>C,VideoTrackerState:()=>D,default:()=>M,getRegisteredHarvester:()=>p,recordEvent:()=>v,version:()=>d.rE,videoAnalyticsHarvester:()=>G});class i{static error(...t){s(t,i.Levels.ERROR,"darkred")}static warn(...t){s(t,i.Levels.WARNING,"darkorange")}static notice(...t){s([].slice.call(arguments),i.Levels.NOTICE,"darkcyan")}static debug(...t){s(t,i.Levels.DEBUG,"indigo")}static debugCommonVideoEvents(t,e,s){try{if(i.level<=i.Levels.DEBUG){s=s||function(t){i.debug("Event: "+t.type)};var r=["canplay","buffering","waiting","ended","play","playing","pause","resume","error","abort","seek","seeking","seeked","stalled","dispose","loadeddata","loadstart","loadedmetadata"];e&&(null===e[0]?(e.shift(),r=e):r=r.concat(e));for(var a=0;a<r.length;a++)"function"==typeof t?t.call(window,r[a],s):t.on?t.on(r[a],s):t.addEventListener?t.addEventListener(r[a],s):t.addEventHandler?t.addEventHandler(r[a],s):i.warn("debugCommonVideoEvents: No common listener function found for ",t)}}catch(t){i.warn(t)}}}function s(t,e,s){e=e||i.Levels.NOTICE,s=s||"darkcyan";var n,o,h,d,l,c,u=i.prefix;(i.includeTime&&(u+=(n=new Date,o=("0"+n.getDate()).slice(-2),h=("0"+n.getMinutes()).slice(-2),d=("0"+n.getSeconds()).slice(-2),l=("00"+n.getMilliseconds()).slice(-3),"["+o+":"+h+":"+d+"."+l+"] ")),u+=function(t){return a[t]}(e)+":",i.level<=e&&e!==i.Levels.SILENT)&&(!i.colorful||"undefined"!=typeof document&&document.documentMode?r(t,u):(c=e===i.Levels.ERROR&&console.error?console.error:e===i.Levels.WARNING&&console.warn?console.warn:e===i.Levels.DEBUG&&console.debug&&null==window.cast?console.debug:console.log,u="%c"+u,t.splice(0,0,u,"color: "+s),c.apply(console,t)))}function r(t,e){if(t instanceof Array)for(var i in t)r(t[i],e);else"string"==typeof t?console.log(e+" "+t):(console.log(e+"↵"),console.log(t))}i.Levels={SILENT:5,ERROR:4,WARNING:3,NOTICE:2,DEBUG:1,ALL:0},i.level=i.Levels.ERROR,i.colorful=!0,i.includeTime=!0,i.prefix="[nrvideo]";const a={4:"e",3:"w",2:"n",1:"d"};!function(){if("undefined"!=typeof window&&window.location&&window.location.search){var t=/\?.*&*nrvideo-debug=(.+)/i.exec(window.location.search);null!==t&&("true"===t[1]?i.level=i.Levels.ALL:i.level=t[1]),null!==/\?.*&*nrvideo-colors=false/i.exec(window.location.search)&&(i.colorful=!1)}}();const n=i;class o{}o.AdPositions={PRE:"pre",MID:"mid",POST:"post"},o.COLLECTOR={US:["bam.nr-data.net","bam-cell.nr-data.net"],EU:"bam.eu01.nr-data.net",JP:"bam.jp.nr-data.net",Staging:"staging-bam-cell.nr-data.net",GOV:"gov-bam.nr-data.net"},o.VALID_EVENT_TYPES=["VideoAction","VideoAdAction","VideoErrorAction","VideoCustomAction"],o.MAX_PAYLOAD_SIZE=1048576,o.MAX_BEACON_SIZE=61440,o.MAX_EVENTS_PER_BATCH=1e3,o.INTERVAL=1e4,o.DEFAULT_QOE_INTERVAL_FACTOR=2,o.QOE_KPI_KEYS=["startupTime","peakBitrate","averageBitrate","totalPlaytime","totalRebufferingTime","rebufferingRatio","hadStartupError","hadPlaybackError","numberOfErrors"],o.QOE_AGGREGATE_KEYS=["coreVersion","instrumentation.name","instrumentation.provider","instrumentation.version","isBackgroundEvent","playerName","playerVersion","src","viewId","viewSession","contentIsAutoplayed","contentIsMuted","contentRenditionHeight","contentRenditionWidth","contentSrc","numberOfVideos","pageUrl","trackerName","trackerVersion","contentDuration","contentPlayrate","contentPlayhead","contentPreload","elapsedTime","contentTitle","contentId","contentIsLive","deviceType","deviceGroup","deviceManufacturer","deviceModel","deviceName","deviceSize","deviceUuid","contentRenditionName","contentIsFullscreen","contentCdn","contentFps","asnOrganization","asnLongitude","asnLatitude","asn","timeSinceRequested","timeSinceStarted"];const h=o,d={rE:"5.0.0"};const l=class{on(t,e){if(this._listeners=this._listeners||{},"function"==typeof e)return this._listeners[t]=this._listeners[t]||[],this._listeners[t].push(e),this}off(t,e){if(this._listeners=this._listeners||{},this._listeners[t]){var i=this._listeners[t].indexOf(e);-1!==i&&this._listeners[t].splice(i,1)}return this}emit(t,e,i){return this._listeners=this._listeners||{},i=i||{},Array.isArray(this._listeners[e])&&this._listeners[e].forEach(s=>{s.call(this,{eventType:t,type:e,data:i,target:this})}),Array.isArray(this._listeners["*"])&&this._listeners["*"].forEach(s=>{s.call(this,{eventType:t,type:e,data:i,target:this})}),this}};class c{constructor(){this.reset()}reset(){this.startTime=0,this.stopTime=0,this.accumulator=0,this.offset=0}getDeltaTime(){return this.startTime?this.offset+((new Date).getTime()-this.startTime):null}start(){this.startTime=(new Date).getTime(),this.stopTime=0}stop(){return this.stopTime=(new Date).getTime(),this.startTime<this.stopTime&&(this.accumulator+=this.stopTime-this.startTime),this.getDeltaTime()}getDuration(){return this.stopTime?this.accumulator+this.offset:this.accumulator+(this.getDeltaTime()??0)}clone(){var t=new c;return t.startTime=this.startTime,t.stopTime=this.stopTime,t.offset=this.offset,t.accumulator=this.accumulator,t}}const u=c;class g extends l{constructor(t){super(),this.customData={},this.heartbeat=null,this.parentTracker=null,this._trackerReadyChrono=new u,this._trackerReadyChrono.start(),this._actionTable=h.ACTION_TABLE,this._actionAdTable=h.ACTION_AD_TABLE,t=t||{},this.setOptions(t)}setOptions(t){t&&(t.parentTracker&&(this.parentTracker=t.parentTracker),t.customData&&(this.customData=t.customData),t.heartbeat&&(this.heartbeat=t.heartbeat))}dispose(){this.unregisterListeners()}registerListeners(){}unregisterListeners(){}getHeartbeat(){return this.state._isAd?2e3:this.heartbeat?this.heartbeat:this.parentTracker&&this.parentTracker.heartbeat?this.parentTracker.heartbeat:3e4}startHeartbeat(){this._heartbeatInterval=setInterval(this.sendHeartbeat.bind(this),Math.max(this.getHeartbeat(),2e3))}stopHeartbeat(){this._heartbeatInterval&&clearInterval(this._heartbeatInterval)}sendHeartbeat(t){this.sendVideoAction(g.Events.HEARTBEAT,t)}getAttributes(t,e){(t=t||{}).trackerName=this.getTrackerName(),t.trackerVersion=this.getTrackerVersion(),t.coreVersion=d.rE,t.timeSinceTrackerReady=this._trackerReadyChrono.getDeltaTime();for(let e in this.customData)t[e]=this.customData[e];return null!=document.hidden&&(t.isBackgroundEvent=document.hidden),t}getTrackerVersion(){return d.rE}getTrackerName(){return"base-tracker"}sendVideoAction(t,e){this.emit("VideoAction",t,this.getAttributes(e))}sendVideoAdAction(t,e){this.emit("VideoAdAction",t,this.getAttributes(e))}sendVideoErrorAction(t,e){let i=this.isAd()?"adError":"videoError";this.emit("VideoErrorAction",t,this.getAttributes(e,i))}sendVideoCustomAction(t,e){this.emit("VideoCustomAction",t,this.getAttributes(e,"customAction"))}setHarvestInterval(t){const e=this.getHarvester?.();if(e)try{e.setHarvestInterval(t)}catch(t){return void n.error("Failed to set harvest interval:",t.message)}else n.error("Tracker has no harvester; setHarvestInterval ignored")}getHarvester(){return null}}g.Events={HEARTBEAT:"HEARTBEAT",QOE_AGGREGATE:"QOE_AGGREGATE"};const m=g;function f(t){try{return JSON.stringify(t,(()=>{const t=new WeakSet;return(e,i)=>{if("object"==typeof i&&null!==i){if(t.has(i))return;t.add(i)}return i}})())??""}catch(t){return n.error("Error stringifying value:",t.message),""}}function E(t){if("string"==typeof t&&t.length)return t.length;if("object"==typeof t){if("undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer&&t.byteLength)return t.byteLength;if("undefined"!=typeof Blob&&t instanceof Blob&&t.size)return t.size;if(!("undefined"!=typeof FormData&&t instanceof FormData))try{return f(t).length}catch(t){return}}}function A(t,e,i,{addTimeSinceLoad:s=!1}={}){const{appName:r,applicationID:a}=i,{qoe:n,...o}=e,d=n?{...n}:{},l={...a?{}:{appName:r},timestamp:Date.now(),...s?{timeSinceLoad:"undefined"!=typeof window&&window.performance?window.performance.now()/1e3:null}:{}},c={...o,eventType:t,...l};let u=null;if("VideoAction"===t){const t=(g=h.QOE_AGGREGATE_KEYS,f=e,g&&Array.isArray(g)&&0!==g.length?f&&"object"==typeof f?g.reduce((t,e)=>(e in f&&(t[e]=f[e]),t),{}):{}:f);u={eventType:"VideoAction",actionName:m.Events.QOE_AGGREGATE,qoeAggregateVersion:"1.0.0",...d,...t,...l}}var g,f;return{eventObject:c,qoeEventObject:u}}const T=Object.create(null);function p(t){return T[t]}function v(t,e={}){try{if(!h.VALID_EVENT_TYPES.includes(t))return n.warn("Invalid event type provided to recordEvent",{eventType:t}),!1;const i="Vega"===e.src,s=i?"Vega":"Browser",r="undefined"!=typeof window?window:void 0,a=i?globalThis.__NRVIDEO_CD__?.info:r?.NRVIDEO?.info;if(!a)return;const o=T[s];if(!o)return n.warn("No harvester registered for routing key",{routingKey:s}),!1;return function(t,e,i,s,r,{addTimeSinceLoad:a=!1}={}){if(!s)return!1;const{eventObject:n,qoeEventObject:o}=A(t,e,i,{addTimeSinceLoad:a}),h=s.addEvent(n);return o&&r?h&&s.addEvent(o):h}(t,e,a,o,i?globalThis.__NRVIDEO_CD__?.config?.qoeAggregate:r?.NRVIDEO?.config?.qoeAggregate,{addTimeSinceLoad:!i})}catch(t){return n.error("Failed to record event:",t.message),!1}}const{COLLECTOR:S}=h;class y{setConfiguration(t,e,i){return!!("Vega"===i?this.validateVegaFields(t):this.validateRequiredFields(t))&&(!!this.validateConfigFields(e)&&(this.initializeGlobalConfig(t,e,i),n.notice("Video analytics configuration initialized successfully"),!0))}validateVegaFields(t){return t&&"object"==typeof t?t.applicationToken?!!["US","EU","staging","GOV"].includes(t.endpoint)||(n.error("Invalid endpoint (must be US, EU, staging, or GOV)"),!1):(n.error("applicationToken is required"),!1):(n.error("Configuration must be an object"),!1)}validateRequiredFields(t){if(!t||"object"!=typeof t)return n.error("Configuration must be an object"),!1;const{licenseKey:e,appName:i,region:s,applicationID:r,beacon:a}=t;if(!e)return n.error("licenseKey is required"),!1;if(r){if(!a)return n.error("beacon is required when applicationID is provided"),!1;if(!Object.values(S).flatMap(t=>t).includes(a))return n.error(`Invalid beacon: ${a}`),!1}else{if(!i||!s)return n.error("appName and region are required when applicationID is not provided"),!1;if(!S[s])return n.error(`Invalid region: ${s}. Valid regions are: ${Object.keys(S).join(", ")}`),!1}return!0}validateConfigFields(t){if(null==t)return!0;if("object"!=typeof t||Array.isArray(t))return n.error("config must be an object"),!1;const{qoeAggregate:e,obfuscate:i}=t;return void 0!==e&&"boolean"!=typeof e?(n.error("qoeAggregate must be a boolean"),!1):!(void 0!==i&&!Array.isArray(i))||(n.error("obfuscate must be an array"),!1)}filterObfuscateRules(t){return t?t.filter(t=>{const e=void 0!==t.regex&&("string"==typeof t.regex||t.regex instanceof RegExp),i=void 0!==t.replacement&&"string"==typeof t.replacement;return!(!e||!i)||(n.warn("obfuscate rule missing required 'regex' (string|RegExp) and/or 'replacement' (string), skipping:",t),!1)}):[]}sanitizeQoeIntervalFactor(t){return null==t?h.DEFAULT_QOE_INTERVAL_FACTOR:"number"==typeof t&&Number.isInteger(t)&&t>=1?t:(n.warn(`Invalid qoeIntervalFactor "${t}" — must be a positive integer. Defaulting to ${h.DEFAULT_QOE_INTERVAL_FACTOR}.`),h.DEFAULT_QOE_INTERVAL_FACTOR)}initializeGlobalConfig(t,e,i){if("Vega"===i)return void(globalThis.__NRVIDEO_CD__={info:{accountId:t.accountId,applicationToken:t.applicationToken,endpoint:t.endpoint,...t.appName?{appName:t.appName}:{},...t.applicationID?{applicationID:t.applicationID}:{},...t.deviceInfo?{deviceInfo:t.deviceInfo}:{}},config:{qoeAggregate:e?.qoeAggregate??!0,qoeIntervalFactor:this.sanitizeQoeIntervalFactor(e?.qoeIntervalFactor),obfuscate:this.filterObfuscateRules(e?.obfuscate)}});let{licenseKey:s,appName:r,region:a,beacon:n,applicationID:o}=t;n="US"===a?h.COLLECTOR.US[0]:n||S[a],window.NRVIDEO={info:{...a?{region:a}:{},beacon:n,licenseKey:s,applicationID:o,...o?{}:{appName:r}},config:{qoeAggregate:e?.qoeAggregate??!0,qoeIntervalFactor:this.sanitizeQoeIntervalFactor(e?.qoeIntervalFactor),obfuscate:this.filterObfuscateRules(e?.obfuscate)}}}}const _=new y;class R{static addTracker(t,e){var i,s,r;e?.info&&(i=e.info,s=e?.config,r=e?.src,_.setConfiguration(i,s,r)),t.on&&t.emit?(B.push(t),t.on("*",b),"function"==typeof t.trackerInit&&t.trackerInit()):n.error("Tried to load a non-tracker.",t)}static removeTracker(t){t.off("*",b),t.dispose();let e=B.indexOf(t);-1!==e&&B.splice(e,1)}static getTrackers(){return B}static send(t,e,i){return v(t,{actionName:e,...i})}static sendError(t){return v("VideoErrorAction",{actionName:"ERROR",...t})}}let B=[];function b(t){try{let e=function(t){let e={};for(let i in t)null!==t[i]&&void 0!==t[i]&&(e[i]=t[i]);return e}(t.data);n.level<=n.Levels.DEBUG?n.notice("Sent",t.type,e):n.notice("Sent",t.type),R.send(t.eventType,t.type,e)}catch(t){n.error("Error in event handler:",t.message)}}const w=R;const D=class{constructor(){this.reset(),this._createdAt=Date.now(),this._hb=!0,this._acc=0,this._bufferAcc=0}reset(){this._viewSession=null,this._viewCount=0,this._isAd=!1,this.numberOfErrors=0,this.numberOfAds=0,this.numberOfVideos=0,this.totalPlaytime=0,this.weightedAverageBitrate=0,this.totalAdPlaytime=0,this.isAdBreak=!1,this.initialBufferingHappened=!1,this.startupTime=null,this.peakBitrate=0,this.partialAverageBitrate=0,this._totalBitrateDuration=0,this.weightedBitrate=0,this._lastBitrate=null,this._lastBitrateChangeTimestamp=null,this._downloadBitrates=[],this._lastDownloadBitrate=null,this.totalSwitchUps=0,this.totalSwitchDowns=0,this.totalPauseTime=0,this._playedRenditions=new Set,this.hadStartupError=!1,this.hadPlaybackError=!1,this.totalRebufferingTime=0,this.resetFlags(),this.resetChronos()}resetFlags(){this.isPlayerReady=!1,this.isRequested=!1,this.isStarted=!1,this.isPaused=!1,this.isSeeking=!1,this.isBuffering=!1,this.isPlaying=!1}resetChronos(){this.timeSinceRequested=new u,this.timeSinceStarted=new u,this.timeSincePaused=new u,this.timeSinceSeekBegin=new u,this.timeSinceBufferBegin=new u,this.timeSinceAdBreakStart=new u,this.timeSinceLastDownload=new u,this.timeSinceLastHeartbeat=new u,this.timeSinceLastRenditionChange=new u,this.timeSinceLastAdQuartile=new u,this.timeSinceLastAd=new u,this.timeSinceLastError=new u,this.timeSinceLastAdError=new u,this.timeSinceResumed=new u,this.timeSinceSeekEnd=new u,this.playtimeSinceLastEvent=new u,this.customTimeSinceAttributes={},this.elapsedTime=new u,this.bufferElapsedTime=new u,this._totalAdPlaytime=new u}isAd(){return this._isAd}setIsAd(t){this._isAd=t}setTimeSinceAttribute(t){this.customTimeSinceAttributes[t]=new u,this.customTimeSinceAttributes[t].start()}removeTimeSinceAttribute(t){delete this.customTimeSinceAttributes[t]}getViewSession(){if(!this._viewSession){let t=(new Date).getTime(),e=Math.random().toString(36).substring(2)+Math.random().toString(36).substring(2);this._viewSession=t+"-"+e}return this._viewSession}getViewId(){return this.getViewSession()+"-"+this._viewCount}getStateAttributes(t){t=t||{},this.isAd()?(this.isRequested&&(t.timeSinceAdRequested=this.timeSinceRequested.getDeltaTime(),t.timeSinceLastAdHeartbeat=this.timeSinceLastHeartbeat.getDeltaTime()),this.isStarted&&(t.timeSinceAdStarted=this.timeSinceStarted.getDeltaTime()),this.isPaused&&(t.timeSinceAdPaused=this.timeSincePaused.getDeltaTime()),this.isBuffering&&(t.timeSinceAdBufferBegin=this.timeSinceBufferBegin.getDeltaTime()),this.isSeeking&&(t.timeSinceAdSeekBegin=this.timeSinceSeekBegin.getDeltaTime()),this.isAdBreak&&(t.timeSinceAdBreakBegin=this.timeSinceAdBreakStart.getDeltaTime()),this.numberOfErrors>0&&this.timeSinceLastAdError.startTime>0&&(t.timeSinceLastAdError=this.timeSinceLastAdError.getDeltaTime()),t.numberOfAds=this.numberOfAds):(this.isRequested&&(t.timeSinceRequested=this.timeSinceRequested.getDeltaTime(),t.timeSinceLastHeartbeat=this.timeSinceLastHeartbeat.getDeltaTime()),this.isStarted&&(t.timeSinceStarted=this.timeSinceStarted.getDeltaTime()),this.isPaused&&(t.timeSincePaused=this.timeSincePaused.getDeltaTime()),this.isBuffering&&(t.timeSinceBufferBegin=this.timeSinceBufferBegin.getDeltaTime()),this.isSeeking&&(t.timeSinceSeekBegin=this.timeSinceSeekBegin.getDeltaTime()),t.timeSinceLastAd=this.timeSinceLastAd.getDeltaTime(),this.numberOfErrors>0&&this.timeSinceLastError.startTime>0&&(t.timeSinceLastError=this.timeSinceLastError.getDeltaTime()),t.numberOfVideos=this.numberOfVideos),t.numberOfErrors=this.numberOfErrors,this.isAd()||(this.playtimeSinceLastEvent.startTime>0?t.playtimeSinceLastEvent=this.playtimeSinceLastEvent.getDeltaTime():t.playtimeSinceLastEvent=0,this.isPlaying?this.playtimeSinceLastEvent.start():this.playtimeSinceLastEvent.reset(),this.totalPlaytime+=t.playtimeSinceLastEvent,t.totalPlaytime=this.totalPlaytime);for(const[e,i]of Object.entries(this.customTimeSinceAttributes))t[e]=i.getDeltaTime();return t}getQoeAttributes(t){t=t||{};const e={};try{if(null!==this.startupTime&&(e.startupTime=this.startupTime),this.peakBitrate>0&&(e.peakBitrate=this.peakBitrate),e.hadStartupError=this.hadStartupError,e.hadPlaybackError=this.hadPlaybackError,e.totalRebufferingTime=this.totalRebufferingTime,e.rebufferingRatio=this.totalPlaytime>0?this.totalRebufferingTime/this.totalPlaytime*100:0,e.totalPlaytime=this.totalPlaytime,e.averageBitrate=this.weightedBitrate,e.numberOfErrors=this.numberOfErrors,this._downloadBitrates.length>0){const t=this._downloadBitrates.reduce((t,e)=>t+e,0);e.avgDownloadRate=Math.round(t/this._downloadBitrates.length),e.minDownloadRate=Math.min(...this._downloadBitrates),e.maxDownloadRate=Math.max(...this._downloadBitrates)}e.totalSwitchUps=this.totalSwitchUps,e.totalSwitchDowns=this.totalSwitchDowns,e.totalPauseTime=this.timeSincePaused.getDuration(),e.totalViewSessionTime=this.totalPlaytime,e.totalRenditions=this._playedRenditions.size,e.qoeAggregateVersion="1.1.0"}catch(t){n.error("Failed to add attributes for QOE KPIs",t.message)}return t.qoe=e,t}calculateBufferType(t){let e="";return e=t?"initial":this.isSeeking?"seek":this.isPaused?"pause":"connection",n.debug("Buffer Type = "+e),e}goViewCountUp(){this._viewCount++}goPlayerReady(){return!this.isPlayerReady&&(this.isPlayerReady=!0,!0)}goRequest(){return!this.isRequested&&(this.isRequested=!0,this.timeSinceLastAd.reset(),this.timeSinceRequested.start(),!0)}goStart(){return!(!this.isRequested||this.isStarted)&&(this.isAd()?this.numberOfAds++:this.numberOfVideos++,this.isStarted=!0,this.isPlaying=!0,this.timeSinceStarted.start(),this.playtimeSinceLastEvent.start(),!0)}goEnd(){return!!this.isRequested&&(this.numberOfErrors=0,this.resetFlags(),this.timeSinceRequested.stop(),this.timeSinceStarted.stop(),this.playtimeSinceLastEvent.stop(),this.isPlaying=!1,!0)}goPause(){return!(!this.isStarted||this.isPaused)&&(this.isPaused=!0,this.isPlaying=!1,this.timeSincePaused.start(),this.playtimeSinceLastEvent.stop(),this.timeSinceResumed.reset(),this.isBuffering&&(this._bufferAcc+=this.bufferElapsedTime.getDeltaTime()),this.elapsedTime.start(),!0)}goResume(){return!(!this.isStarted||!this.isPaused)&&(this.isPaused=!1,this.isPlaying=!0,this.timeSincePaused.stop(),this.timeSinceResumed.start(),this._hb?(this._acc=this.elapsedTime.getDeltaTime(),this._hb=!1):(this.isBuffering&&this.bufferElapsedTime.start(),this._acc+=this.elapsedTime.getDeltaTime()),!0)}goBufferStart(){return!(!this.isRequested||this.isBuffering)&&(this.isBuffering=!0,this.isPlaying=!1,this.timeSinceBufferBegin.start(),this.bufferElapsedTime.start(),!0)}goBufferEnd(){return!(!this.isRequested||!this.isBuffering)&&(this.isBuffering=!1,this.isPlaying=!0,this.timeSinceBufferBegin.stop(),this._hb?(this._bufferAcc=this.bufferElapsedTime.getDeltaTime(),this._hb=!1):this._bufferAcc+=this.bufferElapsedTime.getDeltaTime(),!this.isAd()&&this.initialBufferingHappened&&(this.totalRebufferingTime+=this.timeSinceBufferBegin.stopTime-this.timeSinceBufferBegin.startTime),!0)}goSeekStart(){return!(!this.isStarted||this.isSeeking)&&(this.isSeeking=!0,this.isPlaying=!1,this.timeSinceSeekBegin.start(),this.timeSinceSeekEnd.reset(),!0)}goSeekEnd(){return!(!this.isStarted||!this.isSeeking)&&(this.isSeeking=!1,this.isPlaying=!0,this.timeSinceSeekBegin.stop(),this.timeSinceSeekEnd.start(),!0)}goAdBreakStart(){return!this.isAdBreak&&(this.isAdBreak=!0,this.timeSinceAdBreakStart.start(),!0)}goAdBreakEnd(){return!!this.isAdBreak&&(this.isRequested=!1,this.isAdBreak=!1,this.totalAdPlaytime=this.timeSinceAdBreakStart.getDeltaTime(),this.timeSinceAdBreakStart.stop(),!0)}goDownload(){this.timeSinceLastDownload.start()}goHeartbeat(){this.timeSinceLastHeartbeat.start()}goRenditionChange(){this.timeSinceLastRenditionChange.start()}goAdQuartile(){this.timeSinceLastAdQuartile.start()}goError(){this.isError=!0,this.numberOfErrors++,this.isAd()?this.timeSinceLastAdError.start():(this.timeSinceLastError.start(),this.isStarted?this.hadPlaybackError=!0:this.hadStartupError=!0)}goLastAd(){this.timeSinceLastAd.start()}trackContentBitrateState(t){if(t&&"number"==typeof t){this.peakBitrate=Math.max(this.peakBitrate,t);const e=Date.now();if(!this.isPlaying){if(null!==this._lastBitrate&&null!==this._lastBitrateChangeTimestamp){const t=e-this._lastBitrateChangeTimestamp;t>0&&(this.partialAverageBitrate+=this._lastBitrate*t,this._totalBitrateDuration+=t),this._lastBitrateChangeTimestamp=null}return void(this._lastBitrate=t)}if(null===this._lastBitrateChangeTimestamp&&null!==this._lastBitrate&&(this._lastBitrateChangeTimestamp=e),null!==this._lastBitrate&&this._lastBitrate!==t&&null!==this._lastBitrateChangeTimestamp){const t=e-this._lastBitrateChangeTimestamp;t>0&&(this.partialAverageBitrate+=this._lastBitrate*t,this._totalBitrateDuration+=t),this._lastBitrateChangeTimestamp=e}null===this._lastBitrateChangeTimestamp&&(this._lastBitrateChangeTimestamp=e),this._lastBitrate=t;let i=this.partialAverageBitrate,s=this._totalBitrateDuration;const r=e-this._lastBitrateChangeTimestamp;r>0&&(i+=t*r,s+=r),this.weightedBitrate=s>0?Math.round(i/s):t}}trackDownloadRate(t){!t||"number"!=typeof t||t<=0||t!==this._lastDownloadBitrate&&(this._downloadBitrates.push(t),this._lastDownloadBitrate=t)}addPlayedRendition(t,e){t&&e&&this._playedRenditions.add(`${t}x${e}`)}resetViewIdTrackedState(){this.peakBitrate=0,this.startupTime=null,this.partialAverageBitrate=0,this._totalBitrateDuration=0,this.weightedBitrate=0,this._lastBitrate=null,this._lastBitrateChangeTimestamp=null,this._downloadBitrates=[],this._lastDownloadBitrate=null,this.totalSwitchUps=0,this.totalSwitchDowns=0,this.timeSincePaused.reset(),this._playedRenditions=new Set}clearTotalAdsTime(){n.debug("clear total ads time",this.totalAdTime),this._totalAdPlaytime.reset()}totalAdTime(){return this._totalAdPlaytime.getDuration()}startAdsTime(){return n.debug("startAdsTime"),this._totalAdPlaytime.start()}stopAdsTime(){return n.debug("stopAdsTime"),this._totalAdPlaytime.stop()}setStartupTime(t){null===this.startupTime&&(this.startupTime=Math.max(this.timeSinceRequested.getDeltaTime()-t,0))}};class k extends m{constructor(t,e){super(),this.state=new D,this.adsTracker=null,this._lastBufferType=null,this._userId=null,this._src=null,e=e||{},this.setOptions(e),t&&this.setPlayer(t,e.tag),n.notice("Tracker "+this.getTrackerName()+" v"+this.getTrackerVersion()+" is ready.")}setUserId(t){this._userId=t}setOptions(t){t&&(t.adsTracker&&this.setAdsTracker(t.adsTracker),"boolean"==typeof t.isAd&&this.setIsAd(t.isAd),void 0!==t.src&&(null!==this._src&&this._src!==t.src?n.warn(`setOptions: src is locked to '${this._src}'. Ignoring override '${t.src}'.`):(this._src=t.src,this.adsTracker&&null==this.adsTracker._src&&(this.adsTracker._src=this._src))),m.prototype.setOptions.apply(this,arguments))}setPlayer(t,e){(this.player||this.tag)&&this.dispose(),"undefined"!=typeof document&&document.getElementById&&("string"==typeof t&&(t=document.getElementById(t)),"string"==typeof e&&(e=document.getElementById(e))),e=e||t,this.player=t,this.tag=e,this.registerListeners()}isAd(){return this.state.isAd()}setIsAd(t){this.state.setIsAd(t)}setAdsTracker(t){this.disposeAdsTracker(),t&&(this.adsTracker=t,this.adsTracker.setIsAd(!0),this.adsTracker.parentTracker=this,null!=this._src&&null==t._src&&(t._src=this._src),this.adsTracker.on("*",N.bind(this)))}disposeAdsTracker(){this.adsTracker&&(this.adsTracker.off("*",N),this.adsTracker.dispose())}dispose(){this.stopHeartbeat(),this.disposeAdsTracker(),this.unregisterListeners(),this.player=null,this.tag=null}registerListeners(){}unregisterListeners(){}getViewId(){return this.parentTracker?this.parentTracker.getViewId():this.state.getViewId()}getViewSession(){return this.parentTracker?this.parentTracker.getViewSession():this.state.getViewSession()}getVideoId(){return null}getTitle(){return null}isLive(){return null}getBitrate(){return null}getManifestBitrate(){return null}getSegmentDownloadBitrate(){return null}getNetworkDownloadBitrate(){return null}getWebkitBitrate(){if(this.tag&&this.tag.webkitVideoDecodedByteCount){let t;if(this._lastWebkitBitrate){t=this.tag.webkitVideoDecodedByteCount;let e=t-this._lastWebkitBitrate,i=this.getHeartbeat()/1e3;t=Math.round(e/i*8)}return this._lastWebkitBitrate=this.tag.webkitVideoDecodedByteCount,t||null}}getRenditionName(){return null}getRenditionBitrate(){return null}getRenditionShift(t){let e,i=this.getManifestBitrate();return this.isAd()?(e=this._lastAdRendition,t&&(this._lastAdRendition=i)):(e=this._lastRendition,t&&(this._lastRendition=i)),i&&e?i>e?"up":i<e?"down":null:null}getRenditionHeight(){return this.tag?this.tag.videoHeight:null}getRenditionWidth(){return this.tag?this.tag.videoWidth:null}getDuration(){return this.tag?this.tag.duration:null}getPlayhead(){return this.tag?this.tag.currentTime:null}getLanguage(){return null}getSrc(){return this.tag?this.tag.currentSrc:null}getPlayrate(){return this.tag?this.tag.playbackRate:null}isMuted(){return this.tag?this.tag.muted:null}isFullscreen(){return null}getCdn(){return null}getPlayerName(){return this.getTrackerName()}getPlayerVersion(){return d.rE}getFps(){return null}isAutoplayed(){return this.tag?this.tag.autoplay:null}getPreload(){return this.tag?this.tag.preload:null}getAdQuartile(){return null}getAdPosition(){return this.parentTracker?this.parentTracker.state.isStarted?"mid":"pre":null}getAdPartner(){return null}getAdCreativeId(){return null}getInstrumentationProvider(){return null}getInstrumentationName(){return null}getInstrumentationVersion(){return null}getAttributes(t,e){if(void 0===(t=m.prototype.getAttributes.apply(this,arguments)).isAd&&(t.isAd=this.isAd()),t.viewSession=this.getViewSession(),t.viewId=this.getViewId(),t.playerName=this.getPlayerName(),t.playerVersion=this.getPlayerVersion(),t["instrumentation.provider"]=this.getInstrumentationProvider(),t["instrumentation.name"]=this.getInstrumentationName(),t["instrumentation.version"]=this.getInstrumentationVersion(),t["enduser.id"]=this._userId,t.src=this._src||"Browser","customAction"===e)return t;try{t.pageUrl=window.location.href}catch(t){}this.isAd()?(t.adId=this.getVideoId(),t.adTitle=this.getTitle(),t.adSrc=this.getSrc(),t.adCdn=this.getCdn(),this.state.isStarted&&(t.adBitrate=this.getBitrate()||0),t.adRenditionName=this.getRenditionName(),t.adRenditionHeight=this.getRenditionHeight(),t.adRenditionWidth=this.getRenditionWidth(),t.adDuration=this.getDuration(),t.adPlayhead=this.getPlayhead(),t.adLanguage=this.getLanguage(),t.adIsMuted=this.isMuted(),t.adFps=this.getFps(),t.adPosition=this.getAdPosition(),t.adCreativeId=this.getAdCreativeId(),t.adPartner=this.getAdPartner()):(t.contentId=this.getVideoId(),t.contentTitle=this.getTitle(),t.contentSrc=this.getSrc(),t.contentCdn=this.getCdn(),t.contentPlayhead=this.getPlayhead(),t.contentIsLive=this.isLive(),this.state.isStarted&&(t.contentBitrate=this.getBitrate()||0,t.contentManifestBitrate=this.getManifestBitrate()||0,t.contentSegmentDownloadBitrate=this.getSegmentDownloadBitrate()||0,t.contentNetworkDownloadBitrate=this.getNetworkDownloadBitrate()||0),t.contentRenditionName=this.getRenditionName(),t.contentRenditionHeight=this.getRenditionHeight(),t.contentRenditionWidth=this.getRenditionWidth(),t.contentDuration=this.getDuration(),t.contentLanguage=this.getLanguage(),t.contentPlayrate=this.getPlayrate(),t.contentIsFullscreen=this.isFullscreen(),t.contentIsMuted=this.isMuted(),t.contentIsAutoplayed=this.isAutoplayed(),t.contentPreload=this.getPreload(),t.contentFps=this.getFps(),null!=this.adsTracker&&this.adsTracker.state.totalAdPlaytime>0&&(t.totalAdPlaytime=this.adsTracker.state.totalAdPlaytime)),this.state.getStateAttributes(t),this.state.isStarted&&!this.isAd()&&(this.state.trackContentBitrateState(t.contentBitrate),this.state.trackDownloadRate(t.contentNetworkDownloadBitrate),this.state.addPlayedRendition(t.contentRenditionHeight,t.contentRenditionWidth));for(let e in this.customData)t[e]=this.customData[e];if(!this.isAd()){this.state.getQoeAttributes(t);const e=t.qoe;for(let t in this.customData)e[t]=this.customData[t]}return t}sendCustom(t,e,i){i=i||{},this.sendVideoCustomAction(t,i),this.state.setTimeSinceAttribute(e)}sendPlayerReady(t){this.state.goPlayerReady()&&(t=t||{},this.sendVideoAction(k.Events.PLAYER_READY,t))}sendRequest(t){if(this.state.goRequest()){let e;this.isAd()?(e=k.Events.AD_REQUEST,this.sendVideoAdAction(e,t)):(e=k.Events.CONTENT_REQUEST,this.sendVideoAction(e,t))}}sendStart(t){if(this.state.goStart()){let e;if(this.isAd())e=k.Events.AD_START,this.parentTracker&&(this.parentTracker.state.isPlaying=!1),this.sendVideoAdAction(e,t),this.state.startAdsTime();else{e=k.Events.CONTENT_START;let i=0;this.adsTracker&&((this.adsTracker.state.isPlaying||this.adsTracker.state.isBuffering)&&(this.adsTracker.state.stopAdsTime(),this.adsTracker.state.isPlaying=!1,this.adsTracker.state.isBuffering=!1),i=this.adsTracker.state.totalAdTime()??0),this.state.setStartupTime(i),this.sendVideoAction(e,t);const s=this.getHarvester?.();s?.setBeforeDrainCallback(()=>{if(this.state){const t=this.state.getQoeAttributes({}).qoe;s.refreshQoeKpis(t,this.getViewId())}})}this.startHeartbeat(),this.state.goHeartbeat()}}sendEnd(t){if(this.state.goEnd()){let e;if(t=t||{},this.isAd()?(e=k.Events.AD_END,t.timeSinceAdRequested=this.state.timeSinceRequested.getDeltaTime(),t.timeSinceAdStarted=this.state.timeSinceStarted.getDeltaTime(),this.parentTracker&&(this.parentTracker.state.isPlaying=!0,this.parentTracker.state.timeSincePaused.reset()),this.state.stopAdsTime()):(e=k.Events.CONTENT_END,t.timeSinceRequested=this.state.timeSinceRequested.getDeltaTime(),t.timeSinceStarted=this.state.timeSinceStarted.getDeltaTime()),this.stopHeartbeat(),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t),this.parentTracker&&this.isAd()&&this.parentTracker.state.goLastAd(),this.state.goViewCountUp(),this.state.totalPlaytime=0,!this.isAd()){const t=this.getHarvester?.();t?.forceNextQoeCycle?.(),t?.setBeforeDrainCallback?.(null),this.adsTracker&&this.adsTracker.state.clearTotalAdsTime(),this.state.resetViewIdTrackedState()}}}sendPause(t){if(this.state.goPause()){let e=this.isAd()?k.Events.AD_PAUSE:k.Events.CONTENT_PAUSE;this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendResume(t){if(this.state.goResume()){let e;t=t||{},this.isAd()?(e=k.Events.AD_RESUME,t.timeSinceAdPaused=this.state.timeSincePaused.getDeltaTime()):(e=k.Events.CONTENT_RESUME,t.timeSincePaused=this.state.timeSincePaused.getDeltaTime()),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendBufferStart(t){if(this.state.goBufferStart()){let e;t=t||{},e=this.isAd()?k.Events.AD_BUFFER_START:k.Events.CONTENT_BUFFER_START,t=this.buildBufferAttributes(t),this._lastBufferType=t.bufferType,this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendBufferEnd(t){if(this.state.goBufferEnd()){let e;t=t||{},this.isAd()?(e=k.Events.AD_BUFFER_END,t.timeSinceAdBufferBegin=this.state.timeSinceBufferBegin.getDeltaTime()):(e=k.Events.CONTENT_BUFFER_END,t.timeSinceBufferBegin=this.state.timeSinceBufferBegin.getDeltaTime()),t=this.buildBufferAttributes(t),null!=this._lastBufferType&&(t.bufferType=this._lastBufferType),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t),this.state.initialBufferingHappened=!0}}buildBufferAttributes(t){return null==t.timeSinceStarted||t.timeSinceStarted<100?t.isInitialBuffering=!this.state.initialBufferingHappened:t.isInitialBuffering=!1,t.bufferType=this.state.calculateBufferType(t.isInitialBuffering),t.timeSinceResumed=this.state.timeSinceResumed.getDeltaTime(),t.timeSinceSeekEnd=this.state.timeSinceSeekEnd.getDeltaTime(),t}sendSeekStart(t){if(this.state.goSeekStart()){let e;e=this.isAd()?k.Events.AD_SEEK_START:k.Events.CONTENT_SEEK_START,this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendSeekEnd(t){if(this.state.goSeekEnd()){let e;t=t||{},this.isAd()?(e=k.Events.AD_SEEK_END,t.timeSinceAdSeekBegin=this.state.timeSinceSeekBegin.getDeltaTime()):(e=k.Events.CONTENT_SEEK_END,t.timeSinceSeekBegin=this.state.timeSinceSeekBegin.getDeltaTime()),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendDownload(t){(t=t||{}).state||n.warn("Called sendDownload without { state: xxxxx }."),this.sendVideoAction(k.Events.DOWNLOAD,t),this.state.goDownload()}sendError(t){(t=t||{}).isAd=this.isAd(),this.state.goError();let e=this.isAd()?k.Events.AD_ERROR:k.Events.CONTENT_ERROR;this.sendVideoErrorAction(e,t)}sendRenditionChanged(t){(t=t||{}).timeSinceLastRenditionChange=this.state.timeSinceLastRenditionChange.getDeltaTime();const{oldBitrate:e,newBitrate:i}=t;let s;this.isAd()||void 0===e||void 0===i||(i>e?(t.shift="up",this.state.totalSwitchUps+=1):i<e?(t.shift="down",this.state.totalSwitchDowns+=1):t.shift=null),delete t.oldBitrate,delete t.newBitrate,s=this.isAd()?k.Events.AD_RENDITION_CHANGE:k.Events.CONTENT_RENDITION_CHANGE,this.isAd()?this.sendVideoAdAction(s,t):this.sendVideoAction(s,t),this.state.goRenditionChange()}sendHeartbeat(t){if(this.state.isRequested){let e,i=this.getHeartbeat();this.state._hb=!0,i=this.adjustElapsedTimeForPause(i),this.isAd()?(e=k.Events.AD_HEARTBEAT,"bitmovin-ads"===this.getPlayerName()?this.sendVideoAdAction(e,t):this.sendVideoAdAction(e,{elapsedTime:i,...t})):(e=k.Events.CONTENT_HEARTBEAT,this.sendVideoAction(e,{elapsedTime:i,...t})),this.state.goHeartbeat()}}adjustElapsedTimeForPause(t){return this.state._acc&&(t-=this.state._acc,this.state._acc=0),this.state.isPaused&&((t-=this.state.elapsedTime.getDeltaTime())<10&&(t=0),this.state.elapsedTime.start()),this.state._bufferAcc?(t-=this.state._bufferAcc,this.state._bufferAcc=0):this.state.isBuffering&&((t-=this.state.bufferElapsedTime.getDeltaTime())<5&&(t=0),this.state.bufferElapsedTime.start()),Math.max(0,t)}sendAdBreakStart(t){this.isAd()&&this.state.goAdBreakStart()&&(this.state.totalAdPlaytime=0,this.parentTracker&&(this.parentTracker.state.isPlaying=!1),this.sendVideoAdAction(k.Events.AD_BREAK_START,t))}sendAdBreakEnd(t){this.isAd()&&this.state.goAdBreakEnd()&&((t=t||{}).timeSinceAdBreakBegin=this.state.timeSinceAdBreakStart.getDeltaTime(),this.sendVideoAdAction(k.Events.AD_BREAK_END,t),this.parentTracker&&(this.parentTracker.state.isPlaying=!0),this.stopHeartbeat(),this.parentTracker&&this.isAd()&&this.parentTracker.state.goLastAd())}sendAdQuartile(t){this.isAd()&&((t=t||{}).quartile||n.warn("Called sendAdQuartile without { quartile: xxxxx }."),t.timeSinceLastAdQuartile=this.state.timeSinceLastAdQuartile.getDeltaTime(),this.sendVideoAdAction(k.Events.AD_QUARTILE,t),this.state.goAdQuartile())}sendAdClick(t){this.isAd()&&((t=t||{}).url||n.warn("Called sendAdClick without { url: xxxxx }."),this.sendVideoAdAction(k.Events.AD_CLICK,t))}}function N(t){t.type!==k.Events.AD_ERROR?this.sendVideoAdAction(t.type,t.data):this.sendVideoErrorAction(t.type,t.data)}k.Events={PLAYER_READY:"PLAYER_READY",DOWNLOAD:"DOWNLOAD",ERROR:"ERROR",CONTENT_REQUEST:"CONTENT_REQUEST",CONTENT_START:"CONTENT_START",CONTENT_END:"CONTENT_END",CONTENT_PAUSE:"CONTENT_PAUSE",CONTENT_RESUME:"CONTENT_RESUME",CONTENT_SEEK_START:"CONTENT_SEEK_START",CONTENT_SEEK_END:"CONTENT_SEEK_END",CONTENT_BUFFER_START:"CONTENT_BUFFER_START",CONTENT_BUFFER_END:"CONTENT_BUFFER_END",CONTENT_HEARTBEAT:"CONTENT_HEARTBEAT",CONTENT_RENDITION_CHANGE:"CONTENT_RENDITION_CHANGE",CONTENT_ERROR:"CONTENT_ERROR",AD_REQUEST:"AD_REQUEST",AD_START:"AD_START",AD_END:"AD_END",AD_PAUSE:"AD_PAUSE",AD_RESUME:"AD_RESUME",AD_SEEK_START:"AD_SEEK_START",AD_SEEK_END:"AD_SEEK_END",AD_BUFFER_START:"AD_BUFFER_START",AD_BUFFER_END:"AD_BUFFER_END",AD_HEARTBEAT:"AD_HEARTBEAT",AD_RENDITION_CHANGE:"AD_RENDITION_CHANGE",AD_ERROR:"AD_ERROR",AD_BREAK_START:"AD_BREAK_START",AD_BREAK_END:"AD_BREAK_END",AD_QUARTILE:"AD_QUARTILE",AD_CLICK:"AD_CLICK"};const C=k,{MAX_PAYLOAD_SIZE:O,MAX_EVENTS_PER_BATCH:I}=h;class P{constructor(){this.buffer=[],this.maxPayloadSize=O,this.maxEventsPerBatch=I,this.currentPayloadSize=0,this.totalEvents=0,this.smartHarvestPayloadThreshold=Math.floor(.6*this.maxPayloadSize),this.overflowPayloadThreshold=Math.floor(.9*this.maxPayloadSize),this.smartHarvestEventThreshold=Math.floor(.6*this.maxEventsPerBatch),this.overflowEventThreshold=Math.floor(.9*this.maxEventsPerBatch),this.onSmartHarvestTrigger=null}addOrReplaceByActionName(t,e){const i=this.buffer.findIndex(e=>e.actionName===t);try{return-1===i?this.add(e):this.add(e,i),!0}catch(t){return n.error("Failed to set or replace the event to buffer:",t.message),!1}}addOrReplaceByActionNameAndViewId(t,e,i){const s=this.buffer.findIndex(i=>i.actionName===t&&i.viewId===e);try{return-1===s?this.add(i):this.add(i,s),!0}catch(t){return n.error("Failed to set or replace the event to buffer:",t.message),!1}}findByActionNameAndViewId(t,e){return this.buffer.find(i=>i.actionName===t&&i.viewId===e)||null}findByActionName(t){return this.buffer.find(e=>e.actionName===t)||null}add(t,e){try{const i=E(t),s=this.currentPayloadSize+i>=this.maxPayloadSize,r=this.totalEvents+1>=this.maxEventsPerBatch;if((s||r)&&this.makeRoom(i),null!=e&&e>-1){const s=E(this.buffer[e]);this.buffer[e]=t,this.currentPayloadSize+=i-s}else this.buffer.push(t),this.totalEvents++,this.currentPayloadSize+=i;return this.checkSmartHarvestTrigger(),!0}catch(t){return n.error("Failed to add event to buffer:",t.message),!1}}checkSmartHarvestTrigger(){const t=this.currentPayloadSize/this.maxPayloadSize,e=this.totalEvents/this.maxEventsPerBatch,i=this.currentPayloadSize>=this.overflowPayloadThreshold,s=this.totalEvents>=this.overflowEventThreshold;if(i||s){const s=i?`payload ${this.currentPayloadSize}/${this.maxPayloadSize} bytes (${Math.round(100*t)}%)`:`events ${this.totalEvents}/${this.maxEventsPerBatch} (${Math.round(100*e)}%)`;n.warn(`OVERFLOW PREVENTION: ${s} - Emergency harvest triggered`),this.onSmartHarvestTrigger&&"function"==typeof this.onSmartHarvestTrigger&&this.onSmartHarvestTrigger("overflow",90)}else{const t=this.currentPayloadSize>=this.smartHarvestPayloadThreshold,e=this.totalEvents>=this.smartHarvestEventThreshold;(t||e)&&this.onSmartHarvestTrigger&&"function"==typeof this.onSmartHarvestTrigger&&this.onSmartHarvestTrigger("smart",60)}}setSmartHarvestCallback(t){this.onSmartHarvestTrigger=t}drain(){try{const t=this.buffer.splice(0);return this.totalEvents=0,this.currentPayloadSize=0,t}catch(t){return n.error("Failed to drain events from buffer:",t.message),[]}}isEmpty(){return 0===this.totalEvents}size(){return this.totalEvents}clear(){this.buffer=[],this.totalEvents=0}makeRoom(t){if(t>this.maxPayloadSize)n.error("Event dropped: Event size exceeds maximum payload size.");else for(;(this.totalEvents>=this.maxEventsPerBatch||this.currentPayloadSize+t>=this.maxPayloadSize)&&this.buffer.length>0;){const t=E(this.buffer.shift());this.totalEvents--,this.currentPayloadSize-=t,n.warn("Event buffer full, oldest event removed.")}}}const{MAX_PAYLOAD_SIZE:V,MAX_EVENTS_PER_BATCH:L}=h;class H{constructor(){this.retryQueue=[],this.maxQueueSize=L,this.maxQueueSizeBytes=V}addFailedEvents(t){try{const e=Array.isArray(t)?t:[t];n.notice(`Adding ${e.length} failed events to retry queue`,{queueSizeBefore:this.retryQueue.length});for(const t of e){this.retryQueue.length>=this.maxQueueSize&&this.evictOldestEvent();const e=E(t);for(;E(this.retryQueue)+e>this.maxQueueSizeBytes;)this.evictOldestEvent();this.retryQueue.push({...t})}}catch(t){n.error("Failed to add events to retry queue:",t.message)}}discardEvent(t,e){n.warn("Discarded event",{reason:e,eventType:t.eventType})}evictOldestEvent(){if(this.retryQueue.length>0){const t=this.retryQueue.shift();this.discardEvent(t,"Queue full - evicted oldest")}}getRetryEventsToFit(t,e){const i=[];let s=0,r=0;for(let a=this.retryQueue.length-1;a>=0;a--){const n=this.retryQueue[a];if(r>=e)break;const o=E(n);if(s+o>t)break;i.unshift(n),s+=o,r++,this.retryQueue.splice(a,1)}return i}getQueueSize(){return this.retryQueue.length}clear(){this.retryQueue=[]}}class F{async send(t,e){const{url:i,payload:s,options:r={}}=t;try{if(!i||!s)throw new Error("URL and payload are required");const t={url:i,payload:s,options:r,callback:e};await this.executeRequest(t)}catch(t){n.error("Failed to send request:",t.message),e({retry:!1,status:0,error:t.message})}}async executeRequest(t){const{url:e,payload:i,options:s,callback:r}=t,a=Date.now();try{const r=(o=JSON.stringify(i.body),h=window.NRVIDEO?.config?.obfuscate,h&&0!==h.length?h.reduce((t,e)=>{let i;try{if(e.regex instanceof RegExp){const t=e.regex.flags.includes("g")?e.regex.flags:e.regex.flags+"g";i=new RegExp(e.regex.source,t)}else i=new RegExp(e.regex,"g")}catch(i){return n.warn("applyObfuscationRules: invalid regex, skipping rule:",e.regex,i.message),t}return t.replace(i,e.replacement)},o):o);if(s.isFinalHarvest&&navigator.sendBeacon){const i=await this.sendWithBeacon(e,r),s={success:i,status:i?204:0};return void this.handleRequestComplete(t,s,a)}const d=await this.fetchWithTimeout(e,{method:"POST",body:r,headers:{"Content-Type":"application/json"},keepalive:s.isFinalHarvest},1e4),l={success:d.ok,status:d.status,statusText:d.statusText};this.handleRequestComplete(t,l,a)}catch(e){const i={success:!1,status:0,error:e.message};this.handleRequestComplete(t,i,a)}var o,h}handleRequestComplete(t,e){const{callback:i}=t;i({retry:!e.success&&(0===e.status||function(t){switch(t){case 408:case 429:case 500:return!0;case 401:case 403:case 404:return!1}return t>=502&&t<=504||t>=512&&t<=530}(e.status)),status:e.status,error:e.error})}async sendWithBeacon(t,e){try{return navigator.sendBeacon(t,e)}catch(t){return n.warn("sendBeacon failed, falling back to fetch:",t.message),!1}}async fetchWithTimeout(t,e,i){const s=new AbortController,r=setTimeout(()=>s.abort(),i);try{const i=await fetch(t,{...e,signal:s.signal});return clearTimeout(r),i}catch(t){if(clearTimeout(r),"AbortError"===t.name)throw new Error(`Request timeout after ${i}ms`);throw t}}}function Q(t,e){const i=t[e.viewId];if(!i)return!1;for(const t of h.QOE_KPI_KEYS)if(e[t]!==i[t])return!1;return!0}function x(t,e){const i={};for(const t of h.QOE_KPI_KEYS)i[t]=e[t];t[e.viewId]=i}class q{constructor(t){this.eventBuffer=t,this.retryQueueHandler=new H,this.httpClient=new F,this.fallBackUrl="",this.retryCount=0,this.eventBuffer instanceof P&&this.eventBuffer.setSmartHarvestCallback((t,e)=>this.triggerSmartHarvest(t,e)),this.harvestCycle=h.INTERVAL,this.isHarvesting=!1,this.qoeCycleCount=1,this.forceNextQoeCycle=!1,this.beforeDrainCallback=null,this._lastSentQoeKpis={},this.timer=function({interval:t,onTick:e,errorLabel:i}){let s=!1,r=null,a=t;function o(){s&&(r=setTimeout(async()=>{r=null;try{await e()}catch(t){n.error(`${i}: scheduled tick failed:`,t.message)}finally{s&&o()}},a))}return{start(){s||(s=!0,o())},stop(){s=!1,r&&(clearTimeout(r),r=null)},cancelAndReschedule(){r&&(clearTimeout(r),r=null),s&&o()},updateInterval(t){"number"!=typeof t||t<=0||(a=t,s&&r&&(clearTimeout(r),r=null,o()))},isRunning:()=>s}}({interval:this.harvestCycle,onTick:()=>this.onHarvestInterval(),errorLabel:"HarvestScheduler"}),this.setupPageLifecycleHandlers()}get isStarted(){return this.timer.isRunning()}startScheduler(){this.timer.isRunning()?n.warn("Harvest scheduler is already started"):(n.notice("Starting harvest scheduler",{harvestCycle:this.harvestCycle,eventBufferSize:this.eventBuffer?this.eventBuffer.size():0}),this.timer.start())}stopScheduler(){this.timer.isRunning()&&(this.timer.stop(),n.notice("Harvest scheduler stopped"))}async triggerSmartHarvest(t,e){if(n.notice(`${t} harvest triggered at ${e}% threshold`,{type:t,threshold:e}),this.eventBuffer&&!this.eventBuffer.isEmpty())try{await this.triggerHarvest({})}catch(e){n.error(`${t} harvest failed:`,e.message)}finally{this.timer.cancelAndReschedule()}}async onHarvestInterval(){const t=this.eventBuffer&&!this.eventBuffer.isEmpty(),e=this.retryQueueHandler&&this.retryQueueHandler.getQueueSize()>0;(t||e)&&await this.triggerHarvest({})}async triggerHarvest(t={}){if(this.isHarvesting)return{success:!1,reason:"harvest_in_progress"};this.isHarvesting=!0;try{let e=this.drainEvents(t);if(t.isFinalHarvest){const t=h.MAX_BEACON_SIZE;E(e)>t&&(e=this.trimEventsToFit(e,t))}const i=await this.sendChunk(e,t,!0);return{success:i.success,totalChunks:1,results:[i]}}catch(t){return n.error("Harvest cycle failed:",t.message),this.handleHarvestFailure(t),{success:!1,error:t.message}}finally{this.isHarvesting=!1}}trimEventsToFit(t,e){if(0===t.length)return t;const i=[];let s=0;for(let r=t.length-1;r>=0;r--){const a=t[r],n=E({ins:[a,...i]});n>e||(i.unshift(a),s=n)}const r=t.length-i.length;if(r>0){const a=t.slice(0,r);n.warn(`Discarded ${r} events to fit beacon size limit`,{originalCount:t.length,trimmedCount:i.length,finalSize:s,maxSize:e}),this.retryQueueHandler&&this.retryQueueHandler.addFailedEvents(a)}return i}drainEvents(t={}){const e=window.NRVIDEO?.config?.qoeIntervalFactor??1,i=!!t.isFinalHarvest||this.forceNextQoeCycle,s=(this.qoeCycleCount-1)%e==0||i;if(this.forceNextQoeCycle&&(this.forceNextQoeCycle=!1),this.beforeDrainCallback&&"function"==typeof this.beforeDrainCallback)try{this.beforeDrainCallback()}catch(t){n.error("Before drain callback failed:",t.message)}let r=function(t,e,i){if(e)return t;const s=[];for(const e of t)e.actionName===m.Events.QOE_AGGREGATE?i.add(e):s.push(e);return s}(this.eventBuffer.drain(),s,this.eventBuffer);this.qoeCycleCount++,function(t,e,i){for(let s=t.length-1;s>=0;s--){const r=t[s];r.actionName===m.Events.QOE_AGGREGATE&&(!i&&Q(e,r)?t.splice(s,1):x(e,r))}}(r,this._lastSentQoeKpis,i);let a=[...r],o=E(r);if(this.retryQueueHandler&&this.retryQueueHandler.getQueueSize()>0){const t=h.MAX_PAYLOAD_SIZE-o,e=h.MAX_EVENTS_PER_BATCH-a.length;if(t>0&&e>0){const i=this.retryQueueHandler.getRetryEventsToFit(t,e);i.length>0&&(a=[...i,...a])}}return a}async sendChunk(t,e,i){const s={url:function(t){try{if(!window.NRVIDEO||!window.NRVIDEO.info)throw new Error("NRVIDEO info is not available.");let{beacon:e,licenseKey:i,applicationID:s}=window.NRVIDEO.info;if(!e||!i)throw new Error("Options object provided by New Relic is not correctly initialized");return s?`https://${t||e}/ins/1/${i}?a=${s}&v=${d.rE}&ref=${window.location.href}&ca=VA`:`https://${t||e}/ins/1/${i}?&v=${d.rE}&ref=${window.location.href}&ca=VA`}catch(t){return console.error(t.message),null}}(this.fallBackUrl),payload:{body:{ins:t}},options:{...e,isLastChunk:i}};return new Promise(e=>{this.httpClient.send(s,i=>{i.retry?this.handleRequestFailure(t):(this.retryCount=0,this.fallBackUrl=""),e({success:!i.retry,status:i.status,error:i.error,chunk:t,eventCount:t.length})})})}handleRequestFailure(t){this.retryQueueHandler.addFailedEvents(t),"US"===window.NRVIDEO?.info?.region&&(this.retryCount++,this.retryCount>5?(this.retryCount=0,this.fallBackUrl=""):this.retryCount>=2&&(this.fallBackUrl=h.COLLECTOR.US[1]))}handleHarvestFailure(t){n.warn("Harvest failure handled",{error:t.message})}updateHarvestInterval(t){"number"!=typeof t||isNaN(t)?n.warn("Invalid newInterval provided to updateHarvestInterval"):t<1e3||t>3e5?n.warn("newInterval out of bounds (1000-300000), ignoring"):this.harvestCycle!==t&&(this.harvestCycle=t,n.notice("Updated harvestCycle:",this.harvestCycle),this.timer.updateInterval(t))}setupPageLifecycleHandlers(){let t=!1;const e=()=>{t||(t=!0,this.triggerHarvest({isFinalHarvest:!0,force:!0}))};document.addEventListener("visibilitychange",()=>{document.hidden&&e()}),window.addEventListener("pagehide",()=>{e()}),window.addEventListener("beforeunload",()=>{e()})}}const U=new class{constructor(){this.isInitialized=!1,this.harvestScheduler=null,this.eventBuffer=null}initialize(){if(this.isInitialized)n.warn("Video analytics agent already initialized");else try{this.eventBuffer=new P,this.harvestScheduler=new q(this.eventBuffer),this.harvestScheduler.startScheduler(),this.isInitialized=!0,n.notice("Video analytics agent initialized successfully")}catch(t){n.error("Failed to initialize video analytics agent:",t.message)}}addEvent(t){this.isInitialized||(n.warn("Video analytics agent not initialized, initializing now"),this.initialize());try{return function(t,e){return!!e&&(e.actionName===m.Events.QOE_AGGREGATE?e.viewId?t.addOrReplaceByActionNameAndViewId(m.Events.QOE_AGGREGATE,e.viewId,e):t.addOrReplaceByActionName(m.Events.QOE_AGGREGATE,e):t.add(e))}(this.eventBuffer,t)}catch(t){return n.error("Failed to add event to harvesting system:",t.message),!1}}setHarvestInterval(t){this.isInitialized||this.initialize(),this.harvestScheduler.updateHarvestInterval(t)}forceNextQoeCycle(){this.harvestScheduler&&(this.harvestScheduler.forceNextQoeCycle=!0)}setBeforeDrainCallback(t){this.harvestScheduler&&(this.harvestScheduler.beforeDrainCallback=t)}refreshQoeKpis(t,e){!function(t,e,i){if(!t||!e)return;const s=i?t.findByActionNameAndViewId(m.Events.QOE_AGGREGATE,i):t.findByActionName(m.Events.QOE_AGGREGATE);if(!s)return;const r={...s};for(const t of h.QOE_KPI_KEYS)t in e&&(r[t]=e[t]);i?t.addOrReplaceByActionNameAndViewId(m.Events.QOE_AGGREGATE,i,r):t.addOrReplaceByActionName(m.Events.QOE_AGGREGATE,r)}(this.eventBuffer,t,e)}};var z;z=U,T["Browser"]=z;const G=U,M={Constants:h,Chrono:u,Log:n,Emitter:l,Tracker:m,VideoTracker:C,VideoTrackerState:D,Core:w,version:d.rE,NrVideoEventAggregator:P,RetryQueueHandler:H,OptimizedHttpClient:F,HarvestScheduler:q,recordEvent:v};module.exports=e})();
2
+ (()=>{"use strict";const t={d:(e,i)=>{if(Array.isArray(i))for(var s=0;s<i.length;){var r=i[s++],a=i[s++];t.o(e,r)?0===a&&s++:0===a?Object.defineProperty(e,r,{enumerable:!0,value:i[s++]}):Object.defineProperty(e,r,{enumerable:!0,get:a})}else for(var r in i)t.o(i,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:i[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}};let e={};t.r(e),t.d(e,{Chrono:()=>u,Constants:()=>h,Core:()=>D,Emitter:()=>d,HarvestScheduler:()=>U,Log:()=>n,NrVideoEventAggregator:()=>V,OptimizedHttpClient:()=>Q,RetryQueueHandler:()=>F,Tracker:()=>m,VideoTracker:()=>O,VideoTrackerState:()=>k,default:()=>K,getRegisteredHarvester:()=>p,recordEvent:()=>v,version:()=>l.rE,videoAnalyticsHarvester:()=>M});class i{static error(...t){s(t,i.Levels.ERROR,"darkred")}static warn(...t){s(t,i.Levels.WARNING,"darkorange")}static notice(...t){s([].slice.call(arguments),i.Levels.NOTICE,"darkcyan")}static debug(...t){s(t,i.Levels.DEBUG,"indigo")}static debugCommonVideoEvents(t,e,s){try{if(i.level<=i.Levels.DEBUG){s=s||function(t){i.debug("Event: "+t.type)};var r=["canplay","buffering","waiting","ended","play","playing","pause","resume","error","abort","seek","seeking","seeked","stalled","dispose","loadeddata","loadstart","loadedmetadata"];e&&(null===e[0]?(e.shift(),r=e):r=r.concat(e));for(var a=0;a<r.length;a++)"function"==typeof t?t.call(window,r[a],s):t.on?t.on(r[a],s):t.addEventListener?t.addEventListener(r[a],s):t.addEventHandler?t.addEventHandler(r[a],s):i.warn("debugCommonVideoEvents: No common listener function found for ",t)}}catch(t){i.warn(t)}}}function s(t,e,s){e=e||i.Levels.NOTICE,s=s||"darkcyan";var n,o,h,l,d,c,u=i.prefix;(i.includeTime&&(u+=(n=new Date,o=("0"+n.getDate()).slice(-2),h=("0"+n.getMinutes()).slice(-2),l=("0"+n.getSeconds()).slice(-2),d=("00"+n.getMilliseconds()).slice(-3),"["+o+":"+h+":"+l+"."+d+"] ")),u+=function(t){return a[t]}(e)+":",i.level<=e&&e!==i.Levels.SILENT)&&(!i.colorful||"undefined"!=typeof document&&document.documentMode?r(t,u):(c=e===i.Levels.ERROR&&console.error?console.error:e===i.Levels.WARNING&&console.warn?console.warn:e===i.Levels.DEBUG&&console.debug&&null==window.cast?console.debug:console.log,u="%c"+u,t.splice(0,0,u,"color: "+s),c.apply(console,t)))}function r(t,e){if(t instanceof Array)for(var i in t)r(t[i],e);else"string"==typeof t?console.log(e+" "+t):(console.log(e+"↵"),console.log(t))}i.Levels={SILENT:5,ERROR:4,WARNING:3,NOTICE:2,DEBUG:1,ALL:0},i.level=i.Levels.ERROR,i.colorful=!0,i.includeTime=!0,i.prefix="[nrvideo]";const a={4:"e",3:"w",2:"n",1:"d"};!function(){if("undefined"!=typeof window&&window.location&&window.location.search){var t=/\?.*&*nrvideo-debug=(.+)/i.exec(window.location.search);null!==t&&("true"===t[1]?i.level=i.Levels.ALL:i.level=t[1]),null!==/\?.*&*nrvideo-colors=false/i.exec(window.location.search)&&(i.colorful=!1)}}();const n=i;class o{}o.AdPositions={PRE:"pre",MID:"mid",POST:"post"},o.COLLECTOR={US:["bam.nr-data.net","bam-cell.nr-data.net"],EU:"bam.eu01.nr-data.net",JP:"bam.jp.nr-data.net",Staging:"staging-bam-cell.nr-data.net",GOV:"gov-bam.nr-data.net"},o.VALID_EVENT_TYPES=["VideoAction","VideoAdAction","VideoErrorAction","VideoCustomAction"],o.MAX_PAYLOAD_SIZE=1048576,o.MAX_BEACON_SIZE=61440,o.MAX_EVENTS_PER_BATCH=1e3,o.INTERVAL=1e4,o.DEFAULT_QOE_INTERVAL_FACTOR=2,o.QOE_KPI_KEYS=["startupTime","peakBitrate","averageBitrate","totalPlaytime","totalRebufferingTime","rebufferingRatio","hadStartupError","hadPlaybackError","numberOfErrors"],o.QOE_AGGREGATE_KEYS=["coreVersion","instrumentation.name","instrumentation.provider","instrumentation.version","isBackgroundEvent","playerName","playerVersion","src","viewId","viewSession","contentIsAutoplayed","contentIsMuted","contentRenditionHeight","contentRenditionWidth","contentSrc","numberOfVideos","pageUrl","trackerName","trackerVersion","contentDuration","contentPlayrate","contentPlayhead","contentPreload","elapsedTime","contentTitle","contentId","contentIsLive","deviceType","deviceGroup","deviceManufacturer","deviceModel","deviceName","deviceSize","deviceUuid","contentRenditionName","contentIsFullscreen","contentCdn","contentFps","asnOrganization","asnLongitude","asnLatitude","asn","timeSinceRequested","timeSinceStarted"];const h=o,l={rE:"5.0.1"};const d=class{on(t,e){if(this._listeners=this._listeners||{},"function"==typeof e)return this._listeners[t]=this._listeners[t]||[],this._listeners[t].push(e),this}off(t,e){if(this._listeners=this._listeners||{},this._listeners[t]){var i=this._listeners[t].indexOf(e);-1!==i&&this._listeners[t].splice(i,1)}return this}emit(t,e,i){return this._listeners=this._listeners||{},i=i||{},Array.isArray(this._listeners[e])&&this._listeners[e].forEach(s=>{s.call(this,{eventType:t,type:e,data:i,target:this})}),Array.isArray(this._listeners["*"])&&this._listeners["*"].forEach(s=>{s.call(this,{eventType:t,type:e,data:i,target:this})}),this}};class c{constructor(){this.reset()}reset(){this.startTime=0,this.stopTime=0,this.accumulator=0,this.offset=0}getDeltaTime(){return this.startTime?this.offset+((new Date).getTime()-this.startTime):null}start(){this.startTime=(new Date).getTime(),this.stopTime=0}stop(){return this.stopTime=(new Date).getTime(),this.startTime<this.stopTime&&(this.accumulator+=this.stopTime-this.startTime),this.getDeltaTime()}getDuration(){return this.stopTime?this.accumulator+this.offset:this.accumulator+(this.getDeltaTime()??0)}clone(){var t=new c;return t.startTime=this.startTime,t.stopTime=this.stopTime,t.offset=this.offset,t.accumulator=this.accumulator,t}}const u=c;class g extends d{constructor(t){super(),this.customData={},this.heartbeat=null,this.parentTracker=null,this._trackerReadyChrono=new u,this._trackerReadyChrono.start(),this._actionTable=h.ACTION_TABLE,this._actionAdTable=h.ACTION_AD_TABLE,t=t||{},this.setOptions(t)}setOptions(t){t&&(t.parentTracker&&(this.parentTracker=t.parentTracker),t.customData&&(this.customData=t.customData),t.heartbeat&&(this.heartbeat=t.heartbeat))}dispose(){this.unregisterListeners()}registerListeners(){}unregisterListeners(){}getHeartbeat(){return this.state._isAd?2e3:this.heartbeat?this.heartbeat:this.parentTracker&&this.parentTracker.heartbeat?this.parentTracker.heartbeat:3e4}startHeartbeat(){this._heartbeatInterval=setInterval(this.sendHeartbeat.bind(this),Math.max(this.getHeartbeat(),2e3))}stopHeartbeat(){this._heartbeatInterval&&clearInterval(this._heartbeatInterval)}sendHeartbeat(t){this.sendVideoAction(g.Events.HEARTBEAT,t)}getAttributes(t,e){(t=t||{}).trackerName=this.getTrackerName(),t.trackerVersion=this.getTrackerVersion(),t.coreVersion=l.rE,t.timeSinceTrackerReady=this._trackerReadyChrono.getDeltaTime();for(let e in this.customData)t[e]=this.customData[e];return null!=document.hidden&&(t.isBackgroundEvent=document.hidden),t}getTrackerVersion(){return l.rE}getTrackerName(){return"base-tracker"}sendVideoAction(t,e){this.emit("VideoAction",t,this.getAttributes(e))}sendVideoAdAction(t,e){this.emit("VideoAdAction",t,this.getAttributes(e))}sendVideoErrorAction(t,e){let i=this.isAd()?"adError":"videoError";this.emit("VideoErrorAction",t,this.getAttributes(e,i))}sendVideoCustomAction(t,e){this.emit("VideoCustomAction",t,this.getAttributes(e,"customAction"))}setHarvestInterval(t){const e=this.getHarvester?.();if(e)try{e.setHarvestInterval(t)}catch(t){return void n.error("Failed to set harvest interval:",t.message)}else n.error("Tracker has no harvester; setHarvestInterval ignored")}getHarvester(){return null}}g.Events={HEARTBEAT:"HEARTBEAT",QOE_AGGREGATE:"QOE_AGGREGATE"};const m=g;function f(t){try{return JSON.stringify(t,(()=>{const t=new WeakSet;return(e,i)=>{if("object"==typeof i&&null!==i){if(t.has(i))return;t.add(i)}return i}})())??""}catch(t){return n.error("Error stringifying value:",t.message),""}}function E(t){if("string"==typeof t&&t.length)return t.length;if("object"==typeof t){if("undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer&&t.byteLength)return t.byteLength;if("undefined"!=typeof Blob&&t instanceof Blob&&t.size)return t.size;if(!("undefined"!=typeof FormData&&t instanceof FormData))try{return f(t).length}catch(t){return}}}function A(t,e,i,{addTimeSinceLoad:s=!1}={}){const{appName:r,applicationID:a}=i,{qoe:n,...o}=e,l=n?{...n}:{},d={...a?{}:{appName:r},timestamp:Date.now(),...s?{timeSinceLoad:"undefined"!=typeof window&&window.performance?window.performance.now()/1e3:null}:{}},c={...o,eventType:t,...d};let u=null;if("VideoAction"===t){const t=(g=h.QOE_AGGREGATE_KEYS,f=e,g&&Array.isArray(g)&&0!==g.length?f&&"object"==typeof f?g.reduce((t,e)=>(e in f&&(t[e]=f[e]),t),{}):{}:f);u={eventType:"VideoAction",actionName:m.Events.QOE_AGGREGATE,qoeAggregateVersion:"1.0.0",...l,...t,...d}}var g,f;return{eventObject:c,qoeEventObject:u}}const T=Object.create(null);function p(t){return T[t]}function v(t,e={}){try{if(!h.VALID_EVENT_TYPES.includes(t))return n.warn("Invalid event type provided to recordEvent",{eventType:t}),!1;const i="Vega"===e.src,s=i?"Vega":"Browser",r="undefined"!=typeof window?window:void 0,a=i?globalThis.__NRVIDEO_CD__?.info:r?.NRVIDEO?.info;if(!a)return;const o=T[s];if(!o)return n.warn("No harvester registered for routing key",{routingKey:s}),!1;return function(t,e,i,s,r,{addTimeSinceLoad:a=!1}={}){if(!s)return!1;const{eventObject:n,qoeEventObject:o}=A(t,e,i,{addTimeSinceLoad:a}),h=s.addEvent(n);return o&&r?h&&s.addEvent(o):h}(t,e,a,o,i?globalThis.__NRVIDEO_CD__?.config?.qoeAggregate:r?.NRVIDEO?.config?.qoeAggregate,{addTimeSinceLoad:!i})}catch(t){return n.error("Failed to record event:",t.message),!1}}const S={us:"https://mobile-collector.newrelic.com/mobile",eu:"https://mobile-collector.eu01.nr-data.net/mobile",staging:"https://staging-mobile-collector.newrelic.com/mobile",gov:"https://gov-mobile-collector.newrelic.com/mobile",jp:"https://mobile-collector.jp.nr-data.net/mobile"},{COLLECTOR:y}=h;class _{setConfiguration(t,e,i){return!!("Vega"===i?this.validateVegaFields(t):this.validateRequiredFields(t))&&(!!this.validateConfigFields(e)&&(this.initializeGlobalConfig(t,e,i),n.notice("Video analytics configuration initialized successfully"),!0))}validateVegaFields(t){return t&&"object"==typeof t?t.applicationToken?t.endpoint?.toLowerCase()in S||(n.error("Invalid endpoint (must be us, eu, staging, gov, or jp)"),!1):(n.error("applicationToken is required"),!1):(n.error("Configuration must be an object"),!1)}validateRequiredFields(t){if(!t||"object"!=typeof t)return n.error("Configuration must be an object"),!1;const{licenseKey:e,appName:i,region:s,applicationID:r,beacon:a}=t;if(!e)return n.error("licenseKey is required"),!1;if(r){if(!a)return n.error("beacon is required when applicationID is provided"),!1;if(!Object.values(y).flatMap(t=>t).includes(a))return n.error(`Invalid beacon: ${a}`),!1}else{if(!i||!s)return n.error("appName and region are required when applicationID is not provided"),!1;if(!y[s])return n.error(`Invalid region: ${s}. Valid regions are: ${Object.keys(y).join(", ")}`),!1}return!0}validateConfigFields(t){if(null==t)return!0;if("object"!=typeof t||Array.isArray(t))return n.error("config must be an object"),!1;const{qoeAggregate:e,obfuscate:i}=t;return void 0!==e&&"boolean"!=typeof e?(n.error("qoeAggregate must be a boolean"),!1):!(void 0!==i&&!Array.isArray(i))||(n.error("obfuscate must be an array"),!1)}filterObfuscateRules(t){return t?t.filter(t=>{const e=void 0!==t.regex&&("string"==typeof t.regex||t.regex instanceof RegExp),i=void 0!==t.replacement&&"string"==typeof t.replacement;return!(!e||!i)||(n.warn("obfuscate rule missing required 'regex' (string|RegExp) and/or 'replacement' (string), skipping:",t),!1)}):[]}sanitizeQoeIntervalFactor(t){return null==t?h.DEFAULT_QOE_INTERVAL_FACTOR:"number"==typeof t&&Number.isInteger(t)&&t>=1?t:(n.warn(`Invalid qoeIntervalFactor "${t}" — must be a positive integer. Defaulting to ${h.DEFAULT_QOE_INTERVAL_FACTOR}.`),h.DEFAULT_QOE_INTERVAL_FACTOR)}initializeGlobalConfig(t,e,i){if("Vega"===i)return void(globalThis.__NRVIDEO_CD__={info:{accountId:t.accountId,applicationToken:t.applicationToken,endpoint:t.endpoint?.toLowerCase(),...t.appName?{appName:t.appName}:{},...t.applicationID?{applicationID:t.applicationID}:{},...t.deviceInfo?{deviceInfo:t.deviceInfo}:{}},config:{qoeAggregate:e?.qoeAggregate??!0,qoeIntervalFactor:this.sanitizeQoeIntervalFactor(e?.qoeIntervalFactor),obfuscate:this.filterObfuscateRules(e?.obfuscate)}});let{licenseKey:s,appName:r,region:a,beacon:n,applicationID:o}=t;n="US"===a?h.COLLECTOR.US[0]:n||y[a],window.NRVIDEO={info:{...a?{region:a}:{},beacon:n,licenseKey:s,applicationID:o,...o?{}:{appName:r}},config:{qoeAggregate:e?.qoeAggregate??!0,qoeIntervalFactor:this.sanitizeQoeIntervalFactor(e?.qoeIntervalFactor),obfuscate:this.filterObfuscateRules(e?.obfuscate)}}}}const R=new _;class B{static addTracker(t,e){var i,s,r;e?.info&&(i=e.info,s=e?.config,r=e?.src,R.setConfiguration(i,s,r)),t.on&&t.emit?(b.push(t),t.on("*",w),"function"==typeof t.trackerInit&&t.trackerInit()):n.error("Tried to load a non-tracker.",t)}static removeTracker(t){t.off("*",w),t.dispose();let e=b.indexOf(t);-1!==e&&b.splice(e,1)}static getTrackers(){return b}static send(t,e,i){return v(t,{actionName:e,...i})}static sendError(t){return v("VideoErrorAction",{actionName:"ERROR",...t})}}let b=[];function w(t){try{let e=function(t){let e={};for(let i in t)null!==t[i]&&void 0!==t[i]&&(e[i]=t[i]);return e}(t.data);n.level<=n.Levels.DEBUG?n.notice("Sent",t.type,e):n.notice("Sent",t.type),B.send(t.eventType,t.type,e)}catch(t){n.error("Error in event handler:",t.message)}}const D=B;const k=class{constructor(){this.reset(),this._createdAt=Date.now(),this._hb=!0,this._acc=0,this._bufferAcc=0}reset(){this._viewSession=null,this._viewCount=0,this._isAd=!1,this.numberOfErrors=0,this.numberOfAds=0,this.numberOfVideos=0,this.totalPlaytime=0,this.weightedAverageBitrate=0,this.totalAdPlaytime=0,this.isAdBreak=!1,this.initialBufferingHappened=!1,this.startupTime=null,this.peakBitrate=0,this.partialAverageBitrate=0,this._totalBitrateDuration=0,this.weightedBitrate=0,this._lastBitrate=null,this._lastBitrateChangeTimestamp=null,this._downloadBitrates=[],this._lastDownloadBitrate=null,this.totalSwitchUps=0,this.totalSwitchDowns=0,this.totalPauseTime=0,this._playedRenditions=new Set,this.hadStartupError=!1,this.hadPlaybackError=!1,this.totalRebufferingTime=0,this.resetFlags(),this.resetChronos()}resetFlags(){this.isPlayerReady=!1,this.isRequested=!1,this.isStarted=!1,this.isPaused=!1,this.isSeeking=!1,this.isBuffering=!1,this.isPlaying=!1}resetChronos(){this.timeSinceRequested=new u,this.timeSinceStarted=new u,this.timeSincePaused=new u,this.timeSinceSeekBegin=new u,this.timeSinceBufferBegin=new u,this.timeSinceAdBreakStart=new u,this.timeSinceLastDownload=new u,this.timeSinceLastHeartbeat=new u,this.timeSinceLastRenditionChange=new u,this.timeSinceLastAdQuartile=new u,this.timeSinceLastAd=new u,this.timeSinceLastError=new u,this.timeSinceLastAdError=new u,this.timeSinceResumed=new u,this.timeSinceSeekEnd=new u,this.playtimeSinceLastEvent=new u,this.customTimeSinceAttributes={},this.elapsedTime=new u,this.bufferElapsedTime=new u,this._totalAdPlaytime=new u}isAd(){return this._isAd}setIsAd(t){this._isAd=t}setTimeSinceAttribute(t){this.customTimeSinceAttributes[t]=new u,this.customTimeSinceAttributes[t].start()}removeTimeSinceAttribute(t){delete this.customTimeSinceAttributes[t]}getViewSession(){if(!this._viewSession){let t=(new Date).getTime(),e=Math.random().toString(36).substring(2)+Math.random().toString(36).substring(2);this._viewSession=t+"-"+e}return this._viewSession}getViewId(){return this.getViewSession()+"-"+this._viewCount}getStateAttributes(t){t=t||{},this.isAd()?(this.isRequested&&(t.timeSinceAdRequested=this.timeSinceRequested.getDeltaTime(),t.timeSinceLastAdHeartbeat=this.timeSinceLastHeartbeat.getDeltaTime()),this.isStarted&&(t.timeSinceAdStarted=this.timeSinceStarted.getDeltaTime()),this.isPaused&&(t.timeSinceAdPaused=this.timeSincePaused.getDeltaTime()),this.isBuffering&&(t.timeSinceAdBufferBegin=this.timeSinceBufferBegin.getDeltaTime()),this.isSeeking&&(t.timeSinceAdSeekBegin=this.timeSinceSeekBegin.getDeltaTime()),this.isAdBreak&&(t.timeSinceAdBreakBegin=this.timeSinceAdBreakStart.getDeltaTime()),this.numberOfErrors>0&&this.timeSinceLastAdError.startTime>0&&(t.timeSinceLastAdError=this.timeSinceLastAdError.getDeltaTime()),t.numberOfAds=this.numberOfAds):(this.isRequested&&(t.timeSinceRequested=this.timeSinceRequested.getDeltaTime(),t.timeSinceLastHeartbeat=this.timeSinceLastHeartbeat.getDeltaTime()),this.isStarted&&(t.timeSinceStarted=this.timeSinceStarted.getDeltaTime()),this.isPaused&&(t.timeSincePaused=this.timeSincePaused.getDeltaTime()),this.isBuffering&&(t.timeSinceBufferBegin=this.timeSinceBufferBegin.getDeltaTime()),this.isSeeking&&(t.timeSinceSeekBegin=this.timeSinceSeekBegin.getDeltaTime()),t.timeSinceLastAd=this.timeSinceLastAd.getDeltaTime(),this.numberOfErrors>0&&this.timeSinceLastError.startTime>0&&(t.timeSinceLastError=this.timeSinceLastError.getDeltaTime()),t.numberOfVideos=this.numberOfVideos),t.numberOfErrors=this.numberOfErrors,this.isAd()||(this.playtimeSinceLastEvent.startTime>0?t.playtimeSinceLastEvent=this.playtimeSinceLastEvent.getDeltaTime():t.playtimeSinceLastEvent=0,this.isPlaying?this.playtimeSinceLastEvent.start():this.playtimeSinceLastEvent.reset(),this.totalPlaytime+=t.playtimeSinceLastEvent,t.totalPlaytime=this.totalPlaytime);for(const[e,i]of Object.entries(this.customTimeSinceAttributes))t[e]=i.getDeltaTime();return t}getQoeAttributes(t){t=t||{};const e={};try{if(null!==this.startupTime&&(e.startupTime=this.startupTime),this.peakBitrate>0&&(e.peakBitrate=this.peakBitrate),e.hadStartupError=this.hadStartupError,e.hadPlaybackError=this.hadPlaybackError,e.totalRebufferingTime=this.totalRebufferingTime,e.rebufferingRatio=this.totalPlaytime>0?this.totalRebufferingTime/this.totalPlaytime*100:0,e.totalPlaytime=this.totalPlaytime,e.averageBitrate=this.weightedBitrate,e.numberOfErrors=this.numberOfErrors,this._downloadBitrates.length>0){const t=this._downloadBitrates.reduce((t,e)=>t+e,0);e.avgDownloadRate=Math.round(t/this._downloadBitrates.length),e.minDownloadRate=Math.min(...this._downloadBitrates),e.maxDownloadRate=Math.max(...this._downloadBitrates)}e.totalSwitchUps=this.totalSwitchUps,e.totalSwitchDowns=this.totalSwitchDowns,e.totalPauseTime=this.timeSincePaused.getDuration(),e.totalViewSessionTime=this.totalPlaytime,e.totalRenditions=this._playedRenditions.size,e.qoeAggregateVersion="1.1.0"}catch(t){n.error("Failed to add attributes for QOE KPIs",t.message)}return t.qoe=e,t}calculateBufferType(t){let e="";return e=t?"initial":this.isSeeking?"seek":this.isPaused?"pause":"connection",n.debug("Buffer Type = "+e),e}goViewCountUp(){this._viewCount++}goPlayerReady(){return!this.isPlayerReady&&(this.isPlayerReady=!0,!0)}goRequest(){return!this.isRequested&&(this.isRequested=!0,this.timeSinceLastAd.reset(),this.timeSinceRequested.start(),!0)}goStart(){return!(!this.isRequested||this.isStarted)&&(this.isAd()?this.numberOfAds++:this.numberOfVideos++,this.isStarted=!0,this.isPlaying=!0,this.timeSinceStarted.start(),this.playtimeSinceLastEvent.start(),!0)}goEnd(){return!!this.isRequested&&(this.numberOfErrors=0,this.resetFlags(),this.timeSinceRequested.stop(),this.timeSinceStarted.stop(),this.playtimeSinceLastEvent.stop(),this.isPlaying=!1,!0)}goPause(){return!(!this.isStarted||this.isPaused)&&(this.isPaused=!0,this.isPlaying=!1,this.timeSincePaused.start(),this.playtimeSinceLastEvent.stop(),this.timeSinceResumed.reset(),this.isBuffering&&(this._bufferAcc+=this.bufferElapsedTime.getDeltaTime()),this.elapsedTime.start(),!0)}goResume(){return!(!this.isStarted||!this.isPaused)&&(this.isPaused=!1,this.isPlaying=!0,this.timeSincePaused.stop(),this.timeSinceResumed.start(),this._hb?(this._acc=this.elapsedTime.getDeltaTime(),this._hb=!1):(this.isBuffering&&this.bufferElapsedTime.start(),this._acc+=this.elapsedTime.getDeltaTime()),!0)}goBufferStart(){return!(!this.isRequested||this.isBuffering)&&(this.isBuffering=!0,this.isPlaying=!1,this.timeSinceBufferBegin.start(),this.bufferElapsedTime.start(),!0)}goBufferEnd(){return!(!this.isRequested||!this.isBuffering)&&(this.isBuffering=!1,this.isPlaying=!0,this.timeSinceBufferBegin.stop(),this._hb?(this._bufferAcc=this.bufferElapsedTime.getDeltaTime(),this._hb=!1):this._bufferAcc+=this.bufferElapsedTime.getDeltaTime(),!this.isAd()&&this.initialBufferingHappened&&(this.totalRebufferingTime+=this.timeSinceBufferBegin.stopTime-this.timeSinceBufferBegin.startTime),!0)}goSeekStart(){return!(!this.isStarted||this.isSeeking)&&(this.isSeeking=!0,this.isPlaying=!1,this.timeSinceSeekBegin.start(),this.timeSinceSeekEnd.reset(),!0)}goSeekEnd(){return!(!this.isStarted||!this.isSeeking)&&(this.isSeeking=!1,this.isPlaying=!0,this.timeSinceSeekBegin.stop(),this.timeSinceSeekEnd.start(),!0)}goAdBreakStart(){return!this.isAdBreak&&(this.isAdBreak=!0,this.timeSinceAdBreakStart.start(),!0)}goAdBreakEnd(){return!!this.isAdBreak&&(this.isRequested=!1,this.isAdBreak=!1,this.totalAdPlaytime=this.timeSinceAdBreakStart.getDeltaTime(),this.timeSinceAdBreakStart.stop(),!0)}goDownload(){this.timeSinceLastDownload.start()}goHeartbeat(){this.timeSinceLastHeartbeat.start()}goRenditionChange(){this.timeSinceLastRenditionChange.start()}goAdQuartile(){this.timeSinceLastAdQuartile.start()}goError(){this.isError=!0,this.numberOfErrors++,this.isAd()?this.timeSinceLastAdError.start():(this.timeSinceLastError.start(),this.isStarted?this.hadPlaybackError=!0:this.hadStartupError=!0)}goLastAd(){this.timeSinceLastAd.start()}trackContentBitrateState(t){if(t&&"number"==typeof t){this.peakBitrate=Math.max(this.peakBitrate,t);const e=Date.now();if(!this.isPlaying){if(null!==this._lastBitrate&&null!==this._lastBitrateChangeTimestamp){const t=e-this._lastBitrateChangeTimestamp;t>0&&(this.partialAverageBitrate+=this._lastBitrate*t,this._totalBitrateDuration+=t),this._lastBitrateChangeTimestamp=null}return void(this._lastBitrate=t)}if(null===this._lastBitrateChangeTimestamp&&null!==this._lastBitrate&&(this._lastBitrateChangeTimestamp=e),null!==this._lastBitrate&&this._lastBitrate!==t&&null!==this._lastBitrateChangeTimestamp){const t=e-this._lastBitrateChangeTimestamp;t>0&&(this.partialAverageBitrate+=this._lastBitrate*t,this._totalBitrateDuration+=t),this._lastBitrateChangeTimestamp=e}null===this._lastBitrateChangeTimestamp&&(this._lastBitrateChangeTimestamp=e),this._lastBitrate=t;let i=this.partialAverageBitrate,s=this._totalBitrateDuration;const r=e-this._lastBitrateChangeTimestamp;r>0&&(i+=t*r,s+=r),this.weightedBitrate=s>0?Math.round(i/s):t}}trackDownloadRate(t){!t||"number"!=typeof t||t<=0||t!==this._lastDownloadBitrate&&(this._downloadBitrates.push(t),this._lastDownloadBitrate=t)}addPlayedRendition(t,e){t&&e&&this._playedRenditions.add(`${t}x${e}`)}resetViewIdTrackedState(){this.peakBitrate=0,this.startupTime=null,this.partialAverageBitrate=0,this._totalBitrateDuration=0,this.weightedBitrate=0,this._lastBitrate=null,this._lastBitrateChangeTimestamp=null,this._downloadBitrates=[],this._lastDownloadBitrate=null,this.totalSwitchUps=0,this.totalSwitchDowns=0,this.timeSincePaused.reset(),this._playedRenditions=new Set}clearTotalAdsTime(){n.debug("clear total ads time",this.totalAdTime),this._totalAdPlaytime.reset()}totalAdTime(){return this._totalAdPlaytime.getDuration()}startAdsTime(){return n.debug("startAdsTime"),this._totalAdPlaytime.start()}stopAdsTime(){return n.debug("stopAdsTime"),this._totalAdPlaytime.stop()}setStartupTime(t){null===this.startupTime&&(this.startupTime=Math.max(this.timeSinceRequested.getDeltaTime()-t,0))}};class N extends m{constructor(t,e){super(),this.state=new k,this.adsTracker=null,this._lastBufferType=null,this._userId=null,this._src=null,e=e||{},this.setOptions(e),t&&this.setPlayer(t,e.tag),n.notice("Tracker "+this.getTrackerName()+" v"+this.getTrackerVersion()+" is ready.")}setUserId(t){this._userId=t}setOptions(t){t&&(t.adsTracker&&this.setAdsTracker(t.adsTracker),"boolean"==typeof t.isAd&&this.setIsAd(t.isAd),void 0!==t.src&&(null!==this._src&&this._src!==t.src?n.warn(`setOptions: src is locked to '${this._src}'. Ignoring override '${t.src}'.`):(this._src=t.src,this.adsTracker&&null==this.adsTracker._src&&(this.adsTracker._src=this._src))),m.prototype.setOptions.apply(this,arguments))}setPlayer(t,e){(this.player||this.tag)&&this.dispose(),"undefined"!=typeof document&&document.getElementById&&("string"==typeof t&&(t=document.getElementById(t)),"string"==typeof e&&(e=document.getElementById(e))),e=e||t,this.player=t,this.tag=e,this.registerListeners()}isAd(){return this.state.isAd()}setIsAd(t){this.state.setIsAd(t)}setAdsTracker(t){this.disposeAdsTracker(),t&&(this.adsTracker=t,this.adsTracker.setIsAd(!0),this.adsTracker.parentTracker=this,null!=this._src&&null==t._src&&(t._src=this._src),this.adsTracker.on("*",C.bind(this)))}disposeAdsTracker(){this.adsTracker&&(this.adsTracker.off("*",C),this.adsTracker.dispose())}dispose(){this.stopHeartbeat(),this.disposeAdsTracker(),this.unregisterListeners(),this.player=null,this.tag=null}registerListeners(){}unregisterListeners(){}getViewId(){return this.parentTracker?this.parentTracker.getViewId():this.state.getViewId()}getViewSession(){return this.parentTracker?this.parentTracker.getViewSession():this.state.getViewSession()}getVideoId(){return null}getTitle(){return null}isLive(){return null}getBitrate(){return null}getManifestBitrate(){return null}getSegmentDownloadBitrate(){return null}getNetworkDownloadBitrate(){return null}getWebkitBitrate(){if(this.tag&&this.tag.webkitVideoDecodedByteCount){let t;if(this._lastWebkitBitrate){t=this.tag.webkitVideoDecodedByteCount;let e=t-this._lastWebkitBitrate,i=this.getHeartbeat()/1e3;t=Math.round(e/i*8)}return this._lastWebkitBitrate=this.tag.webkitVideoDecodedByteCount,t||null}}getRenditionName(){return null}getRenditionBitrate(){return null}getRenditionShift(t){let e,i=this.getManifestBitrate();return this.isAd()?(e=this._lastAdRendition,t&&(this._lastAdRendition=i)):(e=this._lastRendition,t&&(this._lastRendition=i)),i&&e?i>e?"up":i<e?"down":null:null}getRenditionHeight(){return this.tag?this.tag.videoHeight:null}getRenditionWidth(){return this.tag?this.tag.videoWidth:null}getDuration(){return this.tag?this.tag.duration:null}getPlayhead(){return this.tag?this.tag.currentTime:null}getLanguage(){return null}getSrc(){return this.tag?this.tag.currentSrc:null}getPlayrate(){return this.tag?this.tag.playbackRate:null}isMuted(){return this.tag?this.tag.muted:null}isFullscreen(){return null}getCdn(){return null}getPlayerName(){return this.getTrackerName()}getPlayerVersion(){return l.rE}getFps(){return null}isAutoplayed(){return this.tag?this.tag.autoplay:null}getPreload(){return this.tag?this.tag.preload:null}getAdQuartile(){return null}getAdPosition(){return this.parentTracker?this.parentTracker.state.isStarted?"mid":"pre":null}getAdPartner(){return null}getAdCreativeId(){return null}getInstrumentationProvider(){return null}getInstrumentationName(){return null}getInstrumentationVersion(){return null}getAttributes(t,e){if(void 0===(t=m.prototype.getAttributes.apply(this,arguments)).isAd&&(t.isAd=this.isAd()),t.viewSession=this.getViewSession(),t.viewId=this.getViewId(),t.playerName=this.getPlayerName(),t.playerVersion=this.getPlayerVersion(),t["instrumentation.provider"]=this.getInstrumentationProvider(),t["instrumentation.name"]=this.getInstrumentationName(),t["instrumentation.version"]=this.getInstrumentationVersion(),t["enduser.id"]=this._userId,t.src=this._src||"Browser","customAction"===e)return t;try{t.pageUrl=window.location.href}catch(t){}this.isAd()?(t.adId=this.getVideoId(),t.adTitle=this.getTitle(),t.adSrc=this.getSrc(),t.adCdn=this.getCdn(),this.state.isStarted&&(t.adBitrate=this.getBitrate()||0),t.adRenditionName=this.getRenditionName(),t.adRenditionHeight=this.getRenditionHeight(),t.adRenditionWidth=this.getRenditionWidth(),t.adDuration=this.getDuration(),t.adPlayhead=this.getPlayhead(),t.adLanguage=this.getLanguage(),t.adIsMuted=this.isMuted(),t.adFps=this.getFps(),t.adPosition=this.getAdPosition(),t.adCreativeId=this.getAdCreativeId(),t.adPartner=this.getAdPartner()):(t.contentId=this.getVideoId(),t.contentTitle=this.getTitle(),t.contentSrc=this.getSrc(),t.contentCdn=this.getCdn(),t.contentPlayhead=this.getPlayhead(),t.contentIsLive=this.isLive(),this.state.isStarted&&(t.contentBitrate=this.getBitrate()||0,t.contentManifestBitrate=this.getManifestBitrate()||0,t.contentSegmentDownloadBitrate=this.getSegmentDownloadBitrate()||0,t.contentNetworkDownloadBitrate=this.getNetworkDownloadBitrate()||0),t.contentRenditionName=this.getRenditionName(),t.contentRenditionHeight=this.getRenditionHeight(),t.contentRenditionWidth=this.getRenditionWidth(),t.contentDuration=this.getDuration(),t.contentLanguage=this.getLanguage(),t.contentPlayrate=this.getPlayrate(),t.contentIsFullscreen=this.isFullscreen(),t.contentIsMuted=this.isMuted(),t.contentIsAutoplayed=this.isAutoplayed(),t.contentPreload=this.getPreload(),t.contentFps=this.getFps(),null!=this.adsTracker&&this.adsTracker.state.totalAdPlaytime>0&&(t.totalAdPlaytime=this.adsTracker.state.totalAdPlaytime)),this.state.getStateAttributes(t),this.state.isStarted&&!this.isAd()&&(this.state.trackContentBitrateState(t.contentBitrate),this.state.trackDownloadRate(t.contentNetworkDownloadBitrate),this.state.addPlayedRendition(t.contentRenditionHeight,t.contentRenditionWidth));for(let e in this.customData)t[e]=this.customData[e];if(!this.isAd()){this.state.getQoeAttributes(t);const e=t.qoe;for(let t in this.customData)e[t]=this.customData[t]}return t}sendCustom(t,e,i){i=i||{},this.sendVideoCustomAction(t,i),this.state.setTimeSinceAttribute(e)}sendPlayerReady(t){this.state.goPlayerReady()&&(t=t||{},this.sendVideoAction(N.Events.PLAYER_READY,t))}sendRequest(t){if(this.state.goRequest()){let e;this.isAd()?(e=N.Events.AD_REQUEST,this.sendVideoAdAction(e,t)):(e=N.Events.CONTENT_REQUEST,this.sendVideoAction(e,t))}}sendStart(t){if(this.state.goStart()){let e;if(this.isAd())e=N.Events.AD_START,this.parentTracker&&(this.parentTracker.state.isPlaying=!1),this.sendVideoAdAction(e,t),this.state.startAdsTime();else{e=N.Events.CONTENT_START;let i=0;this.adsTracker&&((this.adsTracker.state.isPlaying||this.adsTracker.state.isBuffering)&&(this.adsTracker.state.stopAdsTime(),this.adsTracker.state.isPlaying=!1,this.adsTracker.state.isBuffering=!1),i=this.adsTracker.state.totalAdTime()??0),this.state.setStartupTime(i),this.sendVideoAction(e,t);const s=this.getHarvester?.();s?.setBeforeDrainCallback(()=>{if(this.state){const t=this.state.getQoeAttributes({}).qoe;s.refreshQoeKpis(t,this.getViewId())}})}this.startHeartbeat(),this.state.goHeartbeat()}}sendEnd(t){if(this.state.goEnd()){let e;if(t=t||{},this.isAd()?(e=N.Events.AD_END,t.timeSinceAdRequested=this.state.timeSinceRequested.getDeltaTime(),t.timeSinceAdStarted=this.state.timeSinceStarted.getDeltaTime(),this.parentTracker&&(this.parentTracker.state.isPlaying=!0,this.parentTracker.state.timeSincePaused.reset()),this.state.stopAdsTime()):(e=N.Events.CONTENT_END,t.timeSinceRequested=this.state.timeSinceRequested.getDeltaTime(),t.timeSinceStarted=this.state.timeSinceStarted.getDeltaTime()),this.stopHeartbeat(),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t),this.parentTracker&&this.isAd()&&this.parentTracker.state.goLastAd(),this.state.goViewCountUp(),this.state.totalPlaytime=0,!this.isAd()){const t=this.getHarvester?.();t?.forceNextQoeCycle?.(),t?.setBeforeDrainCallback?.(null),this.adsTracker&&this.adsTracker.state.clearTotalAdsTime(),this.state.resetViewIdTrackedState()}}}sendPause(t){if(this.state.goPause()){let e=this.isAd()?N.Events.AD_PAUSE:N.Events.CONTENT_PAUSE;this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendResume(t){if(this.state.goResume()){let e;t=t||{},this.isAd()?(e=N.Events.AD_RESUME,t.timeSinceAdPaused=this.state.timeSincePaused.getDeltaTime()):(e=N.Events.CONTENT_RESUME,t.timeSincePaused=this.state.timeSincePaused.getDeltaTime()),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendBufferStart(t){if(this.state.goBufferStart()){let e;t=t||{},e=this.isAd()?N.Events.AD_BUFFER_START:N.Events.CONTENT_BUFFER_START,t=this.buildBufferAttributes(t),this._lastBufferType=t.bufferType,this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendBufferEnd(t){if(this.state.goBufferEnd()){let e;t=t||{},this.isAd()?(e=N.Events.AD_BUFFER_END,t.timeSinceAdBufferBegin=this.state.timeSinceBufferBegin.getDeltaTime()):(e=N.Events.CONTENT_BUFFER_END,t.timeSinceBufferBegin=this.state.timeSinceBufferBegin.getDeltaTime()),t=this.buildBufferAttributes(t),null!=this._lastBufferType&&(t.bufferType=this._lastBufferType),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t),this.state.initialBufferingHappened=!0}}buildBufferAttributes(t){return null==t.timeSinceStarted||t.timeSinceStarted<100?t.isInitialBuffering=!this.state.initialBufferingHappened:t.isInitialBuffering=!1,t.bufferType=this.state.calculateBufferType(t.isInitialBuffering),t.timeSinceResumed=this.state.timeSinceResumed.getDeltaTime(),t.timeSinceSeekEnd=this.state.timeSinceSeekEnd.getDeltaTime(),t}sendSeekStart(t){if(this.state.goSeekStart()){let e;e=this.isAd()?N.Events.AD_SEEK_START:N.Events.CONTENT_SEEK_START,this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendSeekEnd(t){if(this.state.goSeekEnd()){let e;t=t||{},this.isAd()?(e=N.Events.AD_SEEK_END,t.timeSinceAdSeekBegin=this.state.timeSinceSeekBegin.getDeltaTime()):(e=N.Events.CONTENT_SEEK_END,t.timeSinceSeekBegin=this.state.timeSinceSeekBegin.getDeltaTime()),this.isAd()?this.sendVideoAdAction(e,t):this.sendVideoAction(e,t)}}sendDownload(t){(t=t||{}).state||n.warn("Called sendDownload without { state: xxxxx }."),this.sendVideoAction(N.Events.DOWNLOAD,t),this.state.goDownload()}sendError(t){(t=t||{}).isAd=this.isAd(),this.state.goError();let e=this.isAd()?N.Events.AD_ERROR:N.Events.CONTENT_ERROR;this.sendVideoErrorAction(e,t)}sendRenditionChanged(t){(t=t||{}).timeSinceLastRenditionChange=this.state.timeSinceLastRenditionChange.getDeltaTime();const{oldBitrate:e,newBitrate:i}=t;let s;this.isAd()||void 0===e||void 0===i||(i>e?(t.shift="up",this.state.totalSwitchUps+=1):i<e?(t.shift="down",this.state.totalSwitchDowns+=1):t.shift=null),delete t.oldBitrate,delete t.newBitrate,s=this.isAd()?N.Events.AD_RENDITION_CHANGE:N.Events.CONTENT_RENDITION_CHANGE,this.isAd()?this.sendVideoAdAction(s,t):this.sendVideoAction(s,t),this.state.goRenditionChange()}sendHeartbeat(t){if(this.state.isRequested){let e,i=this.getHeartbeat();this.state._hb=!0,i=this.adjustElapsedTimeForPause(i),this.isAd()?(e=N.Events.AD_HEARTBEAT,"bitmovin-ads"===this.getPlayerName()?this.sendVideoAdAction(e,t):this.sendVideoAdAction(e,{elapsedTime:i,...t})):(e=N.Events.CONTENT_HEARTBEAT,this.sendVideoAction(e,{elapsedTime:i,...t})),this.state.goHeartbeat()}}adjustElapsedTimeForPause(t){return this.state._acc&&(t-=this.state._acc,this.state._acc=0),this.state.isPaused&&((t-=this.state.elapsedTime.getDeltaTime())<10&&(t=0),this.state.elapsedTime.start()),this.state._bufferAcc?(t-=this.state._bufferAcc,this.state._bufferAcc=0):this.state.isBuffering&&((t-=this.state.bufferElapsedTime.getDeltaTime())<5&&(t=0),this.state.bufferElapsedTime.start()),Math.max(0,t)}sendAdBreakStart(t){this.isAd()&&this.state.goAdBreakStart()&&(this.state.totalAdPlaytime=0,this.parentTracker&&(this.parentTracker.state.isPlaying=!1),this.sendVideoAdAction(N.Events.AD_BREAK_START,t))}sendAdBreakEnd(t){this.isAd()&&this.state.goAdBreakEnd()&&((t=t||{}).timeSinceAdBreakBegin=this.state.timeSinceAdBreakStart.getDeltaTime(),this.sendVideoAdAction(N.Events.AD_BREAK_END,t),this.parentTracker&&(this.parentTracker.state.isPlaying=!0),this.stopHeartbeat(),this.parentTracker&&this.isAd()&&this.parentTracker.state.goLastAd())}sendAdQuartile(t){this.isAd()&&((t=t||{}).quartile||n.warn("Called sendAdQuartile without { quartile: xxxxx }."),t.timeSinceLastAdQuartile=this.state.timeSinceLastAdQuartile.getDeltaTime(),this.sendVideoAdAction(N.Events.AD_QUARTILE,t),this.state.goAdQuartile())}sendAdClick(t){this.isAd()&&((t=t||{}).url||n.warn("Called sendAdClick without { url: xxxxx }."),this.sendVideoAdAction(N.Events.AD_CLICK,t))}}function C(t){t.type!==N.Events.AD_ERROR?this.sendVideoAdAction(t.type,t.data):this.sendVideoErrorAction(t.type,t.data)}N.Events={PLAYER_READY:"PLAYER_READY",DOWNLOAD:"DOWNLOAD",ERROR:"ERROR",CONTENT_REQUEST:"CONTENT_REQUEST",CONTENT_START:"CONTENT_START",CONTENT_END:"CONTENT_END",CONTENT_PAUSE:"CONTENT_PAUSE",CONTENT_RESUME:"CONTENT_RESUME",CONTENT_SEEK_START:"CONTENT_SEEK_START",CONTENT_SEEK_END:"CONTENT_SEEK_END",CONTENT_BUFFER_START:"CONTENT_BUFFER_START",CONTENT_BUFFER_END:"CONTENT_BUFFER_END",CONTENT_HEARTBEAT:"CONTENT_HEARTBEAT",CONTENT_RENDITION_CHANGE:"CONTENT_RENDITION_CHANGE",CONTENT_ERROR:"CONTENT_ERROR",AD_REQUEST:"AD_REQUEST",AD_START:"AD_START",AD_END:"AD_END",AD_PAUSE:"AD_PAUSE",AD_RESUME:"AD_RESUME",AD_SEEK_START:"AD_SEEK_START",AD_SEEK_END:"AD_SEEK_END",AD_BUFFER_START:"AD_BUFFER_START",AD_BUFFER_END:"AD_BUFFER_END",AD_HEARTBEAT:"AD_HEARTBEAT",AD_RENDITION_CHANGE:"AD_RENDITION_CHANGE",AD_ERROR:"AD_ERROR",AD_BREAK_START:"AD_BREAK_START",AD_BREAK_END:"AD_BREAK_END",AD_QUARTILE:"AD_QUARTILE",AD_CLICK:"AD_CLICK"};const O=N,{MAX_PAYLOAD_SIZE:I,MAX_EVENTS_PER_BATCH:P}=h;class V{constructor(){this.buffer=[],this.maxPayloadSize=I,this.maxEventsPerBatch=P,this.currentPayloadSize=0,this.totalEvents=0,this.smartHarvestPayloadThreshold=Math.floor(.6*this.maxPayloadSize),this.overflowPayloadThreshold=Math.floor(.9*this.maxPayloadSize),this.smartHarvestEventThreshold=Math.floor(.6*this.maxEventsPerBatch),this.overflowEventThreshold=Math.floor(.9*this.maxEventsPerBatch),this.onSmartHarvestTrigger=null}addOrReplaceByActionName(t,e){const i=this.buffer.findIndex(e=>e.actionName===t);try{return-1===i?this.add(e):this.add(e,i),!0}catch(t){return n.error("Failed to set or replace the event to buffer:",t.message),!1}}addOrReplaceByActionNameAndViewId(t,e,i){const s=this.buffer.findIndex(i=>i.actionName===t&&i.viewId===e);try{return-1===s?this.add(i):this.add(i,s),!0}catch(t){return n.error("Failed to set or replace the event to buffer:",t.message),!1}}findByActionNameAndViewId(t,e){return this.buffer.find(i=>i.actionName===t&&i.viewId===e)||null}findByActionName(t){return this.buffer.find(e=>e.actionName===t)||null}add(t,e){try{const i=E(t),s=this.currentPayloadSize+i>=this.maxPayloadSize,r=this.totalEvents+1>=this.maxEventsPerBatch;if((s||r)&&this.makeRoom(i),null!=e&&e>-1){const s=E(this.buffer[e]);this.buffer[e]=t,this.currentPayloadSize+=i-s}else this.buffer.push(t),this.totalEvents++,this.currentPayloadSize+=i;return this.checkSmartHarvestTrigger(),!0}catch(t){return n.error("Failed to add event to buffer:",t.message),!1}}checkSmartHarvestTrigger(){const t=this.currentPayloadSize/this.maxPayloadSize,e=this.totalEvents/this.maxEventsPerBatch,i=this.currentPayloadSize>=this.overflowPayloadThreshold,s=this.totalEvents>=this.overflowEventThreshold;if(i||s){const s=i?`payload ${this.currentPayloadSize}/${this.maxPayloadSize} bytes (${Math.round(100*t)}%)`:`events ${this.totalEvents}/${this.maxEventsPerBatch} (${Math.round(100*e)}%)`;n.warn(`OVERFLOW PREVENTION: ${s} - Emergency harvest triggered`),this.onSmartHarvestTrigger&&"function"==typeof this.onSmartHarvestTrigger&&this.onSmartHarvestTrigger("overflow",90)}else{const t=this.currentPayloadSize>=this.smartHarvestPayloadThreshold,e=this.totalEvents>=this.smartHarvestEventThreshold;(t||e)&&this.onSmartHarvestTrigger&&"function"==typeof this.onSmartHarvestTrigger&&this.onSmartHarvestTrigger("smart",60)}}setSmartHarvestCallback(t){this.onSmartHarvestTrigger=t}drain(){try{const t=this.buffer.splice(0);return this.totalEvents=0,this.currentPayloadSize=0,t}catch(t){return n.error("Failed to drain events from buffer:",t.message),[]}}isEmpty(){return 0===this.totalEvents}size(){return this.totalEvents}clear(){this.buffer=[],this.totalEvents=0}makeRoom(t){if(t>this.maxPayloadSize)n.error("Event dropped: Event size exceeds maximum payload size.");else for(;(this.totalEvents>=this.maxEventsPerBatch||this.currentPayloadSize+t>=this.maxPayloadSize)&&this.buffer.length>0;){const t=E(this.buffer.shift());this.totalEvents--,this.currentPayloadSize-=t,n.warn("Event buffer full, oldest event removed.")}}}const{MAX_PAYLOAD_SIZE:L,MAX_EVENTS_PER_BATCH:H}=h;class F{constructor(){this.retryQueue=[],this.maxQueueSize=H,this.maxQueueSizeBytes=L}addFailedEvents(t){try{const e=Array.isArray(t)?t:[t];n.notice(`Adding ${e.length} failed events to retry queue`,{queueSizeBefore:this.retryQueue.length});for(const t of e){this.retryQueue.length>=this.maxQueueSize&&this.evictOldestEvent();const e=E(t);for(;E(this.retryQueue)+e>this.maxQueueSizeBytes;)this.evictOldestEvent();this.retryQueue.push({...t})}}catch(t){n.error("Failed to add events to retry queue:",t.message)}}discardEvent(t,e){n.warn("Discarded event",{reason:e,eventType:t.eventType})}evictOldestEvent(){if(this.retryQueue.length>0){const t=this.retryQueue.shift();this.discardEvent(t,"Queue full - evicted oldest")}}getRetryEventsToFit(t,e){const i=[];let s=0,r=0;for(let a=this.retryQueue.length-1;a>=0;a--){const n=this.retryQueue[a];if(r>=e)break;const o=E(n);if(s+o>t)break;i.unshift(n),s+=o,r++,this.retryQueue.splice(a,1)}return i}getQueueSize(){return this.retryQueue.length}clear(){this.retryQueue=[]}}class Q{async send(t,e){const{url:i,payload:s,options:r={}}=t;try{if(!i||!s)throw new Error("URL and payload are required");const t={url:i,payload:s,options:r,callback:e};await this.executeRequest(t)}catch(t){n.error("Failed to send request:",t.message),e({retry:!1,status:0,error:t.message})}}async executeRequest(t){const{url:e,payload:i,options:s,callback:r}=t,a=Date.now();try{const r=(o=JSON.stringify(i.body),h=window.NRVIDEO?.config?.obfuscate,h&&0!==h.length?h.reduce((t,e)=>{let i;try{if(e.regex instanceof RegExp){const t=e.regex.flags.includes("g")?e.regex.flags:e.regex.flags+"g";i=new RegExp(e.regex.source,t)}else i=new RegExp(e.regex,"g")}catch(i){return n.warn("applyObfuscationRules: invalid regex, skipping rule:",e.regex,i.message),t}return t.replace(i,e.replacement)},o):o);if(s.isFinalHarvest&&navigator.sendBeacon){const i=await this.sendWithBeacon(e,r),s={success:i,status:i?204:0};return void this.handleRequestComplete(t,s,a)}const l=await this.fetchWithTimeout(e,{method:"POST",body:r,headers:{"Content-Type":"application/json"},keepalive:s.isFinalHarvest},1e4),d={success:l.ok,status:l.status,statusText:l.statusText};this.handleRequestComplete(t,d,a)}catch(e){const i={success:!1,status:0,error:e.message};this.handleRequestComplete(t,i,a)}var o,h}handleRequestComplete(t,e){const{callback:i}=t;i({retry:!e.success&&(0===e.status||function(t){switch(t){case 408:case 429:case 500:return!0;case 401:case 403:case 404:return!1}return t>=502&&t<=504||t>=512&&t<=530}(e.status)),status:e.status,error:e.error})}async sendWithBeacon(t,e){try{return navigator.sendBeacon(t,e)}catch(t){return n.warn("sendBeacon failed, falling back to fetch:",t.message),!1}}async fetchWithTimeout(t,e,i){const s=new AbortController,r=setTimeout(()=>s.abort(),i);try{const i=await fetch(t,{...e,signal:s.signal});return clearTimeout(r),i}catch(t){if(clearTimeout(r),"AbortError"===t.name)throw new Error(`Request timeout after ${i}ms`);throw t}}}function x(t,e){const i=t[e.viewId];if(!i)return!1;for(const t of h.QOE_KPI_KEYS)if(e[t]!==i[t])return!1;return!0}function q(t,e){const i={};for(const t of h.QOE_KPI_KEYS)i[t]=e[t];t[e.viewId]=i}class U{constructor(t){this.eventBuffer=t,this.retryQueueHandler=new F,this.httpClient=new Q,this.fallBackUrl="",this.retryCount=0,this.eventBuffer instanceof V&&this.eventBuffer.setSmartHarvestCallback((t,e)=>this.triggerSmartHarvest(t,e)),this.harvestCycle=h.INTERVAL,this.isHarvesting=!1,this.qoeCycleCount=1,this.forceNextQoeCycle=!1,this.beforeDrainCallback=null,this._lastSentQoeKpis={},this.timer=function({interval:t,onTick:e,errorLabel:i}){let s=!1,r=null,a=t;function o(){s&&(r=setTimeout(async()=>{r=null;try{await e()}catch(t){n.error(`${i}: scheduled tick failed:`,t.message)}finally{s&&o()}},a))}return{start(){s||(s=!0,o())},stop(){s=!1,r&&(clearTimeout(r),r=null)},cancelAndReschedule(){r&&(clearTimeout(r),r=null),s&&o()},updateInterval(t){"number"!=typeof t||t<=0||(a=t,s&&r&&(clearTimeout(r),r=null,o()))},isRunning:()=>s}}({interval:this.harvestCycle,onTick:()=>this.onHarvestInterval(),errorLabel:"HarvestScheduler"}),this.setupPageLifecycleHandlers()}get isStarted(){return this.timer.isRunning()}startScheduler(){this.timer.isRunning()?n.warn("Harvest scheduler is already started"):(n.notice("Starting harvest scheduler",{harvestCycle:this.harvestCycle,eventBufferSize:this.eventBuffer?this.eventBuffer.size():0}),this.timer.start())}stopScheduler(){this.timer.isRunning()&&(this.timer.stop(),n.notice("Harvest scheduler stopped"))}async triggerSmartHarvest(t,e){if(n.notice(`${t} harvest triggered at ${e}% threshold`,{type:t,threshold:e}),this.eventBuffer&&!this.eventBuffer.isEmpty())try{await this.triggerHarvest({})}catch(e){n.error(`${t} harvest failed:`,e.message)}finally{this.timer.cancelAndReschedule()}}async onHarvestInterval(){const t=this.eventBuffer&&!this.eventBuffer.isEmpty(),e=this.retryQueueHandler&&this.retryQueueHandler.getQueueSize()>0;(t||e)&&await this.triggerHarvest({})}async triggerHarvest(t={}){if(this.isHarvesting)return{success:!1,reason:"harvest_in_progress"};this.isHarvesting=!0;try{let e=this.drainEvents(t);if(t.isFinalHarvest){const t=h.MAX_BEACON_SIZE;E(e)>t&&(e=this.trimEventsToFit(e,t))}const i=await this.sendChunk(e,t,!0);return{success:i.success,totalChunks:1,results:[i]}}catch(t){return n.error("Harvest cycle failed:",t.message),this.handleHarvestFailure(t),{success:!1,error:t.message}}finally{this.isHarvesting=!1}}trimEventsToFit(t,e){if(0===t.length)return t;const i=[];let s=0;for(let r=t.length-1;r>=0;r--){const a=t[r],n=E({ins:[a,...i]});n>e||(i.unshift(a),s=n)}const r=t.length-i.length;if(r>0){const a=t.slice(0,r);n.warn(`Discarded ${r} events to fit beacon size limit`,{originalCount:t.length,trimmedCount:i.length,finalSize:s,maxSize:e}),this.retryQueueHandler&&this.retryQueueHandler.addFailedEvents(a)}return i}drainEvents(t={}){const e=window.NRVIDEO?.config?.qoeIntervalFactor??1,i=!!t.isFinalHarvest||this.forceNextQoeCycle,s=(this.qoeCycleCount-1)%e==0||i;if(this.forceNextQoeCycle&&(this.forceNextQoeCycle=!1),this.beforeDrainCallback&&"function"==typeof this.beforeDrainCallback)try{this.beforeDrainCallback()}catch(t){n.error("Before drain callback failed:",t.message)}let r=function(t,e,i){if(e)return t;const s=[];for(const e of t)e.actionName===m.Events.QOE_AGGREGATE?i.add(e):s.push(e);return s}(this.eventBuffer.drain(),s,this.eventBuffer);this.qoeCycleCount++,function(t,e,i){for(let s=t.length-1;s>=0;s--){const r=t[s];r.actionName===m.Events.QOE_AGGREGATE&&(!i&&x(e,r)?t.splice(s,1):q(e,r))}}(r,this._lastSentQoeKpis,i);let a=[...r],o=E(r);if(this.retryQueueHandler&&this.retryQueueHandler.getQueueSize()>0){const t=h.MAX_PAYLOAD_SIZE-o,e=h.MAX_EVENTS_PER_BATCH-a.length;if(t>0&&e>0){const i=this.retryQueueHandler.getRetryEventsToFit(t,e);i.length>0&&(a=[...i,...a])}}return a}async sendChunk(t,e,i){const s={url:function(t){try{if(!window.NRVIDEO||!window.NRVIDEO.info)throw new Error("NRVIDEO info is not available.");let{beacon:e,licenseKey:i,applicationID:s}=window.NRVIDEO.info;if(!e||!i)throw new Error("Options object provided by New Relic is not correctly initialized");return s?`https://${t||e}/ins/1/${i}?a=${s}&v=${l.rE}&ref=${window.location.href}&ca=VA`:`https://${t||e}/ins/1/${i}?&v=${l.rE}&ref=${window.location.href}&ca=VA`}catch(t){return console.error(t.message),null}}(this.fallBackUrl),payload:{body:{ins:t}},options:{...e,isLastChunk:i}};return new Promise(e=>{this.httpClient.send(s,i=>{i.retry?this.handleRequestFailure(t):(this.retryCount=0,this.fallBackUrl=""),e({success:!i.retry,status:i.status,error:i.error,chunk:t,eventCount:t.length})})})}handleRequestFailure(t){this.retryQueueHandler.addFailedEvents(t),"US"===window.NRVIDEO?.info?.region&&(this.retryCount++,this.retryCount>5?(this.retryCount=0,this.fallBackUrl=""):this.retryCount>=2&&(this.fallBackUrl=h.COLLECTOR.US[1]))}handleHarvestFailure(t){n.warn("Harvest failure handled",{error:t.message})}updateHarvestInterval(t){"number"!=typeof t||isNaN(t)?n.warn("Invalid newInterval provided to updateHarvestInterval"):t<1e3||t>3e5?n.warn("newInterval out of bounds (1000-300000), ignoring"):this.harvestCycle!==t&&(this.harvestCycle=t,n.notice("Updated harvestCycle:",this.harvestCycle),this.timer.updateInterval(t))}setupPageLifecycleHandlers(){let t=!1;const e=()=>{t||(t=!0,this.triggerHarvest({isFinalHarvest:!0,force:!0}))};document.addEventListener("visibilitychange",()=>{document.hidden&&e()}),window.addEventListener("pagehide",()=>{e()}),window.addEventListener("beforeunload",()=>{e()})}}const z=new class{constructor(){this.isInitialized=!1,this.harvestScheduler=null,this.eventBuffer=null}initialize(){if(this.isInitialized)n.warn("Video analytics agent already initialized");else try{this.eventBuffer=new V,this.harvestScheduler=new U(this.eventBuffer),this.harvestScheduler.startScheduler(),this.isInitialized=!0,n.notice("Video analytics agent initialized successfully")}catch(t){n.error("Failed to initialize video analytics agent:",t.message)}}addEvent(t){this.isInitialized||(n.warn("Video analytics agent not initialized, initializing now"),this.initialize());try{return function(t,e){return!!e&&(e.actionName===m.Events.QOE_AGGREGATE?e.viewId?t.addOrReplaceByActionNameAndViewId(m.Events.QOE_AGGREGATE,e.viewId,e):t.addOrReplaceByActionName(m.Events.QOE_AGGREGATE,e):t.add(e))}(this.eventBuffer,t)}catch(t){return n.error("Failed to add event to harvesting system:",t.message),!1}}setHarvestInterval(t){this.isInitialized||this.initialize(),this.harvestScheduler.updateHarvestInterval(t)}forceNextQoeCycle(){this.harvestScheduler&&(this.harvestScheduler.forceNextQoeCycle=!0)}setBeforeDrainCallback(t){this.harvestScheduler&&(this.harvestScheduler.beforeDrainCallback=t)}refreshQoeKpis(t,e){!function(t,e,i){if(!t||!e)return;const s=i?t.findByActionNameAndViewId(m.Events.QOE_AGGREGATE,i):t.findByActionName(m.Events.QOE_AGGREGATE);if(!s)return;const r={...s};for(const t of h.QOE_KPI_KEYS)t in e&&(r[t]=e[t]);i?t.addOrReplaceByActionNameAndViewId(m.Events.QOE_AGGREGATE,i,r):t.addOrReplaceByActionName(m.Events.QOE_AGGREGATE,r)}(this.eventBuffer,t,e)}};var G;G=z,T["Browser"]=G;const M=z,K={Constants:h,Chrono:u,Log:n,Emitter:d,Tracker:m,VideoTracker:O,VideoTrackerState:k,Core:D,version:l.rE,NrVideoEventAggregator:V,RetryQueueHandler:F,OptimizedHttpClient:Q,HarvestScheduler:U,recordEvent:v};module.exports=e})();
3
3
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * @license Apache-2.0
3
- * @newrelic/video-core 5.0.0
3
+ * @newrelic/video-core 5.0.1
4
4
  * Copyright New Relic <http://newrelic.com/>
5
5
  * @author Jordi Aguilar
6
6
  */