stormcloud-video-player 0.7.9 → 0.7.11

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.
@@ -1,5 +1,5 @@
1
1
  import { Component } from 'react';
2
- import { S as StormcloudVideoPlayerConfig } from '../types-ClqQZM3U.cjs';
2
+ import { S as StormcloudVideoPlayerConfig } from '../types-jU4lq0ST.cjs';
3
3
 
4
4
  interface HlsPlayerProps extends StormcloudVideoPlayerConfig {
5
5
  onMount?: (player: any) => void;
@@ -2840,6 +2840,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2840
2840
  this.isInAdTransition = false;
2841
2841
  this.maxPlaceholderDurationMs = 5e3;
2842
2842
  this.isShowingPlaceholder = false;
2843
+ this.lastAdInsertionPoint = null;
2844
+ this.processedAdInsertionUpdatedAt = null;
2843
2845
  this.totalAdRequestsInBreak = 0;
2844
2846
  this.maxTotalAdRequestsPerBreak = 20;
2845
2847
  this.pendingAdBreak = null;
@@ -2857,6 +2859,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2857
2859
  this.preloadedTokens = [];
2858
2860
  this.debugLogEntries = [];
2859
2861
  this.scteMarkerHistory = [];
2862
+ this.adInsertionDebugHistory = [];
2860
2863
  initializePolyfills();
2861
2864
  var browserOverrides = getBrowserConfigOverrides();
2862
2865
  this.config = _object_spread({}, browserOverrides, config);
@@ -3041,6 +3044,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3041
3044
  _state.sent();
3042
3045
  _state.label = 2;
3043
3046
  case 2:
3047
+ if (!this.config.disableAds && this.config.projectId) {
3048
+ this.startAdInsertionPolling();
3049
+ }
3044
3050
  return [
3045
3051
  2
3046
3052
  ];
@@ -3048,78 +3054,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3048
3054
  });
3049
3055
  }).call(_this);
3050
3056
  });
3051
- this.hls.on(import_hls.default.Events.LEVEL_LOADED, function(_evt, data) {
3057
+ this.hls.on(import_hls.default.Events.LEVEL_LOADED, function() {
3052
3058
  if (_this.inAdBreak || _this.pendingAdBreak) {
3053
3059
  return;
3054
3060
  }
3055
- var details = data === null || data === void 0 ? void 0 : data.details;
3056
- if (!details || !details.fragments || details.fragments.length === 0) {
3057
- return;
3058
- }
3059
- var fragmentsToScan = Math.min(5, details.fragments.length);
3060
- for(var i = 0; i < fragmentsToScan; i++){
3061
- var frag = details.fragments[i];
3062
- var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3063
- if (!Array.isArray(tagList)) continue;
3064
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3065
- try {
3066
- for(var _iterator = tagList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3067
- var entry = _step.value;
3068
- var tag = "";
3069
- var value = "";
3070
- if (Array.isArray(entry)) {
3071
- var _entry_, _entry_1;
3072
- tag = String((_entry_ = entry[0]) !== null && _entry_ !== void 0 ? _entry_ : "");
3073
- value = String((_entry_1 = entry[1]) !== null && _entry_1 !== void 0 ? _entry_1 : "");
3074
- } else if (typeof entry === "string") {
3075
- var idx = entry.indexOf(":");
3076
- if (idx >= 0) {
3077
- tag = entry.substring(0, idx);
3078
- value = entry.substring(idx + 1);
3079
- } else {
3080
- tag = entry;
3081
- }
3082
- }
3083
- if (!tag) continue;
3084
- if (tag.includes("EXT-X-CUE-OUT") || tag.includes("EXT-X-DATERANGE")) {
3085
- var attrs = tag.includes("EXT-X-DATERANGE") ? _this.parseAttributeList(value) : {};
3086
- var hasScteOut = tag.includes("EXT-X-CUE-OUT") || "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
3087
- if (hasScteOut) {
3088
- var durationSeconds = _this.parseCueOutDuration(value);
3089
- var marker = _object_spread_props(_object_spread({
3090
- type: "start"
3091
- }, durationSeconds !== void 0 ? {
3092
- durationSeconds: durationSeconds
3093
- } : {}), {
3094
- raw: {
3095
- tag: tag,
3096
- value: value,
3097
- earlyDetection: true
3098
- }
3099
- });
3100
- if (_this.config.debugAdTiming) {
3101
- console.log("[StormcloudVideoPlayer] \uD83C\uDFAF EARLY SCTE-35 DETECTION: Ad break marker found in fragment", i, "- starting pre-fetch (NOT playing yet)");
3102
- }
3103
- _this.startAdPrefetch(marker, frag === null || frag === void 0 ? void 0 : frag.sn);
3104
- return;
3105
- }
3106
- }
3107
- }
3108
- } catch (err) {
3109
- _didIteratorError = true;
3110
- _iteratorError = err;
3111
- } finally{
3112
- try {
3113
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3114
- _iterator.return();
3115
- }
3116
- } finally{
3117
- if (_didIteratorError) {
3118
- throw _iteratorError;
3119
- }
3120
- }
3121
- }
3122
- }
3061
+ _this.checkAdInsertionInManifest();
3123
3062
  });
3124
3063
  this.hls.on(import_hls.default.Events.FRAG_BUFFERED, function(_evt, data) {
3125
3064
  return _async_to_generator(function() {
@@ -3181,124 +3120,42 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3181
3120
  });
3182
3121
  }).call(_this);
3183
3122
  });
3184
- this.hls.on(import_hls.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3185
- var id3Tags = ((data === null || data === void 0 ? void 0 : data.samples) || []).map(function(s) {
3186
- return {
3187
- key: "ID3",
3188
- value: s === null || s === void 0 ? void 0 : s.data,
3189
- ptsSeconds: s === null || s === void 0 ? void 0 : s.pts
3190
- };
3191
- });
3192
- id3Tags.forEach(function(tag) {
3193
- return _this.onId3Tag(tag);
3194
- });
3195
- });
3196
3123
  this.hls.on(import_hls.default.Events.FRAG_CHANGED, function(_evt, data) {
3197
3124
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3198
- var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3199
- if (!Array.isArray(tagList)) return;
3200
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3201
- try {
3202
- for(var _iterator = tagList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3203
- var entry = _step.value;
3204
- var tag = "";
3205
- var value = "";
3206
- if (Array.isArray(entry)) {
3207
- var _entry_, _entry_1;
3208
- tag = String((_entry_ = entry[0]) !== null && _entry_ !== void 0 ? _entry_ : "");
3209
- value = String((_entry_1 = entry[1]) !== null && _entry_1 !== void 0 ? _entry_1 : "");
3210
- } else if (typeof entry === "string") {
3211
- var idx = entry.indexOf(":");
3212
- if (idx >= 0) {
3213
- tag = entry.substring(0, idx);
3214
- value = entry.substring(idx + 1);
3215
- } else {
3216
- tag = entry;
3217
- value = "";
3218
- }
3125
+ if (!frag) return;
3126
+ if (_this.lastAdInsertionPoint && !_this.inAdBreak && _this.lastAdInsertionPoint.updated_at !== _this.processedAdInsertionUpdatedAt) {
3127
+ var segmentName = _this.lastAdInsertionPoint.segment_ts_name;
3128
+ if (_this.fragmentMatchesSegment(frag, segmentName)) {
3129
+ var _ref;
3130
+ _this.processedAdInsertionUpdatedAt = _this.lastAdInsertionPoint.updated_at;
3131
+ var offsetMs = (_this.lastAdInsertionPoint.offset_seconds || 0) * 1e3;
3132
+ _this.pushAdInsertionDebug("segment_playing", segmentName, {
3133
+ offsetSeconds: _this.lastAdInsertionPoint.offset_seconds,
3134
+ detail: "sn=".concat((_ref = frag === null || frag === void 0 ? void 0 : frag.sn) !== null && _ref !== void 0 ? _ref : "?")
3135
+ });
3136
+ if (_this.config.debugAdTiming) {
3137
+ console.log('[StormcloudVideoPlayer] Ad insertion segment "'.concat(segmentName, '" now playing — scheduling ad start in ').concat(offsetMs, "ms"));
3219
3138
  }
3220
- if (!tag) continue;
3221
- if (tag.includes("EXT-X-CUE-OUT-CONT")) {
3222
- var prog = _this.parseCueOutCont(value);
3223
- var marker = _object_spread_props(_object_spread({
3224
- type: "progress"
3225
- }, (prog === null || prog === void 0 ? void 0 : prog.duration) !== void 0 ? {
3226
- durationSeconds: prog.duration
3227
- } : {}, (prog === null || prog === void 0 ? void 0 : prog.elapsed) !== void 0 ? {
3228
- ptsSeconds: prog.elapsed
3229
- } : {}), {
3230
- raw: {
3231
- tag: tag,
3232
- value: value
3233
- }
3139
+ _this.pushAdInsertionDebug("ad_scheduled", segmentName, {
3140
+ offsetSeconds: _this.lastAdInsertionPoint.offset_seconds,
3141
+ detail: "in ".concat(offsetMs, "ms, dur=60s")
3142
+ });
3143
+ _this.clearAdInsertionOffsetTimer();
3144
+ _this.adInsertionOffsetTimerId = window.setTimeout(function() {
3145
+ _this.adInsertionOffsetTimerId = void 0;
3146
+ if (_this.inAdBreak) return;
3147
+ _this.pushAdInsertionDebug("ad_triggered", segmentName, {
3148
+ detail: "ad break started (60s)"
3234
3149
  });
3235
- _this.onScte35Marker(marker);
3236
- } else if (tag.includes("EXT-X-CUE-OUT")) {
3237
- var durationSeconds = _this.parseCueOutDuration(value);
3238
- var marker1 = _object_spread_props(_object_spread({
3239
- type: "start"
3240
- }, durationSeconds !== void 0 ? {
3241
- durationSeconds: durationSeconds
3242
- } : {}), {
3150
+ var marker = {
3151
+ type: "start",
3152
+ durationSeconds: 60,
3243
3153
  raw: {
3244
- tag: tag,
3245
- value: value
3154
+ apiInsertionPoint: _this.lastAdInsertionPoint
3246
3155
  }
3247
- });
3248
- _this.onScte35Marker(marker1);
3249
- } else if (tag.includes("EXT-X-CUE-IN")) {
3250
- _this.onScte35Marker({
3251
- type: "end",
3252
- raw: {
3253
- tag: tag,
3254
- value: value
3255
- }
3256
- });
3257
- } else if (tag.includes("EXT-X-DATERANGE")) {
3258
- var _attrs_CLASS;
3259
- var attrs = _this.parseAttributeList(value);
3260
- var hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
3261
- var hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
3262
- var klass = String((_attrs_CLASS = attrs["CLASS"]) !== null && _attrs_CLASS !== void 0 ? _attrs_CLASS : "");
3263
- var duration = _this.toNumber(attrs["DURATION"]);
3264
- if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
3265
- var marker2 = _object_spread_props(_object_spread({
3266
- type: "start"
3267
- }, duration !== void 0 ? {
3268
- durationSeconds: duration
3269
- } : {}), {
3270
- raw: {
3271
- tag: tag,
3272
- value: value,
3273
- attrs: attrs
3274
- }
3275
- });
3276
- _this.onScte35Marker(marker2);
3277
- }
3278
- if (hasScteIn) {
3279
- _this.onScte35Marker({
3280
- type: "end",
3281
- raw: {
3282
- tag: tag,
3283
- value: value,
3284
- attrs: attrs
3285
- }
3286
- });
3287
- }
3288
- }
3289
- }
3290
- } catch (err) {
3291
- _didIteratorError = true;
3292
- _iteratorError = err;
3293
- } finally{
3294
- try {
3295
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3296
- _iterator.return();
3297
- }
3298
- } finally{
3299
- if (_didIteratorError) {
3300
- throw _iteratorError;
3301
- }
3156
+ };
3157
+ _this.onScte35Marker(marker);
3158
+ }, offsetMs);
3302
3159
  }
3303
3160
  }
3304
3161
  });
@@ -4498,6 +4355,182 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4498
4355
  this.preloadedTokens = [];
4499
4356
  }
4500
4357
  },
4358
+ {
4359
+ key: "startAdInsertionPolling",
4360
+ value: function startAdInsertionPolling() {
4361
+ var _this = this;
4362
+ if (this.adInsertionPollingId != null) return;
4363
+ this.fetchAdInsertionPoint();
4364
+ this.adInsertionPollingId = window.setInterval(function() {
4365
+ _this.fetchAdInsertionPoint();
4366
+ }, 1e3);
4367
+ }
4368
+ },
4369
+ {
4370
+ key: "stopAdInsertionPolling",
4371
+ value: function stopAdInsertionPolling() {
4372
+ if (this.adInsertionPollingId != null) {
4373
+ clearInterval(this.adInsertionPollingId);
4374
+ this.adInsertionPollingId = void 0;
4375
+ }
4376
+ }
4377
+ },
4378
+ {
4379
+ key: "fetchAdInsertionPoint",
4380
+ value: function fetchAdInsertionPoint() {
4381
+ return _async_to_generator(function() {
4382
+ var _this_lastAdInsertionPoint, resp, data, isNew, unused;
4383
+ return _ts_generator(this, function(_state) {
4384
+ switch(_state.label){
4385
+ case 0:
4386
+ if (!this.config.projectId) return [
4387
+ 2
4388
+ ];
4389
+ _state.label = 1;
4390
+ case 1:
4391
+ _state.trys.push([
4392
+ 1,
4393
+ 4,
4394
+ ,
4395
+ 5
4396
+ ]);
4397
+ return [
4398
+ 4,
4399
+ fetch("https://adstorm.co/api-adstorm-dev/adstorm/swirl/projects/".concat(encodeURIComponent(this.config.projectId), "/ad-insertion-point"))
4400
+ ];
4401
+ case 2:
4402
+ resp = _state.sent();
4403
+ if (!resp.ok) return [
4404
+ 2
4405
+ ];
4406
+ return [
4407
+ 4,
4408
+ resp.json()
4409
+ ];
4410
+ case 3:
4411
+ data = _state.sent();
4412
+ isNew = data.updated_at !== ((_this_lastAdInsertionPoint = this.lastAdInsertionPoint) === null || _this_lastAdInsertionPoint === void 0 ? void 0 : _this_lastAdInsertionPoint.updated_at);
4413
+ this.lastAdInsertionPoint = data;
4414
+ if (isNew) {
4415
+ this.pushAdInsertionDebug("api_response", data.segment_ts_name, {
4416
+ offsetSeconds: data.offset_seconds,
4417
+ updatedAt: data.updated_at,
4418
+ detail: "project=".concat(data.project_id)
4419
+ });
4420
+ }
4421
+ if (this.config.debugAdTiming) {
4422
+ console.log("[StormcloudVideoPlayer] Ad insertion point API response:", data);
4423
+ }
4424
+ return [
4425
+ 3,
4426
+ 5
4427
+ ];
4428
+ case 4:
4429
+ unused = _state.sent();
4430
+ if (this.config.debugAdTiming) {
4431
+ console.warn("[StormcloudVideoPlayer] Ad insertion point API fetch failed");
4432
+ }
4433
+ return [
4434
+ 3,
4435
+ 5
4436
+ ];
4437
+ case 5:
4438
+ return [
4439
+ 2
4440
+ ];
4441
+ }
4442
+ });
4443
+ }).call(this);
4444
+ }
4445
+ },
4446
+ {
4447
+ key: "checkAdInsertionInManifest",
4448
+ value: function checkAdInsertionInManifest() {
4449
+ var _this_hls;
4450
+ if (!this.lastAdInsertionPoint) return;
4451
+ if (this.inAdBreak || this.pendingAdBreak) return;
4452
+ if (this.lastAdInsertionPoint.updated_at === this.processedAdInsertionUpdatedAt) return;
4453
+ var segmentName = this.lastAdInsertionPoint.segment_ts_name;
4454
+ var levels = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.levels;
4455
+ if (!levels) return;
4456
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4457
+ try {
4458
+ for(var _iterator = levels[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4459
+ var level = _step.value;
4460
+ var _level_details;
4461
+ var fragments = (_level_details = level.details) === null || _level_details === void 0 ? void 0 : _level_details.fragments;
4462
+ if (!Array.isArray(fragments)) continue;
4463
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
4464
+ try {
4465
+ for(var _iterator1 = fragments[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
4466
+ var frag = _step1.value;
4467
+ if (this.fragmentMatchesSegment(frag, segmentName)) {
4468
+ var _ref;
4469
+ this.pushAdInsertionDebug("segment_found", segmentName, {
4470
+ detail: "sn=".concat((_ref = frag === null || frag === void 0 ? void 0 : frag.sn) !== null && _ref !== void 0 ? _ref : "?")
4471
+ });
4472
+ if (this.config.debugAdTiming) {
4473
+ console.log('[StormcloudVideoPlayer] Ad insertion segment "'.concat(segmentName, '" found in manifest — starting pre-fetch'));
4474
+ }
4475
+ var marker = {
4476
+ type: "start",
4477
+ durationSeconds: 60,
4478
+ raw: {
4479
+ apiInsertionPoint: this.lastAdInsertionPoint,
4480
+ earlyDetection: true
4481
+ }
4482
+ };
4483
+ this.startAdPrefetch(marker, frag === null || frag === void 0 ? void 0 : frag.sn);
4484
+ return;
4485
+ }
4486
+ }
4487
+ } catch (err) {
4488
+ _didIteratorError1 = true;
4489
+ _iteratorError1 = err;
4490
+ } finally{
4491
+ try {
4492
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
4493
+ _iterator1.return();
4494
+ }
4495
+ } finally{
4496
+ if (_didIteratorError1) {
4497
+ throw _iteratorError1;
4498
+ }
4499
+ }
4500
+ }
4501
+ }
4502
+ } catch (err) {
4503
+ _didIteratorError = true;
4504
+ _iteratorError = err;
4505
+ } finally{
4506
+ try {
4507
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
4508
+ _iterator.return();
4509
+ }
4510
+ } finally{
4511
+ if (_didIteratorError) {
4512
+ throw _iteratorError;
4513
+ }
4514
+ }
4515
+ }
4516
+ }
4517
+ },
4518
+ {
4519
+ key: "fragmentMatchesSegment",
4520
+ value: function fragmentMatchesSegment(frag, segmentName) {
4521
+ var url = (frag === null || frag === void 0 ? void 0 : frag.url) || (frag === null || frag === void 0 ? void 0 : frag.relurl) || "";
4522
+ return url.endsWith(segmentName) || url.includes("/" + segmentName);
4523
+ }
4524
+ },
4525
+ {
4526
+ key: "clearAdInsertionOffsetTimer",
4527
+ value: function clearAdInsertionOffsetTimer() {
4528
+ if (this.adInsertionOffsetTimerId != null) {
4529
+ clearTimeout(this.adInsertionOffsetTimerId);
4530
+ this.adInsertionOffsetTimerId = void 0;
4531
+ }
4532
+ }
4533
+ },
4501
4534
  {
4502
4535
  key: "startContinuousFetchLoop",
4503
4536
  value: function startContinuousFetchLoop() {
@@ -5419,6 +5452,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5419
5452
  }
5420
5453
  this.clearAdRequestWatchdog();
5421
5454
  this.clearAdFailsafeTimer();
5455
+ this.clearAdInsertionOffsetTimer();
5422
5456
  this.activeAdRequestToken = null;
5423
5457
  this.isInAdTransition = false;
5424
5458
  this.stopContinuousFetching();
@@ -5749,6 +5783,32 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5749
5783
  });
5750
5784
  }
5751
5785
  },
5786
+ {
5787
+ key: "pushAdInsertionDebug",
5788
+ value: function pushAdInsertionDebug(event, segmentName, opts) {
5789
+ if (!this.config.debugAdTiming) return;
5790
+ this.adInsertionDebugHistory.push(_object_spread({
5791
+ timestampMs: Date.now(),
5792
+ event: event,
5793
+ segmentName: segmentName
5794
+ }, (opts === null || opts === void 0 ? void 0 : opts.offsetSeconds) !== void 0 ? {
5795
+ offsetSeconds: opts.offsetSeconds
5796
+ } : {}, (opts === null || opts === void 0 ? void 0 : opts.updatedAt) ? {
5797
+ updatedAt: opts.updatedAt
5798
+ } : {}, (opts === null || opts === void 0 ? void 0 : opts.detail) ? {
5799
+ detail: opts.detail
5800
+ } : {}));
5801
+ if (this.adInsertionDebugHistory.length > DEBUG_HISTORY_LIMIT) {
5802
+ this.adInsertionDebugHistory = this.adInsertionDebugHistory.slice(-DEBUG_HISTORY_LIMIT);
5803
+ }
5804
+ }
5805
+ },
5806
+ {
5807
+ key: "getAdInsertionDebugLog",
5808
+ value: function getAdInsertionDebugLog() {
5809
+ return this.adInsertionDebugHistory.slice();
5810
+ }
5811
+ },
5752
5812
  {
5753
5813
  key: "getDebugLogs",
5754
5814
  value: function getDebugLogs() {
@@ -6015,6 +6075,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6015
6075
  key: "destroy",
6016
6076
  value: function destroy() {
6017
6077
  var _this_hls, _this_adLayer;
6078
+ this.stopAdInsertionPolling();
6079
+ this.clearAdInsertionOffsetTimer();
6018
6080
  this.stopContinuousFetching();
6019
6081
  this.stopFillerBreakTimer();
6020
6082
  this.clearAdStartTimer();
@@ -6046,6 +6108,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6046
6108
  this.consecutiveFailures = 0;
6047
6109
  this.debugLogEntries = [];
6048
6110
  this.scteMarkerHistory = [];
6111
+ this.adInsertionDebugHistory = [];
6049
6112
  }
6050
6113
  }
6051
6114
  ]);