/* * Application Insights plugin for Azure Media Player - Microsoft Sample Code - Copyright (c) 2016 - Licensed MIT * Attribution: Google Analytics plugin for Azure Media Player - Microsoft Sample Code - Copyright (c) 2015 - Licensed MIT * Attribution: "videojs-ga - v0.4.2" - Copyright (c) 2015 Michael Bensoussan - Licensed MIT */ (function () { var e = [].indexOf || function (e) { for (var t = 0, i = this.length; i > t; t++) if (t in this && this[t] === e) return t; return -1 }; amp.plugin("appInsights", function (t) { function i(e) { var t = "unknown"; return e && (t = e.split("//")[1], t.match(/.ism\/manifest/i) && (t = t.split(/.ism\/manifest/i)[0] + ".ism/manifest")), t } function a(e) { var t = "unknown"; if (e) switch (e.toLowerCase()) { case "aes": t = "aes"; break; case "playready": t = "drm"; break; case "widevine": t = "drm"; break; case "fairplay": t = "drm"; break; default: t = "none" } return t } function n() { var e = myPlayer.buffered(), t = myPlayer.currentTime(); return e ? Math.max(0, e.end(e.length - 1) - t) : void 0 } function r() { S.unloaddatasent || (S.unloaddatasent = !0, s()) } function s() { var e = M.totalSeconds, t = M.totalSecondsFullscreen, i = Math.min(w, 100); if (o.isLive() || (e = L.getTotalPlayTime(), t = L.totalSecondsFullscreen, i = Math.min(Math.round(L.getTotalUniquePlayTime() / o.duration() * 100), 100)), 0 == S.loadTime && S.updateLoadTime(), I.state && I.send(), m.playTime && M.send(), m.percentsPlayed && (o.isLive() || J("percentPlayed", { percentage: w })), m.bitrateQuality && O.send(), m.buffering && J("rebufferTime", { count: I.count, totalRebufferTime: I.bufferingTimeTotal }), m.playbackSummary) { var a = { playTime: e, fullscreenTime: t, rebufferCount: I.count, rebufferTime: I.bufferingTimeTotal }; if (S.loadTime <= 1e5 && (a.loadTime = S.loadTime), o.isLive() || (a.percentPlayed = i), O.downloadedChunks > 0) { var n = Math.round(O.sumBitrate / O.downloadedChunks); a.avgBitrate = n } O.videoBuffer && (a.failedDownloads = O.failedChunks), o.error() && (a.errorCode = o.error().code.toString(16)), J("playbackSummary", a) } appInsights.flush() } var d, o = this, u = .1; null == t && (t = {}); var l = {}; this.options()["data-setup"] && (d = JSON.parse(this.options()["data-setup"]), d.ga && (l = d.ga)), appInsights.config.maxBatchInterval = sendInterval = t.sendInterval || l.sendInterval || 15, appInsights.config.disableFlushOnBeforeUnload = !0; var f = ["playbackSummary"], c = t.metricsToTrack || l.metricsToTrack || f, m = {}; c.forEach(function (e, t, i) { m[e] = !0 }); var h = t.percentsPlayedInterval || l.percentsPlayedInterval || 20; if (t.debug = t.debug || !1, t.userId || l.userId) { var p = t.userId || l.userId, T = t.accountId || l.accountId || null; appInsights.setAuthenticatedUserContext(p, T), t.debug && console.log("Authenticated User Context set as userId: " + p + " and accountId: " + T) } var g = t.streamId || l.streamId || null, v = t.trackSdn || l.trackSdn || !1, y = [], b = -1, w = 0, k = !1, B = null, S = { loadTime: 0, loadTimeStart: (new Date).getTime(), firstPlay: !1, endedReached: !1, videoElementUsed: !1, unloaddatasent: !1, updateLoadTime: function () { this.loadTime = Math.abs((new Date).getTime() - this.loadTimeStart), t.debug && console.log("Player Load Time determined: " + this.loadTime + "ms"), this.send() }, send: function () { m.loaded && this.loadTime < 1e5 && J("loadTime", { time: this.loadTime }) }, reset: function () { this.loadTime = 0, this.loadTimeStart = (new Date).getTime(), this.firstPlay = !1, this.endedReached = !1; t.streamId || l.streamId || null } }, I = { state: !1, bufferingTime: 0, bufferingTimeStart: 0, bufferingTimeTotal: 0, count: 0, enterBuffering: function () { S.firstPlay && (this.bufferingTimeStart = (new Date).getTime(), this.state = !0, this.count++, t.debug && console.log("Entering buffering state...")) }, send: function () { if (this.state) { this.bufferingTime = Math.abs((new Date).getTime() - this.bufferingTimeStart); var e = Math.round(o.currentTime()); 0 !== e && m.buffering && (bufferingMetrics = { currentTime: e, bufferingTime: this.bufferingTime }, O.videoBuffer && (bufferingMetrics.perceivedBandwidth = O.videoBuffer.perceivedBandwidth), n && (bufferingMetrics.buffered = n), J("buffering", bufferingMetrics)), this.bufferingTimeTotal += this.bufferingTime, this.state = !1, t.debug && console.log("Exiting buffering state. Time spent rebuffering was " + this.bufferingTime + "ms") } }, reset: function () { this.bufferingTime = 0, this.state = !1 }, fullReset: function () { this.bufferingTime = 0, this.bufferingTimeStart = 0, this.bufferingTimeTotal = 0, this.count = 0, this.state = !1 } }, O = { videoBuffer: null, audioBuffer: null, sumBitrate: 0, sumPerceivedBandwidth: 0, sumMeasuredBandwidth: 0, downloadedChunks: 0, failedChunks: 0, completed: function () { o.currentDownloadBitrate() && (this.downloadedChunks += 1, this.sumBitrate += o.currentDownloadBitrate(), this.videoBuffer && (m.downloadInfo && J("downloadCompleted", { bitrate: o.currentDownloadBitrate(), measuredBandwidth: this.videoBuffer.downloadCompleted.measuredBandwidth, perceivedBandwidth: this.videoBuffer.perceivedBandwidth }), this.sumPerceivedBandwidth += this.videoBuffer.perceivedBandwidth, this.sumMeasuredBandwidth += this.videoBuffer.downloadCompleted.measuredBandwidth)) }, failed: function (e) { if (m.downloadInfo) { if ("audio" == e.toLowerCase()) var t = 0, i = this.audioBuffer.downloadFailed.code.toString(8); else var t = 1, i = this.videoBuffer.downloadFailed.code.toString(8); J("downloadFailed", { isVideo: t, error: i }) } this.failedChunks++ }, send: function () { if (m.bitrateQuality && this.downloadedChunks > 0) { if (bitrateQualityMetrics = { avgBitrate: this.sumBitrate / this.downloadedChunks }, this.videoBuffer) { var e = Math.round(this.sumMeasuredBandwidth / this.downloadedChunks), t = Math.round(this.sumPerceivedBandwidth / this.downloadedChunks); bitrateQualityMetrics.avgMeasuredBandwidth = e, bitrateQualityMetrics.avgPerceivedBandwidth = t } J("bitrateQuality", bitrateQualityMetrics) } }, reset: function () { this.videoBuffer = null, this.audioBuffer = null, this.sumBitrate = 0, this.sumPerceivedBandwidth = 0, this.sumMeasuredBandwidth = 0, this.downloadedChunks = 0, this.failedChunks = 0 } }, L = { startTime: 0, endTime: 0, added: !1, lastCheckedTime: 0, arrayOfTimes: [], overlappingArrayOfTimes: [], sorted: !1, totalSecondsFullscreen: 0, sortAlgorithm: function (e, t) { return e[0] < t[0] ? -1 : e[0] > t[0] ? 1 : 0 }, update: function (e) { e == this.lastCheckedTime + 1 && o.isFullscreen() && (this.totalSecondsFullscreen += 1), e != this.lastCheckedTime && e != this.lastCheckedTime + 1 && (this.endTime = this.lastCheckedTime, this.push(), this.startTime = e, this.added = !1), this.lastCheckedTime = e }, push: function () { this.arrayOfTimes.push([this.startTime, this.endTime]), this.added = !0 }, getOverlappingArrayOfTimes: function () { if (this.added || (this.endTime = Math.round(o.currentTime()), this.push()), this.arrayOfTimes = this.arrayOfTimes.sort(this.sortAlgorithm), this.arrayOfTimes.length > 1) { this.overlappingArrayOfTimes.push(this.arrayOfTimes[0]); for (var e = 1; e < this.arrayOfTimes.length; e++) if (this.arrayOfTimes[e][0] <= this.overlappingArrayOfTimes[this.overlappingArrayOfTimes.length - 1][1]) { if (this.arrayOfTimes[e][1] > this.overlappingArrayOfTimes[this.overlappingArrayOfTimes.length - 1][1]) { var t = this.overlappingArrayOfTimes[this.overlappingArrayOfTimes.length - 1][0], i = this.arrayOfTimes[e][1]; this.overlappingArrayOfTimes.pop(), this.overlappingArrayOfTimes.push([t, i]) } } else this.overlappingArrayOfTimes.push(this.arrayOfTimes[e]) } else this.overlappingArrayOfTimes = this.arrayOfTimes; this.sorted = !0 }, getTotalPlayTime: function () { this.sorted || this.getOverlappingArrayOfTimes(); for (var e = 0, t = 0; t < this.arrayOfTimes.length; t++) e += this.arrayOfTimes[t][1] - this.arrayOfTimes[t][0]; return Math.round(e) }, getTotalUniquePlayTime: function () { this.sorted || this.getOverlappingArrayOfTimes(); for (var e = 0, t = 0; t < this.overlappingArrayOfTimes.length; t++) e += this.overlappingArrayOfTimes[t][1] - this.overlappingArrayOfTimes[t][0]; return Math.round(e) }, reset: function () { this.startTime = 0, this.endTime = 0, this.totalSecondsFullscreen = 0, this.added = !1, this.sorted = !1, this.arrayOfTimes = [], this.overlappingArrayOfTimes = [] } }, M = { totalSeconds: 0, totalSecondsFullscreen: 0, start: function () { var e = this; this.interval = setInterval(function () { e.totalSeconds += 1, o.isFullscreen() && (e.totalSecondsFullscreen += 1) }, 1e3) }, pause: function () { clearInterval(this.interval), delete this.interval }, resume: function () { this.interval || this.start() }, send: function () { J("playTime", { time: this.totalSeconds }) }, reset: function () { this.totalSeconds = 0, this.totalSecondsFullscreen = 0 } }, P = function () { S.videoElementUsed && s(), S.reset(), I.fullReset(), M.reset(), L.reset(), O.reset(), w = 0, b = null, B = null, g = null, t.debug && console.log("Resetting App Insight Plugin Config") }, C = function () { g = t.streamId || l.streamId || null, g || (g = i(o.currentSrc())), t.debug && console.log("streamId set as: " + g), B = o.currentProtectionInfo() ? a(o.currentProtectionInfo()[0].type) : "none", t.debug && console.log("protectionInfo set as: " + B), m.loaded && J("loadedmetadata"), S.videoElementUsed = !0 }, A = function () { S.updateLoadTime() }, E = function () { if (g) { var t = Math.round(o.currentTime()); if ((m.playbackSummary || m.playTime) && L.update(t), m.percentsPlayed && !this.isLive()) { var i = Math.round(o.duration()), a = Math.round(t / i * 100); a != b && a % h == 0 && 100 >= a && (e.call(y, a) < 0 && (0 !== a && (w += h), y.push(a)), J("percentReached", { percent: a })), b = a } (m.bitrateQuality || m.playbackSummary) && !O.videoBuffer && o.currentDownloadBitrate() && O.completed() } }, F = function () { if (m.play) { var e; e = Math.round(o.currentTime()), J("play", { currentTime: e }) } }, D = function () { k = !1, S.firstPlay || (m.viewed && J("viewed"), S.firstPlay = !0), (m.buffering || m.playbackSummary) && I.send(), (m.playTime || m.playbackSummary) && o.isLive() && (0 == M.totalSeconds ? M.start() : M.resume()) }, Q = function () { if ((m.playTime || m.playbackSummary) && o.isLive() && M.pause(), m.pause) { var e = Math.round(o.currentTime()), t = Math.round(o.duration()); e === t || k || m.pause && J("pause", { currentTime: e }) } }, R = function () { if (k = !0, m.seek) { var e = Math.round(o.currentTime()); J("seek", { currentTime: e }) } }, U = function () { (m.playTime || m.playbackSummary) && o.isLive() && M.pause(), m.ended && (S.endedReached || (J("ended"), S.endedReached = !0)) }, x = function () { I.enterBuffering() }, N = function () { var e = Math.round(o.currentTime()); ("function" == typeof o.isFullscreen ? o.isFullscreen() : void 0) || ("function" == typeof o.isFullScreen ? o.isFullScreen() : void 0) ? J("fullscreen", { enter: 1, currentTime: e }) : J("fullscreen", { enter: 0, currentTime: e }) }, _ = function () { if (0 == S.loadTime && S.updateLoadTime(), (m.playTime || m.playbackSummary) && o.isLive() && M.pause(), m.error) { var e = Math.round(o.currentTime()), t = o.error().code.toString(16); J("error", { code: t, currentTime: e }) } }, J = function (e, i) { if (window.appInsights) { var n = { StreamId: g || "unknown", PluginVersion: u, PlayerVersion: o.getAmpVersion() || "unknown", PlaybackTech: o.currentTechName() || "unknown", MimeType: o.currentType() || "unknown", ProtectionType: B || "unkown", isLive: o.isLive() ? "live" : "vod" }; if (!g) { var r = "unknown"; o.options_.sourceList[0] && (r = o.options_.sourceList[0].src.split("//")[1], r.match(/.ism\/manifest/i) && (r = r.split(/.ism\/manifest/i)[0] + ".ism/manifest")), n.StreamId = r } if (!B) { var s = "unknown"; o.options_.sourceList[0] && (s = o.options_.sourceList[0].protectionInfo ? a(o.options_.sourceList[0].protectionInfo[0].type) : "none"), n.ProtectionType = s } v && (n.Sdn = o.options_.sdn.name || "none"); var d = i || {}; appInsights.trackEvent(e, n, d), t.debug && console.log("sent to Application Insights...'event': " + e + "\n'properties': " + JSON.stringify(n) + "\n'metrics': " + JSON.stringify(d)), "error" == e && (n.errorMessage = o.error().message, appInsights.trackTrace(e, n, d), t.debug && console.log("sent to Application Insights Error Trace...'message': " + e + "\n'properties': " + JSON.stringify(n) + "\n'metrics': " + JSON.stringify(d))) } else t.debug && console.log("App Insights not detected") }; o.addEventListener("sourceset", P), o.addEventListener("loadedmetadata", C), o.addEventListener("canplaythrough", A), (m.bitrateQuality || m.downloadInfo || m.playbackSummary) && o.addEventListener("loadedmetadata", function () { O.videoBuffer = o.videoBufferData(), O.videoBuffer && (O.videoBuffer.addEventListener("downloadcompleted", function () { O.completed() }), O.videoBuffer.addEventListener("downloadfailed", function () { O.failed("video") })), O.audioBuffer = o.audioBufferData(), O.audioBuffer && O.audioBuffer.addEventListener("downloadfailed", function () { O.failed("audio") }) }), (m.percentsPlayed || m.bitrateQuality || m.playbackSummary || m.playTime) && o.addEventListener("timeupdate", E), o.addEventListener("playing", D), (m.playTime || m.bitrateQuality || m.playbackSummary) && (window.addEventListener("onbeforeunload", r, !1), window.addEventListener("pagehide", r, !1), o.tempDispose = o.dispose, o.dispose = function () { s(), o.tempDispose() }), (m.error || m.playTime || m.playbackSummary) && o.addEventListener("error", _), (m.end || m.playTime || m.playbackSummary) && o.addEventListener("ended", U), m.play && o.addEventListener("play", F), (m.pause || m.playTime || m.buffering || m.playbackSummary) && o.addEventListener("pause", Q), (m.buffering || m.playbackSummary) && o.addEventListener("waiting", x), (m.buffering || m.seek || m.playbackSummary) && o.addEventListener("seeked", R), m.fullscreen && o.addEventListener("fullscreenchange", N) }) }).call(this);