@gumlet/insights-js-core 1.1.4 → 1.1.6

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.
Files changed (53) hide show
  1. package/build/release/gumlet-insights.min.js +2 -0
  2. package/build/release/gumlet-insights.min.js.LICENSE.txt +10 -0
  3. package/build/release/package.json +1 -0
  4. package/package.json +3 -2
  5. package/.github/workflows/main.yml +0 -87
  6. package/.gitlab-ci.yml +0 -54
  7. package/bitbucket-pipelines.yml +0 -35
  8. package/docs/payload-documentation.md +0 -72
  9. package/html/bitmovin.html +0 -82
  10. package/html/dashjs.html +0 -55
  11. package/html/hlsjs.html +0 -72
  12. package/html/html5.html +0 -59
  13. package/html/shaka.html +0 -102
  14. package/html/videojs.html +0 -67
  15. package/index.html +0 -73
  16. package/jest.config.js +0 -187
  17. package/js/adapters/Bitmovin7Adapter.js +0 -352
  18. package/js/adapters/BitmovinAdapter.js +0 -198
  19. package/js/adapters/DashjsAdapter.js +0 -140
  20. package/js/adapters/HTML5Adapter.js +0 -774
  21. package/js/adapters/HlsjsAdapter.js +0 -152
  22. package/js/adapters/ShakaAdapter.js +0 -81
  23. package/js/adapters/VideoJsAdapter.js +0 -455
  24. package/js/analyticsStateMachines/Bitmovin7AnalyticsStateMachine.js +0 -471
  25. package/js/analyticsStateMachines/BitmovinAnalyticsStateMachine.js +0 -299
  26. package/js/analyticsStateMachines/HTML5AnalyticsStateMachine.js +0 -443
  27. package/js/analyticsStateMachines/VideoJsAnalyticsStateMachine.js +0 -503
  28. package/js/cast/CastClient.js +0 -50
  29. package/js/cast/CastReceiver.js +0 -37
  30. package/js/core/AdapterFactory.js +0 -41
  31. package/js/core/Analytics.js +0 -1367
  32. package/js/core/AnalyticsStateMachineFactory.js +0 -36
  33. package/js/core/GumletInsightsExport.js +0 -81
  34. package/js/enums/CDNProviders.js +0 -11
  35. package/js/enums/Events.js +0 -32
  36. package/js/enums/GumletEnum.js +0 -19
  37. package/js/enums/MIMETypes.js +0 -30
  38. package/js/enums/Players.js +0 -11
  39. package/js/enums/StreamTypes.js +0 -15
  40. package/js/utils/EventsCall.js +0 -22
  41. package/js/utils/HttpCall.js +0 -57
  42. package/js/utils/LicenseCall.js +0 -18
  43. package/js/utils/Logger.js +0 -40
  44. package/js/utils/PlayerDetector.js +0 -75
  45. package/js/utils/PlayerInitCall.js +0 -22
  46. package/js/utils/SessionCreationCall.js +0 -22
  47. package/js/utils/Settings.js +0 -3
  48. package/js/utils/Utils.js +0 -195
  49. package/precommit.bash +0 -8
  50. package/tests/stage1.test.js +0 -50
  51. package/webpack.config.debug.js +0 -34
  52. package/webpack.config.js +0 -40
  53. package/webpack.config.release.js +0 -62
@@ -1,774 +0,0 @@
1
- import Events from '../enums/Events';
2
- import {getMIMETypeFromFileExtension} from '../enums/MIMETypes';
3
- import {getStreamTypeFromMIMEType} from '../enums/StreamTypes';
4
- import {Players} from '../enums/Players';
5
-
6
- const BUFFERING_TIMECHANGED_TIMEOUT = 1000;
7
-
8
- /**
9
- * @typedef QualityLevelInfo
10
- * @type {Object}
11
- * @prop {bitrate} number
12
- * @prop {width} number
13
- * @prop {height} number
14
- */
15
-
16
- /**
17
- * Base-class for all HTML5 media based playback engines
18
- * @class
19
- * @constructor
20
- */
21
- export class HTML5Adapter {
22
-
23
- /**
24
- * @constructs
25
- * @param {HTMLMediaElement} mediaElement
26
- * @param {function} eventCallback
27
- * @param {AnalyticsStateMachine} stateMachine
28
- */
29
- constructor(mediaElement, eventCallback, stateMachine, playerName = null) {
30
- /**
31
- * @public
32
- * @member {AnalyticsEventCallback}
33
- */
34
- this.eventCallback = eventCallback;
35
-
36
- if (playerName) {
37
- this.playerSoftwareName = playerName;
38
- }else {
39
- this.playerSoftwareName = Players.HTML;
40
- }
41
-
42
- /**
43
- * @member {AnalyticsStateMachine}
44
- */
45
- this.stateMachine = stateMachine;
46
-
47
- /**
48
- * @public
49
- * @member {HTMLMediaElement}
50
- */
51
- this.mediaEl = mediaElement;
52
-
53
- /**
54
- * @public
55
- * @member {function[]}
56
- */
57
- this.mediaElEventHandlers = [];
58
-
59
- /**
60
- * @private
61
- * @member {number}
62
- */
63
- this.analyticsBitrate_ = -1;
64
-
65
- /**
66
- * @private
67
- * @member {string}
68
- */
69
- this.audioCodec_ = "";
70
-
71
- /**
72
- * @private
73
- * @member {string}
74
- */
75
- this.videoCodec_ = "";
76
-
77
- /**
78
- * @private
79
- * @member {number}
80
- */
81
- this.bufferingTimeout_ = null;
82
-
83
- /**
84
- * @private
85
- * @member {boolean}
86
- */
87
- this.isBuffering_ = false;
88
-
89
- /**
90
- * @private
91
- * @member {boolean}
92
- */
93
- this.isLive_ = false;
94
-
95
- /**
96
- * @private
97
- * @member {boolean}
98
- */
99
- this.isPaused_ = false;
100
-
101
- /**
102
- * @private
103
- * @member {number}
104
- */
105
- this.previousMediaTime_ = null;
106
-
107
-
108
- /**
109
- * @private
110
- * @member {boolean}
111
- */
112
- this.needsReadyEvent_ = true;
113
-
114
- /**
115
- * @private
116
- * @member {boolean}
117
- */
118
- this.needsFirstPlayIntent_ = true;
119
-
120
- /**
121
- * @private
122
- * @member {boolean}
123
- */
124
- this.mediaElementSet_ = false;
125
- this.playbackReadySet_ = false;
126
-
127
- if (mediaElement) {
128
- this.setMediaElement();
129
- }
130
-
131
-
132
- }
133
-
134
- /**
135
- * Used to setup against the media element.
136
- * We need this method to desynchronize construction of this class
137
- * and the actual initialization against the media element.
138
- * That is because at construction some media engine
139
- * may not already have the media element attached, for example
140
- * when passing in the DOM element is happening at once with passing the source URL
141
- * and can not be decoupled.
142
- * We are then awaiting an event from the engine and calling this with the media element
143
- * as argument from our sub-class.
144
- *
145
- * This method can also be called without arguments and then it will perform
146
- * initialization against the existing media element (should only be called once, will throw an error otherwise)
147
- *
148
- * It can also be used to replace the element.
149
- *
150
- *
151
- * @param {HTMLMediaElement} mediaElement
152
- */
153
- setMediaElement(mediaElement = null) {
154
- // replace previously existing, if calld with args
155
- if (mediaElement && this.mediaEl) {
156
- this.unregisterMediaElement();
157
- this.mediaElementSet_ = false;
158
- }
159
-
160
- // if called without args we assume it's already there
161
- // we can also be called with args but without any being there before
162
- if (mediaElement) {
163
- this.mediaEl = mediaElement;
164
- }
165
-
166
- if (!this.mediaEl) {
167
- throw new Error('No media element owned');
168
- }
169
-
170
- if (this.mediaElementSet_) {
171
- throw new Error('Media element already set (only call this once)');
172
- }
173
- this.mediaElementSet_ = true;
174
-
175
- this.registerMediaElement();
176
- this.onMaybeReady();
177
- }
178
-
179
- /**
180
- * Implemented by sub-class to deliver current quality-level info
181
- * specific to media-engine.
182
- * @returns {QualityLevelInfo}
183
- * @abstract
184
- */
185
- getCurrentQualityLevelInfo() {
186
- return null;
187
- }
188
-
189
- /**
190
- * @abstract
191
- * @returns {boolean}
192
- */
193
- isLive() {
194
- return false;
195
- }
196
-
197
- /**
198
- * Can be overriden by sub-classes
199
- * @returns {string}
200
- */
201
- getMIMEType() {
202
- const mediaEl = this.mediaEl;
203
- let streamURL = "";
204
- if (!mediaEl) {
205
- streamURL = null;
206
- }
207
- if (mediaEl && mediaEl.src) {
208
- streamURL = mediaEl.src
209
- }else if(mediaEl && mediaEl.querySelector('source') && mediaEl.querySelector('source').src){
210
- streamURL = mediaEl.querySelector('source').src;
211
- }else{
212
- streamURL = null;
213
- }
214
- return getMIMETypeFromFileExtension(streamURL);
215
- }
216
-
217
- /**
218
- * Can be overriden by sub-classes
219
- * @returns {string}
220
- */
221
- getStreamType() {
222
- return getStreamTypeFromMIMEType(this.getMIMEType());
223
- }
224
-
225
- /**
226
- * @abstract
227
- * @returns {string}
228
- */
229
- getPlayerVersion() {
230
- return null;
231
- }
232
-
233
- /**
234
- * Can be overriden by subclasses.
235
- * @returns {string}
236
- */
237
- getStreamURL() {
238
- const mediaEl = this.mediaEl;
239
-
240
- if (!mediaEl) {
241
- return null;
242
- }
243
- if (mediaEl && mediaEl.src) {
244
- return mediaEl.src
245
- }else if(mediaEl && mediaEl.querySelector('source') && mediaEl.querySelector('source').src){
246
- return mediaEl.querySelector('source').src;
247
- }else{
248
- return null;
249
- }
250
- }
251
-
252
- resetMedia() {
253
- this.mediaEl = null;
254
- this.mediaElEventHandlers = [];
255
- }
256
-
257
- registerMediaElement() {
258
-
259
- const mediaEl = this.mediaEl;
260
- if (!mediaEl) {
261
- return;
262
- }
263
-
264
- this.listenToMediaElementEvent('loadedmetadata', () => {
265
-
266
- // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState
267
- // HAVE_NOTHING 0 No information is available about the media resource.
268
- // HAVE_METADATA 1 Enough of the media resource has been retrieved that
269
- // the metadata attributes are initialized. Seeking will no longer raise an exception.
270
- // HAVE_CURRENT_DATA 2 Data is available for the current playback position,
271
- // but not enough to actually play more than one frame.
272
- // HAVE_FUTURE_DATA 3 Data for the current playback position as well as for
273
- // at least a little bit of time into the future is available
274
- // (in other words, at least two frames of video, for example).
275
- // HAVE_ENOUGH_DATA 4 Enough data is available—and the download rate is high
276
- // enough—that the media can be played through to the end without interruption.
277
- if (mediaEl.readyState !== 1) {
278
- // we can't really gather any more information at this point
279
- return;
280
- }
281
-
282
- // silent
283
- this.checkQualityLevelAttributes(true);
284
-
285
- const {
286
- duration,
287
- autoplay,
288
- videoWidth,
289
- videoHeight,
290
- muted
291
- } = mediaEl;
292
-
293
- const width = mediaEl.clientWidth;
294
- const height = mediaEl.clientHeight;
295
-
296
- // This is redundant with what we give to updateMetadata method.
297
- // Not sure if there are good reasons to keep that so or if we should better centralize.
298
- const info = {
299
- type : 'html5',
300
- isLive : this.isLive(),
301
- version : this.getPlayerVersion() || 'html5',
302
- streamType : this.getStreamType(),
303
- streamUrl : this.getStreamURL(),
304
- duration,
305
- autoplay,
306
- // HTMLVideoElement.width and HTMLVideoElement.height
307
- // is a DOMString that reflects the height HTML attribute,
308
- // which specifies the height of the display area, in CSS pixels.
309
- // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement
310
- currentVideoData:{
311
- height : videoHeight,
312
- width : videoWidth,
313
- bitrate : this.analyticsBitrate_,
314
- audioCodec : this.audioCodec_,
315
- videoCodec : this.videoCodec_,
316
- },
317
- // Returns an unsigned long containing the intrinsic
318
- // height of the resource in CSS pixels,
319
- // taking into account the dimensions, aspect ratio,
320
- // clean aperture, resolution, and so forth,
321
- // as defined for the format used by the resource.
322
- // If the element's ready state is HAVE_NOTHING, the value is 0.
323
- // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement
324
- videoWindowWidth : parseInt(width),
325
- videoWindowHeight: parseInt(height),
326
- muted
327
- };
328
-
329
- // silence events if we have not yet intended play
330
- if (this.needsFirstPlayIntent_) {
331
- return;
332
- }
333
-
334
- this.eventCallback(Events.METADATA_LOADED, info);
335
- });
336
-
337
- // For DashJS this is written in DashjsAdapter.js as it overrides
338
- this.listenToMediaElementEvent('canplay', () => {
339
-
340
- if (this.playbackReadySet_) {
341
- return;
342
- }else {
343
- this.playbackReadySet_ = true;
344
- }
345
-
346
- const {
347
- duration,
348
- autoplay,
349
- videoWidth,
350
- videoHeight,
351
- muted
352
- } = mediaEl;
353
-
354
- const width = mediaEl.clientWidth;
355
- const height = mediaEl.clientHeight;
356
-
357
- const info = {
358
- type : 'html5',
359
- isLive : this.isLive(),
360
- version : this.getPlayerVersion() || 'html5',
361
- streamType : this.getStreamType(),
362
- streamUrl : this.getStreamURL(),
363
- duration : duration,
364
- autoplay : autoplay,
365
- playerSoftware : this.playerSoftwareName,
366
- videoWindowWidth : parseInt(width),
367
- videoWindowHeight: parseInt(height),
368
- currentVideoData:{
369
- height : videoHeight,
370
- width : videoWidth,
371
- bitrate : this.analyticsBitrate_,
372
- audioCodec : this.audioCodec_,
373
- videoCodec : this.videoCodec_,
374
- },
375
- muted
376
- };
377
-
378
- this.eventCallback(Events.SOURCE_LOADED, info);
379
- });
380
-
381
- // We need the PLAY event to indicate the intent to play
382
- // NOTE: use TIMECHANGED event on 'playing' and trigger PLAY as intended in states.dot graph
383
-
384
- this.listenToMediaElementEvent('play', () => {
385
- const { currentTime, videoWidth, videoHeight,} = mediaEl;
386
-
387
- this.needsFirstPlayIntent_ = false;
388
-
389
- this.eventCallback(Events.PLAY, {
390
- currentVideoData:{
391
- height : videoHeight,
392
- width : videoWidth,
393
- bitrate : this.analyticsBitrate_,
394
- audioCodec : this.audioCodec_,
395
- videoCodec : this.videoCodec_,
396
- },
397
- currentTime
398
- });
399
- });
400
-
401
- this.listenToMediaElementEvent('pause', () => {
402
- this.onPaused();
403
- });
404
-
405
- this.listenToMediaElementEvent('playing', () => {
406
- const {currentTime, videoWidth, videoHeight} = mediaEl;
407
-
408
- this.isPaused_ = false;
409
-
410
- // silence events if we have not yet intended play
411
- if (this.needsFirstPlayIntent_) {
412
- return;
413
- }
414
-
415
- this.eventCallback(Events.TIMECHANGED, {
416
- currentVideoData:{
417
- height : videoHeight,
418
- width : videoWidth,
419
- bitrate : this.analyticsBitrate_,
420
- audioCodec : this.audioCodec_,
421
- videoCodec : this.videoCodec_,
422
- },
423
- currentTime
424
- });
425
- });
426
-
427
- this.listenToMediaElementEvent('error', () => {
428
- const {currentTime, error} = mediaEl;
429
-
430
- this.eventCallback(Events.ERROR, {
431
- currentTime,
432
- // See https://developer.mozilla.org/en-US/docs/Web/API/MediaError
433
- code : error.code,
434
- message : error.message
435
- });
436
- });
437
-
438
- this.listenToMediaElementEvent('volumechange', () => {
439
- const {muted, currentTime} = mediaEl;
440
-
441
- if (muted) {
442
- this.eventCallback(Events.MUTE, {
443
- currentTime
444
- });
445
- } else {
446
- this.eventCallback(Events.UN_MUTE, {
447
- currentTime
448
- });
449
- }
450
- });
451
-
452
- this.listenToMediaElementEvent('seeking', () => {
453
- const {currentTime, videoWidth, videoHeight} = mediaEl;
454
-
455
- this.eventCallback(Events.SEEK, {
456
- currentVideoData:{
457
- height : videoHeight,
458
- width : videoWidth,
459
- bitrate : this.analyticsBitrate_,
460
- audioCodec : this.audioCodec_,
461
- videoCodec : this.videoCodec_,
462
- },
463
- currentTime,
464
- droppedFrames: 0
465
- });
466
- });
467
-
468
- this.listenToMediaElementEvent('seeked', () => {
469
- const {currentTime, videoWidth, videoHeight} = mediaEl;
470
-
471
- if (this.bufferingTimeout_) {
472
- clearTimeout(this.bufferingTimeout_);
473
- }
474
-
475
- this.eventCallback(Events.SEEKED, {
476
- currentVideoData:{
477
- height : videoHeight,
478
- width : videoWidth,
479
- bitrate : this.analyticsBitrate_,
480
- audioCodec : this.audioCodec_,
481
- videoCodec : this.videoCodec_,
482
- },
483
- currentTime,
484
- droppedFrames: 0
485
- });
486
- });
487
-
488
- this.listenToMediaElementEvent('ended', () => {
489
- const {currentTime, videoWidth, videoHeight} = mediaEl;
490
-
491
- this.eventCallback(Events.END, {
492
- currentVideoData:{
493
- height : videoHeight,
494
- width : videoWidth,
495
- bitrate : this.analyticsBitrate_,
496
- audioCodec : this.audioCodec_,
497
- videoCodec : this.videoCodec_,
498
- },
499
- currentTime
500
- });
501
- });
502
-
503
- this.listenToMediaElementEvent('timeupdate', () => {
504
-
505
- const {currentTime, videoHeight, videoWidth} = mediaEl;
506
-
507
- this.isBuffering_ = false;
508
-
509
- // silence events if we have not yet intended play
510
- if (this.needsFirstPlayIntent_) {
511
- return;
512
- }
513
-
514
- if (!this.isPaused_) {
515
- this.eventCallback(Events.TIMECHANGED, {
516
- currentVideoData:{
517
- height : videoHeight,
518
- width : videoWidth,
519
- bitrate : this.analyticsBitrate_,
520
- audioCodec : this.audioCodec_,
521
- videoCodec : this.videoCodec_,
522
- },
523
- currentTime
524
- });
525
- }
526
-
527
- this.checkQualityLevelAttributes();
528
-
529
- // We are doing this in case we can not rely
530
- // on the "stalled" or "waiting" events in a specific browser
531
- // and to detect intrinsinc paused states (when we do not get a paused event)
532
- // but the player is paused already before attach or is paused from initialization on.
533
- this.checkPlayheadProgress();
534
-
535
- this.previousMediaTime_ = currentTime;
536
- });
537
-
538
- // The stalled event is fired when the user agent is trying to fetch media data,
539
- // but data is unexpectedly not forthcoming.
540
- // https://developer.mozilla.org/en-US/docs/Web/Events/stalled
541
- this.listenToMediaElementEvent('stalled', () => {
542
-
543
- // this event doesn't indicate buffering by definition (interupted playback),
544
- // only that data throughput to playout buffers is not as high as expected
545
- // It happens on Chrome every once in a while as SourceBuffer's are not fed
546
- // as fast as the underlying native player may prefer (but it does not lead to
547
- // interuption).
548
- });
549
-
550
- // The waiting event is fired when playback has stopped because of a temporary lack of data.
551
- // See https://developer.mozilla.org/en-US/docs/Web/Events/waiting
552
- this.listenToMediaElementEvent('waiting', () => {
553
-
554
- this.onBuffering();
555
- });
556
-
557
- }
558
-
559
- /**
560
- * Should only be calld when a mediaEl is attached
561
- */
562
- listenToMediaElementEvent(event, handler) {
563
- if (!this.mediaEl) {
564
- throw new Error('No media attached');
565
- }
566
- const boundHandler = handler.bind(this);
567
-
568
- this.mediaElEventHandlers.push(boundHandler);
569
- this.mediaEl.addEventListener(event, boundHandler, false);
570
- }
571
-
572
- onMaybeReady() {
573
-
574
- if (!this.needsReadyEvent_ || !this.mediaEl) {
575
- return;
576
- }
577
-
578
- this.needsReadyEvent_ = false;
579
-
580
- let playerPreload = false;
581
- const {
582
- duration,
583
- autoplay,
584
- videoWidth,
585
- videoHeight,
586
- muted,
587
- preload
588
- } = this.mediaEl;
589
-
590
- let streamURL = "";
591
-
592
- if (this.mediaEl && this.mediaEl.src) {
593
- streamURL = this.mediaEl.src
594
- }else if(this.mediaEl && this.mediaEl.querySelector('source') && this.mediaEl.querySelector('source').src){
595
- streamURL = this.mediaEl.querySelector('source').src;
596
- }else{
597
- streamURL = null;
598
- }
599
- const width = this.mediaEl.clientWidth;
600
- const height = this.mediaEl.clientHeight;
601
-
602
- if (preload !== 'none') {
603
- playerPreload = true;
604
- }
605
-
606
- const info = {
607
- type : 'html5',
608
- isLive : this.isLive(),
609
- version : this.getPlayerVersion() || 'html5',
610
- streamType : this.getStreamType(),
611
- streamUrl : this.getStreamURL(),
612
- duration : duration,
613
- autoplay : autoplay,
614
- preload : playerPreload,
615
- playerSoftware : this.playerSoftwareName,
616
- currentVideoData:{
617
- height : videoHeight,
618
- width : videoWidth,
619
- bitrate : this.analyticsBitrate_,
620
- audioCodec : this.audioCodec_,
621
- videoCodec : this.videoCodec_,
622
- },
623
- // HTMLVideoElement.width and HTMLVideoElement.height
624
- // is a DOMString that reflects the height HTML attribute,
625
- // which specifies the height of the display area, in CSS pixels.
626
- // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement
627
- // width : parseInt(width),
628
- // height : parseInt(height),
629
-
630
-
631
- // Returns an unsigned long containing the intrinsic
632
- // height of the resource in CSS pixels,
633
- // taking into account the dimensions, aspect ratio,
634
- // clean aperture, resolution, and so forth,
635
- // as defined for the format used by the resource.
636
- // If the element's ready state is HAVE_NOTHING, the value is 0.
637
- // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement
638
- videoWindowWidth : parseInt(width),
639
- videoWindowHeight: parseInt(height),
640
- muted
641
- };
642
-
643
- this.stateMachine.updateMetadata(info);
644
- this.eventCallback(Events.READY, info);
645
- }
646
-
647
- /**
648
- * Should only be calld when a mediaEl is attached
649
- */
650
- unregisterMediaElement() {
651
- if (!this.mediaEl) {
652
- throw new Error('No media attached');
653
- }
654
-
655
- this.mediaElEventHandlers.forEach((handler) => {
656
- this.mediaEl.removeEventListener(handler);
657
- });
658
-
659
- this.resetMedia();
660
- }
661
-
662
- onBuffering() {
663
- const {currentTime} = this.mediaEl;
664
-
665
- // this handler may be called multiple times
666
- // for one actual buffering-event occuring so lets guard from
667
- // triggering this event redundantly.
668
- if (this.isBuffering_ || this.isPaused_) {
669
- return;
670
- }
671
-
672
- this.eventCallback(Events.START_BUFFERING, {
673
- currentTime
674
- });
675
-
676
- this.isBuffering_ = true;
677
- }
678
-
679
- onPaused() {
680
- if (this.isPaused_) {
681
- return;
682
- }
683
-
684
- const {currentTime, videoHeight, videoWidth} = this.mediaEl;
685
-
686
- this.eventCallback(Events.PAUSE, {
687
- currentVideoData:{
688
- height : videoHeight,
689
- width : videoWidth,
690
- bitrate : this.analyticsBitrate_,
691
- audioCodec : this.audioCodec_,
692
- videoCodec : this.videoCodec_,
693
- },
694
- currentTime
695
- });
696
-
697
- this.isPaused_ = true;
698
- }
699
-
700
- checkPlayheadProgress() {
701
- const mediaEl = this.mediaEl;
702
-
703
- if (mediaEl.paused) {
704
- this.onPaused();
705
- }
706
-
707
- if (this.bufferingTimeout_) {
708
- clearTimeout(this.bufferingTimeout_);
709
- }
710
-
711
- this.bufferingTimeout_ = setTimeout(() => {
712
-
713
- if (mediaEl.paused || mediaEl.ended && !this.isBuffering_) {
714
- return;
715
- }
716
-
717
- const timeDelta = mediaEl.currentTime - this.previousMediaTime_;
718
-
719
- if (timeDelta < BUFFERING_TIMECHANGED_TIMEOUT) {
720
- this.onBuffering();
721
- }
722
-
723
- }, BUFFERING_TIMECHANGED_TIMEOUT);
724
- }
725
-
726
- /**
727
- * @param {boolean} silent
728
- */
729
- checkQualityLevelAttributes(silent = false) {
730
-
731
- const mediaEl = this.mediaEl;
732
-
733
- const qualityLevelInfo = this.getCurrentQualityLevelInfo();
734
- if (!qualityLevelInfo) {
735
- return;
736
- }
737
-
738
- const {bitrate, width, height, videoCodec, audioCodec} = qualityLevelInfo;
739
-
740
- const isLive = this.isLive();
741
-
742
- if (isLive !== this.isLive_) {
743
- this.isLive_ = isLive;
744
-
745
- if (!silent) {
746
- this.stateMachine.updateMetadata({
747
- isLive
748
- });
749
- }
750
-
751
- }
752
-
753
- this.audioCodec_ = audioCodec;
754
- this.videoCodec_ = videoCodec;
755
-
756
- if (this.analyticsBitrate_ !== bitrate) {
757
- const eventData = {
758
- width,
759
- height,
760
- bitrate,
761
- videoCodec,
762
- audioCodec,
763
- currentTime: mediaEl.currentTime
764
- };
765
-
766
- if (!silent) {
767
- this.eventCallback(Events.VIDEO_CHANGE, eventData);
768
- }
769
-
770
- this.analyticsBitrate_ = bitrate;
771
- }
772
-
773
- }
774
- }