stormcloud-video-player 0.5.26 → 0.6.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.
@@ -400,362 +400,6 @@ module.exports = __toCommonJS(HlsPlayer_exports);
400
400
  var import_react = require("react");
401
401
  // src/player/StormcloudVideoPlayer.ts
402
402
  var import_hls2 = __toESM(require("hls.js"), 1);
403
- // src/sdk/prebid.ts
404
- var DEFAULT_TIMEOUT_MS = 3e3;
405
- var AUCTION_URL = "https://sspproxy.adstorm.co/openrtb2/auction/adstorm";
406
- function createPrebidManager() {
407
- var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
408
- var _options_debug;
409
- var initialized = false;
410
- var debug = (_options_debug = options.debug) !== null && _options_debug !== void 0 ? _options_debug : false;
411
- function log() {
412
- for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
413
- args[_key] = arguments[_key];
414
- }
415
- if (debug) {
416
- var _console;
417
- (_console = console).log.apply(_console, [
418
- "[Prebid]"
419
- ].concat(_to_consumable_array(args)));
420
- }
421
- }
422
- function warn() {
423
- for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
424
- args[_key] = arguments[_key];
425
- }
426
- var _console;
427
- (_console = console).warn.apply(_console, [
428
- "[Prebid]"
429
- ].concat(_to_consumable_array(args)));
430
- }
431
- function parseResponse(data) {
432
- var bids = [];
433
- var seatbids = (data === null || data === void 0 ? void 0 : data.seatbid) || [];
434
- var currency = (data === null || data === void 0 ? void 0 : data.cur) || "USD";
435
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
436
- try {
437
- for(var _iterator = seatbids[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
438
- var seatbid = _step.value;
439
- var seat = seatbid.seat || "unknown";
440
- var bidArray = seatbid.bid || [];
441
- var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
442
- try {
443
- for(var _iterator1 = bidArray[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
444
- var bid = _step1.value;
445
- var _bid_ext_prebid_cache_vastXml, _bid_ext_prebid_cache, _bid_ext_prebid, _bid_ext;
446
- var cacheUrl = (_bid_ext = bid.ext) === null || _bid_ext === void 0 ? void 0 : (_bid_ext_prebid = _bid_ext.prebid) === null || _bid_ext_prebid === void 0 ? void 0 : (_bid_ext_prebid_cache = _bid_ext_prebid.cache) === null || _bid_ext_prebid_cache === void 0 ? void 0 : (_bid_ext_prebid_cache_vastXml = _bid_ext_prebid_cache.vastXml) === null || _bid_ext_prebid_cache_vastXml === void 0 ? void 0 : _bid_ext_prebid_cache_vastXml.url;
447
- var vastXml = bid.adm || void 0;
448
- var bidResponse = {
449
- bidder: seat,
450
- cpm: bid.price || 0,
451
- width: bid.w || 0,
452
- height: bid.h || 0,
453
- adId: bid.id || "",
454
- impId: bid.impid || "",
455
- creativeId: bid.crid || "",
456
- currency: currency
457
- };
458
- if (cacheUrl) bidResponse.vastUrl = cacheUrl;
459
- if (vastXml) bidResponse.vastXml = vastXml;
460
- if (bid.adomain) bidResponse.adomain = bid.adomain;
461
- bids.push(bidResponse);
462
- }
463
- } catch (err) {
464
- _didIteratorError1 = true;
465
- _iteratorError1 = err;
466
- } finally{
467
- try {
468
- if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
469
- _iterator1.return();
470
- }
471
- } finally{
472
- if (_didIteratorError1) {
473
- throw _iteratorError1;
474
- }
475
- }
476
- }
477
- }
478
- } catch (err) {
479
- _didIteratorError = true;
480
- _iteratorError = err;
481
- } finally{
482
- try {
483
- if (!_iteratorNormalCompletion && _iterator.return != null) {
484
- _iterator.return();
485
- }
486
- } finally{
487
- if (_didIteratorError) {
488
- throw _iteratorError;
489
- }
490
- }
491
- }
492
- bids.sort(function(a, b) {
493
- return b.cpm - a.cpm;
494
- });
495
- return bids;
496
- }
497
- function initialize() {
498
- return _async_to_generator(function() {
499
- return _ts_generator(this, function(_state) {
500
- if (initialized) return [
501
- 2
502
- ];
503
- initialized = true;
504
- log("Initialized, auction URL:", AUCTION_URL);
505
- return [
506
- 2
507
- ];
508
- });
509
- })();
510
- }
511
- function requestBids(context) {
512
- return _async_to_generator(function() {
513
- var timeout, controller, timeoutId, _data_ext, _data_ext1, fetchOptions, body, response, body1, data, bids, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, b, error;
514
- return _ts_generator(this, function(_state) {
515
- switch(_state.label){
516
- case 0:
517
- if (!initialized) {
518
- throw new Error("Prebid not initialized. Call initialize() first.");
519
- }
520
- timeout = DEFAULT_TIMEOUT_MS;
521
- log("Fetching auction response from:", AUCTION_URL);
522
- controller = typeof AbortController !== "undefined" ? new AbortController() : null;
523
- timeoutId = setTimeout(function() {
524
- controller === null || controller === void 0 ? void 0 : controller.abort();
525
- }, timeout + 2e3);
526
- _state.label = 1;
527
- case 1:
528
- _state.trys.push([
529
- 1,
530
- 6,
531
- ,
532
- 7
533
- ]);
534
- fetchOptions = {
535
- method: "POST"
536
- };
537
- if (controller) {
538
- fetchOptions.signal = controller.signal;
539
- }
540
- if ((context === null || context === void 0 ? void 0 : context.remainingBreakSec) != null) {
541
- body = {
542
- imp: [
543
- {
544
- video: {
545
- maxduration: Math.floor(context.remainingBreakSec)
546
- }
547
- }
548
- ]
549
- };
550
- fetchOptions.body = JSON.stringify(body);
551
- fetchOptions.headers = {
552
- "Content-Type": "application/json"
553
- };
554
- log("Sending context to auction: maxduration=", Math.floor(context.remainingBreakSec));
555
- }
556
- return [
557
- 4,
558
- fetch(AUCTION_URL, fetchOptions)
559
- ];
560
- case 2:
561
- response = _state.sent();
562
- clearTimeout(timeoutId);
563
- if (!!response.ok) return [
564
- 3,
565
- 4
566
- ];
567
- return [
568
- 4,
569
- response.text().catch(function() {
570
- return "";
571
- })
572
- ];
573
- case 3:
574
- body1 = _state.sent();
575
- throw new Error("Prebid Server returned HTTP ".concat(response.status, ": ").concat(body1.slice(0, 200)));
576
- case 4:
577
- return [
578
- 4,
579
- response.json()
580
- ];
581
- case 5:
582
- data = _state.sent();
583
- if (debug && (data === null || data === void 0 ? void 0 : (_data_ext = data.ext) === null || _data_ext === void 0 ? void 0 : _data_ext.responsetimemillis)) {
584
- log("Bidder response times:", data.ext.responsetimemillis);
585
- }
586
- if (debug && (data === null || data === void 0 ? void 0 : (_data_ext1 = data.ext) === null || _data_ext1 === void 0 ? void 0 : _data_ext1.errors)) {
587
- warn("Auction errors:", data.ext.errors);
588
- }
589
- bids = parseResponse(data);
590
- log("Received ".concat(bids.length, " bid(s)"));
591
- if (debug) {
592
- _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
593
- try {
594
- for(_iterator = bids[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
595
- b = _step.value;
596
- log(" ".concat(b.bidder, ": $").concat(b.cpm.toFixed(2), " ").concat(b.currency, " ").concat(b.width, "x").concat(b.height) + (b.vastUrl ? " [cached VAST]" : "") + (b.vastXml && !b.vastUrl ? " [VAST XML]" : ""));
597
- }
598
- } catch (err) {
599
- _didIteratorError = true;
600
- _iteratorError = err;
601
- } finally{
602
- try {
603
- if (!_iteratorNormalCompletion && _iterator.return != null) {
604
- _iterator.return();
605
- }
606
- } finally{
607
- if (_didIteratorError) {
608
- throw _iteratorError;
609
- }
610
- }
611
- }
612
- }
613
- return [
614
- 2,
615
- bids
616
- ];
617
- case 6:
618
- error = _state.sent();
619
- clearTimeout(timeoutId);
620
- if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
621
- warn("Auction request timed out after ".concat(timeout + 2e3, "ms"));
622
- return [
623
- 2,
624
- []
625
- ];
626
- }
627
- throw error;
628
- case 7:
629
- return [
630
- 2
631
- ];
632
- }
633
- });
634
- })();
635
- }
636
- var REQUEST_BIDS_MAX_RETRIES = 3;
637
- var REQUEST_BIDS_BACKOFF_MS = 1500;
638
- function requestBidsUntilResponse(context) {
639
- return _async_to_generator(function() {
640
- var _loop, lastError, attempt, _ret;
641
- return _ts_generator(this, function(_state) {
642
- switch(_state.label){
643
- case 0:
644
- _loop = function(attempt) {
645
- var bids, err, delay;
646
- return _ts_generator(this, function(_state) {
647
- switch(_state.label){
648
- case 0:
649
- _state.trys.push([
650
- 0,
651
- 2,
652
- ,
653
- 3
654
- ]);
655
- return [
656
- 4,
657
- requestBids(context)
658
- ];
659
- case 1:
660
- bids = _state.sent();
661
- if (bids.length > 0) {
662
- log("requestBidsUntilResponse: got ".concat(bids.length, " bid(s) on attempt ").concat(attempt));
663
- return [
664
- 2,
665
- {
666
- v: bids
667
- }
668
- ];
669
- }
670
- log("requestBidsUntilResponse: no bids on attempt ".concat(attempt, "/").concat(REQUEST_BIDS_MAX_RETRIES));
671
- return [
672
- 3,
673
- 3
674
- ];
675
- case 2:
676
- err = _state.sent();
677
- lastError = err;
678
- warn("requestBidsUntilResponse: attempt ".concat(attempt, "/").concat(REQUEST_BIDS_MAX_RETRIES, " failed:"), err);
679
- return [
680
- 3,
681
- 3
682
- ];
683
- case 3:
684
- if (!(attempt < REQUEST_BIDS_MAX_RETRIES)) return [
685
- 3,
686
- 5
687
- ];
688
- delay = REQUEST_BIDS_BACKOFF_MS * attempt;
689
- log("requestBidsUntilResponse: waiting ".concat(delay, "ms before retry"));
690
- return [
691
- 4,
692
- new Promise(function(resolve) {
693
- return setTimeout(resolve, delay);
694
- })
695
- ];
696
- case 4:
697
- _state.sent();
698
- _state.label = 5;
699
- case 5:
700
- return [
701
- 2
702
- ];
703
- }
704
- });
705
- };
706
- if (!initialized) {
707
- throw new Error("Prebid not initialized. Call initialize() first.");
708
- }
709
- attempt = 1;
710
- _state.label = 1;
711
- case 1:
712
- if (!(attempt <= REQUEST_BIDS_MAX_RETRIES)) return [
713
- 3,
714
- 4
715
- ];
716
- return [
717
- 5,
718
- _ts_values(_loop(attempt))
719
- ];
720
- case 2:
721
- _ret = _state.sent();
722
- if (_type_of(_ret) === "object") return [
723
- 2,
724
- _ret.v
725
- ];
726
- _state.label = 3;
727
- case 3:
728
- attempt++;
729
- return [
730
- 3,
731
- 1
732
- ];
733
- case 4:
734
- if (_instanceof(lastError, Error)) {
735
- throw lastError;
736
- }
737
- return [
738
- 2,
739
- []
740
- ];
741
- }
742
- });
743
- })();
744
- }
745
- function destroy() {
746
- initialized = false;
747
- log("Destroyed");
748
- }
749
- return {
750
- initialize: initialize,
751
- requestBids: requestBids,
752
- requestBidsUntilResponse: requestBidsUntilResponse,
753
- destroy: destroy,
754
- get isInitialized () {
755
- return initialized;
756
- }
757
- };
758
- }
759
403
  // src/sdk/vastParser.ts
760
404
  function isHlsType(type) {
761
405
  return type === "application/x-mpegURL" || type.includes("m3u8");
@@ -1054,11 +698,271 @@ function fireTrackingPixels(urls, sessionId) {
1054
698
  } catch (error) {
1055
699
  console.warn("".concat(logPrefix, " Error firing tracking pixel:"), error);
1056
700
  }
1057
- });
701
+ });
702
+ }
703
+ // src/sdk/vastManager.ts
704
+ var VAST_TAG_URL = "https://pubads.g.doubleclick.net/gampad/ads?iu=/21821455290/Airy-Android&description_url=http%3A%2F%2Fairy.tv&tfcd=0&npa=0&sz=1x1%7C300x250%7C400x300%7C640x480&gdfp_req=1&unviewed_position_start=1&correlator=[placeholder]&vpos=preroll&output=vast&env=vp&vpmute=0&vpa=click";
705
+ var DEFAULT_TIMEOUT_MS = 5e3;
706
+ var MAX_RETRIES = 3;
707
+ var RETRY_BACKOFF_MS = 1500;
708
+ function createVastManager() {
709
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
710
+ var _options_debug;
711
+ var initialized = false;
712
+ var debug = (_options_debug = options.debug) !== null && _options_debug !== void 0 ? _options_debug : false;
713
+ function log() {
714
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
715
+ args[_key] = arguments[_key];
716
+ }
717
+ if (debug) {
718
+ var _console;
719
+ (_console = console).log.apply(_console, [
720
+ "[VastManager]"
721
+ ].concat(_to_consumable_array(args)));
722
+ }
723
+ }
724
+ function warn() {
725
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
726
+ args[_key] = arguments[_key];
727
+ }
728
+ var _console;
729
+ (_console = console).warn.apply(_console, [
730
+ "[VastManager]"
731
+ ].concat(_to_consumable_array(args)));
732
+ }
733
+ function initialize() {
734
+ return _async_to_generator(function() {
735
+ return _ts_generator(this, function(_state) {
736
+ if (initialized) return [
737
+ 2
738
+ ];
739
+ initialized = true;
740
+ log("Initialized, VAST tag URL:", VAST_TAG_URL.split("?")[0]);
741
+ return [
742
+ 2
743
+ ];
744
+ });
745
+ })();
746
+ }
747
+ function requestBids(_context) {
748
+ return _async_to_generator(function() {
749
+ var correlator, url, controller, timeoutId, _ref, _ref1, _vastAd_mediaFiles_, _vastAd_mediaFiles_1, fetchOptions, response, vastXml, vastAd, bid, error;
750
+ return _ts_generator(this, function(_state) {
751
+ switch(_state.label){
752
+ case 0:
753
+ if (!initialized) {
754
+ throw new Error("VastManager not initialized. Call initialize() first.");
755
+ }
756
+ correlator = Math.floor(Math.random() * 1e12).toString();
757
+ url = VAST_TAG_URL.replace("[placeholder]", correlator);
758
+ log("Fetching VAST tag, correlator:", correlator);
759
+ controller = typeof AbortController !== "undefined" ? new AbortController() : null;
760
+ timeoutId = setTimeout(function() {
761
+ return controller === null || controller === void 0 ? void 0 : controller.abort();
762
+ }, DEFAULT_TIMEOUT_MS);
763
+ _state.label = 1;
764
+ case 1:
765
+ _state.trys.push([
766
+ 1,
767
+ 4,
768
+ ,
769
+ 5
770
+ ]);
771
+ fetchOptions = {
772
+ method: "GET",
773
+ mode: "cors",
774
+ credentials: "omit",
775
+ headers: {
776
+ Accept: "application/xml, text/xml, */*"
777
+ },
778
+ referrerPolicy: "no-referrer-when-downgrade"
779
+ };
780
+ if (controller) fetchOptions.signal = controller.signal;
781
+ return [
782
+ 4,
783
+ fetch(url, fetchOptions)
784
+ ];
785
+ case 2:
786
+ response = _state.sent();
787
+ clearTimeout(timeoutId);
788
+ if (!response.ok) {
789
+ throw new Error("VAST request returned HTTP ".concat(response.status));
790
+ }
791
+ return [
792
+ 4,
793
+ response.text()
794
+ ];
795
+ case 3:
796
+ vastXml = _state.sent();
797
+ log("VAST XML received, length:", vastXml.length);
798
+ vastAd = parseVastXml(vastXml, "mp4-first", "[VastManager]");
799
+ if (!vastAd) {
800
+ log("VAST parsed but no usable ad found");
801
+ return [
802
+ 2,
803
+ []
804
+ ];
805
+ }
806
+ log("Ad parsed: id=".concat(vastAd.id, ", duration=").concat(vastAd.duration, "s, mediaFiles=").concat(vastAd.mediaFiles.length));
807
+ bid = {
808
+ bidder: "vast-direct",
809
+ cpm: 0,
810
+ vastXml: vastXml,
811
+ width: (_ref = (_vastAd_mediaFiles_ = vastAd.mediaFiles[0]) === null || _vastAd_mediaFiles_ === void 0 ? void 0 : _vastAd_mediaFiles_.width) !== null && _ref !== void 0 ? _ref : 0,
812
+ height: (_ref1 = (_vastAd_mediaFiles_1 = vastAd.mediaFiles[0]) === null || _vastAd_mediaFiles_1 === void 0 ? void 0 : _vastAd_mediaFiles_1.height) !== null && _ref1 !== void 0 ? _ref1 : 0,
813
+ adId: vastAd.id,
814
+ impId: correlator,
815
+ creativeId: vastAd.id,
816
+ currency: "USD",
817
+ durationSec: vastAd.duration
818
+ };
819
+ return [
820
+ 2,
821
+ [
822
+ bid
823
+ ]
824
+ ];
825
+ case 4:
826
+ error = _state.sent();
827
+ clearTimeout(timeoutId);
828
+ if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
829
+ warn("VAST request timed out after ".concat(DEFAULT_TIMEOUT_MS, "ms"));
830
+ return [
831
+ 2,
832
+ []
833
+ ];
834
+ }
835
+ throw error;
836
+ case 5:
837
+ return [
838
+ 2
839
+ ];
840
+ }
841
+ });
842
+ })();
843
+ }
844
+ function requestBidsUntilResponse(context) {
845
+ return _async_to_generator(function() {
846
+ var _loop, lastError, attempt, _ret;
847
+ return _ts_generator(this, function(_state) {
848
+ switch(_state.label){
849
+ case 0:
850
+ _loop = function(attempt) {
851
+ var bids, err, delay;
852
+ return _ts_generator(this, function(_state) {
853
+ switch(_state.label){
854
+ case 0:
855
+ _state.trys.push([
856
+ 0,
857
+ 2,
858
+ ,
859
+ 3
860
+ ]);
861
+ return [
862
+ 4,
863
+ requestBids(context)
864
+ ];
865
+ case 1:
866
+ bids = _state.sent();
867
+ if (bids.length > 0) {
868
+ log("requestBidsUntilResponse: got ".concat(bids.length, " ad(s) on attempt ").concat(attempt));
869
+ return [
870
+ 2,
871
+ {
872
+ v: bids
873
+ }
874
+ ];
875
+ }
876
+ log("requestBidsUntilResponse: no ads on attempt ".concat(attempt, "/").concat(MAX_RETRIES));
877
+ return [
878
+ 3,
879
+ 3
880
+ ];
881
+ case 2:
882
+ err = _state.sent();
883
+ lastError = err;
884
+ warn("requestBidsUntilResponse: attempt ".concat(attempt, "/").concat(MAX_RETRIES, " failed:"), err);
885
+ return [
886
+ 3,
887
+ 3
888
+ ];
889
+ case 3:
890
+ if (!(attempt < MAX_RETRIES)) return [
891
+ 3,
892
+ 5
893
+ ];
894
+ delay = RETRY_BACKOFF_MS * attempt;
895
+ log("requestBidsUntilResponse: waiting ".concat(delay, "ms before retry"));
896
+ return [
897
+ 4,
898
+ new Promise(function(resolve) {
899
+ return setTimeout(resolve, delay);
900
+ })
901
+ ];
902
+ case 4:
903
+ _state.sent();
904
+ _state.label = 5;
905
+ case 5:
906
+ return [
907
+ 2
908
+ ];
909
+ }
910
+ });
911
+ };
912
+ if (!initialized) {
913
+ throw new Error("VastManager not initialized. Call initialize() first.");
914
+ }
915
+ attempt = 1;
916
+ _state.label = 1;
917
+ case 1:
918
+ if (!(attempt <= MAX_RETRIES)) return [
919
+ 3,
920
+ 4
921
+ ];
922
+ return [
923
+ 5,
924
+ _ts_values(_loop(attempt))
925
+ ];
926
+ case 2:
927
+ _ret = _state.sent();
928
+ if (_type_of(_ret) === "object") return [
929
+ 2,
930
+ _ret.v
931
+ ];
932
+ _state.label = 3;
933
+ case 3:
934
+ attempt++;
935
+ return [
936
+ 3,
937
+ 1
938
+ ];
939
+ case 4:
940
+ if (_instanceof(lastError, Error)) throw lastError;
941
+ return [
942
+ 2,
943
+ []
944
+ ];
945
+ }
946
+ });
947
+ })();
948
+ }
949
+ function destroy() {
950
+ initialized = false;
951
+ log("Destroyed");
952
+ }
953
+ return {
954
+ initialize: initialize,
955
+ requestBids: requestBids,
956
+ requestBidsUntilResponse: requestBidsUntilResponse,
957
+ destroy: destroy,
958
+ get isInitialized () {
959
+ return initialized;
960
+ }
961
+ };
1058
962
  }
1059
- // src/sdk/prebidAdLayer.ts
963
+ // src/sdk/vastAdLayer.ts
1060
964
  var import_hls = __toESM(require("hls.js"), 1);
1061
- var LOG = "[PrebidAdLayer]";
965
+ var LOG = "[VastAdLayer]";
1062
966
  function resolveBidToVastAd(winner, logPrefix) {
1063
967
  if (winner.vastXml) {
1064
968
  var ad = parseVastXml(winner.vastXml, "mp4-first", logPrefix);
@@ -1069,15 +973,17 @@ function resolveBidToVastAd(winner, logPrefix) {
1069
973
  }
1070
974
  return Promise.resolve(null);
1071
975
  }
1072
- function createPrebidAdLayer(contentVideo, options) {
1073
- var _ref, _ref1;
976
+ function createVastAdLayer(contentVideo, options) {
977
+ var _ref, _ref1, _ref2, _ref3;
1074
978
  var adPlaying = false;
1075
979
  var originalMutedState = false;
1076
980
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
1077
981
  var listeners = /* @__PURE__ */ new Map();
1078
982
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
1079
983
  var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
1080
- var debug = (_ref1 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref1 !== void 0 ? _ref1 : false;
984
+ var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
985
+ var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
986
+ var debug = (_ref3 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref3 !== void 0 ? _ref3 : false;
1081
987
  var adVideoElement;
1082
988
  var adHls;
1083
989
  var adContainerEl;
@@ -1086,6 +992,7 @@ function createPrebidAdLayer(contentVideo, options) {
1086
992
  var destroyed = false;
1087
993
  var tornDown = false;
1088
994
  var trackingFired = createEmptyTrackingState();
995
+ var currentAdEventHandlers;
1089
996
  var preloadSlots = /* @__PURE__ */ new Map();
1090
997
  function emit(event, payload) {
1091
998
  var set = listeners.get(event);
@@ -1188,63 +1095,86 @@ function createPrebidAdLayer(contentVideo, options) {
1188
1095
  video.volume = 1;
1189
1096
  return video;
1190
1097
  }
1098
+ function removeAdEventListeners() {
1099
+ if (!currentAdEventHandlers || !adVideoElement) return;
1100
+ var el = adVideoElement;
1101
+ el.removeEventListener("timeupdate", currentAdEventHandlers.timeupdate);
1102
+ el.removeEventListener("playing", currentAdEventHandlers.playing);
1103
+ el.removeEventListener("ended", currentAdEventHandlers.ended);
1104
+ el.removeEventListener("error", currentAdEventHandlers.error);
1105
+ el.removeEventListener("volumechange", currentAdEventHandlers.volumechange);
1106
+ el.removeEventListener("pause", currentAdEventHandlers.pause);
1107
+ el.removeEventListener("play", currentAdEventHandlers.play);
1108
+ currentAdEventHandlers = void 0;
1109
+ }
1191
1110
  function setupAdEventListeners() {
1192
1111
  if (!adVideoElement) return;
1193
- adVideoElement.addEventListener("timeupdate", function() {
1194
- var ad = currentAd;
1195
- if (!ad || !adVideoElement) return;
1196
- var progress = adVideoElement.currentTime / ad.duration;
1197
- if (progress >= 0.25 && !trackingFired.firstQuartile) {
1198
- trackingFired.firstQuartile = true;
1199
- fireTrackingPixels2(ad.trackingUrls.firstQuartile);
1200
- }
1201
- if (progress >= 0.5 && !trackingFired.midpoint) {
1202
- trackingFired.midpoint = true;
1203
- fireTrackingPixels2(ad.trackingUrls.midpoint);
1204
- }
1205
- if (progress >= 0.75 && !trackingFired.thirdQuartile) {
1206
- trackingFired.thirdQuartile = true;
1207
- fireTrackingPixels2(ad.trackingUrls.thirdQuartile);
1208
- }
1209
- });
1210
- adVideoElement.addEventListener("playing", function() {
1211
- var ad = currentAd;
1212
- if (!ad || trackingFired.start) return;
1213
- trackingFired.start = true;
1214
- fireTrackingPixels2(ad.trackingUrls.start);
1215
- if (debug) console.log("".concat(LOG, " Ad started playing"));
1216
- });
1217
- adVideoElement.addEventListener("ended", function() {
1218
- if (tornDown || !currentAd || trackingFired.complete) return;
1219
- trackingFired.complete = true;
1220
- fireTrackingPixels2(currentAd.trackingUrls.complete);
1221
- if (debug) console.log("".concat(LOG, " Ad completed"));
1222
- handleAdComplete();
1223
- });
1224
- adVideoElement.addEventListener("error", function(e) {
1225
- if (tornDown) return;
1226
- console.error("".concat(LOG, " Ad video error:"), e);
1227
- if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
1228
- handleAdError();
1229
- });
1230
- adVideoElement.addEventListener("volumechange", function() {
1231
- if (!currentAd || !adVideoElement) return;
1232
- if (adVideoElement.muted) {
1233
- fireTrackingPixels2(currentAd.trackingUrls.mute);
1234
- } else {
1235
- fireTrackingPixels2(currentAd.trackingUrls.unmute);
1236
- }
1237
- });
1238
- adVideoElement.addEventListener("pause", function() {
1239
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1240
- fireTrackingPixels2(currentAd.trackingUrls.pause);
1241
- }
1242
- });
1243
- adVideoElement.addEventListener("play", function() {
1244
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1245
- fireTrackingPixels2(currentAd.trackingUrls.resume);
1112
+ removeAdEventListeners();
1113
+ var handlers = {
1114
+ timeupdate: function timeupdate() {
1115
+ var ad = currentAd;
1116
+ if (!ad || !adVideoElement) return;
1117
+ var progress = adVideoElement.currentTime / ad.duration;
1118
+ if (progress >= 0.25 && !trackingFired.firstQuartile) {
1119
+ trackingFired.firstQuartile = true;
1120
+ fireTrackingPixels2(ad.trackingUrls.firstQuartile);
1121
+ }
1122
+ if (progress >= 0.5 && !trackingFired.midpoint) {
1123
+ trackingFired.midpoint = true;
1124
+ fireTrackingPixels2(ad.trackingUrls.midpoint);
1125
+ }
1126
+ if (progress >= 0.75 && !trackingFired.thirdQuartile) {
1127
+ trackingFired.thirdQuartile = true;
1128
+ fireTrackingPixels2(ad.trackingUrls.thirdQuartile);
1129
+ }
1130
+ },
1131
+ playing: function playing() {
1132
+ var ad = currentAd;
1133
+ if (!ad || trackingFired.start) return;
1134
+ trackingFired.start = true;
1135
+ fireTrackingPixels2(ad.trackingUrls.start);
1136
+ if (debug) console.log("".concat(LOG, " Ad started playing"));
1137
+ },
1138
+ ended: function ended() {
1139
+ if (tornDown || !currentAd || trackingFired.complete) return;
1140
+ trackingFired.complete = true;
1141
+ fireTrackingPixels2(currentAd.trackingUrls.complete);
1142
+ if (debug) console.log("".concat(LOG, " Ad completed"));
1143
+ handleAdComplete();
1144
+ },
1145
+ error: function error(e) {
1146
+ if (tornDown) return;
1147
+ console.error("".concat(LOG, " Ad video error:"), e);
1148
+ if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
1149
+ handleAdError();
1150
+ },
1151
+ volumechange: function volumechange() {
1152
+ if (!currentAd || !adVideoElement) return;
1153
+ if (adVideoElement.muted) {
1154
+ fireTrackingPixels2(currentAd.trackingUrls.mute);
1155
+ } else {
1156
+ fireTrackingPixels2(currentAd.trackingUrls.unmute);
1157
+ }
1158
+ },
1159
+ pause: function pause() {
1160
+ if (currentAd && adVideoElement && !adVideoElement.ended) {
1161
+ fireTrackingPixels2(currentAd.trackingUrls.pause);
1162
+ }
1163
+ },
1164
+ play: function play() {
1165
+ if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1166
+ fireTrackingPixels2(currentAd.trackingUrls.resume);
1167
+ }
1246
1168
  }
1247
- });
1169
+ };
1170
+ adVideoElement.addEventListener("timeupdate", handlers.timeupdate);
1171
+ adVideoElement.addEventListener("playing", handlers.playing);
1172
+ adVideoElement.addEventListener("ended", handlers.ended);
1173
+ adVideoElement.addEventListener("error", handlers.error);
1174
+ adVideoElement.addEventListener("volumechange", handlers.volumechange);
1175
+ adVideoElement.addEventListener("pause", handlers.pause);
1176
+ adVideoElement.addEventListener("play", handlers.play);
1177
+ currentAdEventHandlers = handlers;
1248
1178
  }
1249
1179
  function setAdPlayingFlag(isPlaying) {
1250
1180
  if (isPlaying) {
@@ -1267,6 +1197,7 @@ function createPrebidAdLayer(contentVideo, options) {
1267
1197
  }
1268
1198
  function handleAdError() {
1269
1199
  if (tornDown) return;
1200
+ if (!adPlaying) return;
1270
1201
  if (debug) console.log("".concat(LOG, " Handling ad error"));
1271
1202
  adPlaying = false;
1272
1203
  setAdPlayingFlag(false);
@@ -1277,14 +1208,19 @@ function createPrebidAdLayer(contentVideo, options) {
1277
1208
  emit("ad_error");
1278
1209
  }
1279
1210
  function teardownCurrentPlayback() {
1211
+ removeAdEventListeners();
1280
1212
  if (adHls) {
1281
1213
  adHls.destroy();
1282
1214
  adHls = void 0;
1283
1215
  }
1284
1216
  if (adVideoElement) {
1285
- adVideoElement.pause();
1286
- adVideoElement.removeAttribute("src");
1287
- adVideoElement.load();
1217
+ if (singleElementMode && adVideoElement === contentVideo) {
1218
+ contentVideo.pause();
1219
+ } else {
1220
+ adVideoElement.pause();
1221
+ adVideoElement.removeAttribute("src");
1222
+ adVideoElement.load();
1223
+ }
1288
1224
  }
1289
1225
  }
1290
1226
  function startNativePlayback(mediaFile) {
@@ -1317,8 +1253,17 @@ function createPrebidAdLayer(contentVideo, options) {
1317
1253
  handleAdError();
1318
1254
  });
1319
1255
  });
1256
+ var nonFatalNetworkErrors = 0;
1320
1257
  adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1321
- if (data.fatal) handleAdError();
1258
+ if (data.fatal) {
1259
+ handleAdError();
1260
+ } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1261
+ nonFatalNetworkErrors++;
1262
+ if (nonFatalNetworkErrors >= 3) {
1263
+ if (debug) console.warn("".concat(LOG, " Too many non-fatal HLS network errors (").concat(nonFatalNetworkErrors, "), treating as fatal"));
1264
+ handleAdError();
1265
+ }
1266
+ }
1322
1267
  });
1323
1268
  } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
1324
1269
  adVideoElement.src = mediaFile.url;
@@ -1341,7 +1286,7 @@ function createPrebidAdLayer(contentVideo, options) {
1341
1286
  }
1342
1287
  function playAd(bids) {
1343
1288
  return _async_to_generator(function() {
1344
- var winner, ad, _contentVideo_parentElement, container, contentVolume, adVolume, mediaFile;
1289
+ var winner, ad, contentVolume, _contentVideo_parentElement, container, adVolume, mediaFile;
1345
1290
  return _ts_generator(this, function(_state) {
1346
1291
  switch(_state.label){
1347
1292
  case 0:
@@ -1383,32 +1328,40 @@ function createPrebidAdLayer(contentVideo, options) {
1383
1328
  trackingFired = _object_spread({}, createEmptyTrackingState());
1384
1329
  fireTrackingPixels2(ad.trackingUrls.impression);
1385
1330
  trackingFired.impression = true;
1386
- if (!adContainerEl) {
1387
- ;
1388
- container = document.createElement("div");
1389
- container.style.position = "absolute";
1390
- container.style.left = "0";
1391
- container.style.top = "0";
1392
- container.style.right = "0";
1393
- container.style.bottom = "0";
1394
- container.style.display = "none";
1395
- container.style.alignItems = "center";
1396
- container.style.justifyContent = "center";
1397
- container.style.pointerEvents = "none";
1398
- container.style.zIndex = "10";
1399
- container.style.backgroundColor = "#000";
1400
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1401
- adContainerEl = container;
1402
- }
1403
- if (!adVideoElement) {
1404
- adVideoElement = createAdVideoElement();
1405
- adContainerEl.appendChild(adVideoElement);
1331
+ contentVolume = contentVideo.volume;
1332
+ originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1333
+ if (singleElementMode) {
1334
+ mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1335
+ teardownCurrentPlayback();
1336
+ adVideoElement = contentVideo;
1337
+ adHls = void 0;
1406
1338
  setupAdEventListeners();
1407
1339
  } else {
1408
- teardownCurrentPlayback();
1340
+ if (!adContainerEl) {
1341
+ ;
1342
+ container = document.createElement("div");
1343
+ container.style.position = "absolute";
1344
+ container.style.left = "0";
1345
+ container.style.top = "0";
1346
+ container.style.right = "0";
1347
+ container.style.bottom = "0";
1348
+ container.style.display = "none";
1349
+ container.style.alignItems = "center";
1350
+ container.style.justifyContent = "center";
1351
+ container.style.pointerEvents = "none";
1352
+ container.style.zIndex = "10";
1353
+ container.style.backgroundColor = "#000";
1354
+ (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1355
+ adContainerEl = container;
1356
+ }
1357
+ if (!adVideoElement) {
1358
+ adVideoElement = createAdVideoElement();
1359
+ adContainerEl.appendChild(adVideoElement);
1360
+ setupAdEventListeners();
1361
+ } else {
1362
+ teardownCurrentPlayback();
1363
+ }
1409
1364
  }
1410
- contentVolume = contentVideo.volume;
1411
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1412
1365
  if (!continueLiveStreamDuringAds) {
1413
1366
  contentVideo.pause();
1414
1367
  }
@@ -1419,7 +1372,7 @@ function createPrebidAdLayer(contentVideo, options) {
1419
1372
  adVolume = originalMutedState ? 1 : originalVolume;
1420
1373
  adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1421
1374
  adVideoElement.muted = false;
1422
- if (adContainerEl) {
1375
+ if (!singleElementMode && adContainerEl) {
1423
1376
  adContainerEl.style.display = "flex";
1424
1377
  adContainerEl.style.pointerEvents = "auto";
1425
1378
  }
@@ -1456,7 +1409,7 @@ function createPrebidAdLayer(contentVideo, options) {
1456
1409
  }
1457
1410
  function preloadAd(bids, token) {
1458
1411
  return _async_to_generator(function() {
1459
- var winner, ad, mediaFile, videoEl, container, hls, slot, slot1;
1412
+ var winner, ad, mediaFile, slot, videoEl, container, hls, slot1, slot2;
1460
1413
  return _ts_generator(this, function(_state) {
1461
1414
  switch(_state.label){
1462
1415
  case 0:
@@ -1481,6 +1434,20 @@ function createPrebidAdLayer(contentVideo, options) {
1481
1434
  if (!mediaFile) return [
1482
1435
  2
1483
1436
  ];
1437
+ if (smartTVMode || singleElementMode) {
1438
+ slot = {
1439
+ bids: bids,
1440
+ ad: ad,
1441
+ mediaFile: mediaFile,
1442
+ videoEl: null,
1443
+ ready: true
1444
+ };
1445
+ preloadSlots.set(token, slot);
1446
+ if (debug) console.log("".concat(LOG, " [preload] Metadata-only preload (smartTV/singleElement), token=").concat(token, ", url=").concat(mediaFile.url));
1447
+ return [
1448
+ 2
1449
+ ];
1450
+ }
1484
1451
  videoEl = createAdVideoElement();
1485
1452
  videoEl.style.visibility = "hidden";
1486
1453
  videoEl.style.pointerEvents = "none";
@@ -1494,7 +1461,7 @@ function createPrebidAdLayer(contentVideo, options) {
1494
1461
  });
1495
1462
  hls.loadSource(mediaFile.url);
1496
1463
  hls.attachMedia(videoEl);
1497
- slot = {
1464
+ slot1 = {
1498
1465
  bids: bids,
1499
1466
  ad: ad,
1500
1467
  mediaFile: mediaFile,
@@ -1502,7 +1469,7 @@ function createPrebidAdLayer(contentVideo, options) {
1502
1469
  hlsInstance: hls,
1503
1470
  ready: false
1504
1471
  };
1505
- preloadSlots.set(token, slot);
1472
+ preloadSlots.set(token, slot1);
1506
1473
  hls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1507
1474
  var s = preloadSlots.get(token);
1508
1475
  if (s) s.ready = true;
@@ -1519,14 +1486,14 @@ function createPrebidAdLayer(contentVideo, options) {
1519
1486
  } else {
1520
1487
  videoEl.src = mediaFile.url;
1521
1488
  videoEl.load();
1522
- slot1 = {
1489
+ slot2 = {
1523
1490
  bids: bids,
1524
1491
  ad: ad,
1525
1492
  mediaFile: mediaFile,
1526
1493
  videoEl: videoEl,
1527
1494
  ready: false
1528
1495
  };
1529
- preloadSlots.set(token, slot1);
1496
+ preloadSlots.set(token, slot2);
1530
1497
  videoEl.addEventListener("canplay", function() {
1531
1498
  var s = preloadSlots.get(token);
1532
1499
  if (s) s.ready = true;
@@ -1545,7 +1512,7 @@ function createPrebidAdLayer(contentVideo, options) {
1545
1512
  }
1546
1513
  function playPreloaded(token) {
1547
1514
  return _async_to_generator(function() {
1548
- var slot, contentVolume, adVolume, container;
1515
+ var slot, contentVolume, adVolume2, videoEl, container2, adVolume21, adVolume, container;
1549
1516
  return _ts_generator(this, function(_state) {
1550
1517
  if (destroyed) return [
1551
1518
  2,
@@ -1560,6 +1527,68 @@ function createPrebidAdLayer(contentVideo, options) {
1560
1527
  }
1561
1528
  preloadSlots.delete(token);
1562
1529
  if (debug) console.log("".concat(LOG, " [preload] Playing preloaded ad, token=").concat(token, ", ready=").concat(slot.ready));
1530
+ contentVolume = contentVideo.volume;
1531
+ originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1532
+ sessionId = generateSessionId();
1533
+ currentAd = slot.ad;
1534
+ trackingFired = _object_spread({}, createEmptyTrackingState());
1535
+ fireTrackingPixels2(slot.ad.trackingUrls.impression);
1536
+ trackingFired.impression = true;
1537
+ if (singleElementMode) {
1538
+ mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1539
+ teardownCurrentPlayback();
1540
+ adVideoElement = contentVideo;
1541
+ adHls = void 0;
1542
+ setupAdEventListeners();
1543
+ if (!continueLiveStreamDuringAds) {
1544
+ contentVideo.pause();
1545
+ }
1546
+ contentVideo.muted = true;
1547
+ contentVideo.volume = 0;
1548
+ adPlaying = true;
1549
+ setAdPlayingFlag(true);
1550
+ adVolume2 = originalMutedState ? 1 : originalVolume;
1551
+ contentVideo.volume = Math.max(0, Math.min(1, adVolume2));
1552
+ contentVideo.muted = false;
1553
+ emit("content_pause");
1554
+ if (debug) console.log("".concat(LOG, " [preload] singleElementMode: attaching ad to contentVideo, url=").concat(slot.mediaFile.url));
1555
+ startPlayback(slot.mediaFile);
1556
+ return [
1557
+ 2
1558
+ ];
1559
+ }
1560
+ if (smartTVMode && !slot.videoEl) {
1561
+ teardownCurrentPlayback();
1562
+ if (adVideoElement) {
1563
+ adVideoElement.remove();
1564
+ adVideoElement = void 0;
1565
+ }
1566
+ videoEl = createAdVideoElement();
1567
+ videoEl.style.visibility = "visible";
1568
+ videoEl.style.pointerEvents = "none";
1569
+ container2 = ensureAdContainer();
1570
+ container2.appendChild(videoEl);
1571
+ adVideoElement = videoEl;
1572
+ setupAdEventListeners();
1573
+ if (!continueLiveStreamDuringAds) {
1574
+ contentVideo.pause();
1575
+ }
1576
+ contentVideo.muted = true;
1577
+ contentVideo.volume = 0;
1578
+ adPlaying = true;
1579
+ setAdPlayingFlag(true);
1580
+ adVolume21 = originalMutedState ? 1 : originalVolume;
1581
+ adVideoElement.volume = Math.max(0, Math.min(1, adVolume21));
1582
+ adVideoElement.muted = false;
1583
+ container2.style.display = "flex";
1584
+ container2.style.pointerEvents = "auto";
1585
+ emit("content_pause");
1586
+ if (debug) console.log("".concat(LOG, " [preload] smartTVMode deferred: creating video element and loading, url=").concat(slot.mediaFile.url));
1587
+ startPlayback(slot.mediaFile);
1588
+ return [
1589
+ 2
1590
+ ];
1591
+ }
1563
1592
  teardownCurrentPlayback();
1564
1593
  if (adVideoElement && adVideoElement !== slot.videoEl) {
1565
1594
  adVideoElement.remove();
@@ -1569,13 +1598,6 @@ function createPrebidAdLayer(contentVideo, options) {
1569
1598
  adVideoElement = slot.videoEl;
1570
1599
  adHls = slot.hlsInstance;
1571
1600
  setupAdEventListeners();
1572
- sessionId = generateSessionId();
1573
- currentAd = slot.ad;
1574
- trackingFired = _object_spread({}, createEmptyTrackingState());
1575
- fireTrackingPixels2(slot.ad.trackingUrls.impression);
1576
- trackingFired.impression = true;
1577
- contentVolume = contentVideo.volume;
1578
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1579
1601
  if (!continueLiveStreamDuringAds) {
1580
1602
  contentVideo.pause();
1581
1603
  }
@@ -1590,17 +1612,10 @@ function createPrebidAdLayer(contentVideo, options) {
1590
1612
  container.style.display = "flex";
1591
1613
  container.style.pointerEvents = "auto";
1592
1614
  emit("content_pause");
1593
- if (slot.hlsInstance) {
1594
- adVideoElement.play().catch(function(error) {
1595
- console.error("".concat(LOG, " [preload] Error playing preloaded HLS ad:"), error);
1596
- handleAdError();
1597
- });
1598
- } else {
1599
- adVideoElement.play().catch(function(error) {
1600
- console.error("".concat(LOG, " [preload] Error playing preloaded ad:"), error);
1601
- handleAdError();
1602
- });
1603
- }
1615
+ adVideoElement.play().catch(function(error) {
1616
+ console.error("".concat(LOG, " [preload] Error playing preloaded ad:"), error);
1617
+ handleAdError();
1618
+ });
1604
1619
  return [
1605
1620
  2
1606
1621
  ];
@@ -1614,10 +1629,12 @@ function createPrebidAdLayer(contentVideo, options) {
1614
1629
  if (slot.hlsInstance) {
1615
1630
  slot.hlsInstance.destroy();
1616
1631
  }
1617
- slot.videoEl.pause();
1618
- slot.videoEl.removeAttribute("src");
1619
- slot.videoEl.load();
1620
- slot.videoEl.remove();
1632
+ if (slot.videoEl) {
1633
+ slot.videoEl.pause();
1634
+ slot.videoEl.removeAttribute("src");
1635
+ slot.videoEl.load();
1636
+ slot.videoEl.remove();
1637
+ }
1621
1638
  if (debug) console.log("".concat(LOG, " [preload] Cancelled and cleaned up token=").concat(token));
1622
1639
  }
1623
1640
  return {
@@ -1665,20 +1682,27 @@ function createPrebidAdLayer(contentVideo, options) {
1665
1682
  setAdPlayingFlag(false);
1666
1683
  contentVideo.muted = originalMutedState;
1667
1684
  contentVideo.volume = originalMutedState ? 0 : originalVolume;
1668
- if (adContainerEl) {
1669
- adContainerEl.style.display = "none";
1670
- adContainerEl.style.pointerEvents = "none";
1671
- }
1672
1685
  contentVideo.style.visibility = "visible";
1673
1686
  contentVideo.style.opacity = "1";
1674
- if (continueLiveStreamDuringAds) {
1675
- contentVideo.play().catch(function() {});
1676
- }
1677
- teardownCurrentPlayback();
1678
- if (adVideoElement) {
1679
- adVideoElement.pause();
1680
- adVideoElement.removeAttribute("src");
1681
- adVideoElement.load();
1687
+ if (singleElementMode) {
1688
+ teardownCurrentPlayback();
1689
+ contentVideo.removeAttribute("src");
1690
+ contentVideo.load();
1691
+ adVideoElement = void 0;
1692
+ } else {
1693
+ if (adContainerEl) {
1694
+ adContainerEl.style.display = "none";
1695
+ adContainerEl.style.pointerEvents = "none";
1696
+ }
1697
+ if (continueLiveStreamDuringAds) {
1698
+ contentVideo.play().catch(function() {});
1699
+ }
1700
+ teardownCurrentPlayback();
1701
+ if (adVideoElement) {
1702
+ adVideoElement.pause();
1703
+ adVideoElement.removeAttribute("src");
1704
+ adVideoElement.load();
1705
+ }
1682
1706
  }
1683
1707
  currentAd = void 0;
1684
1708
  tornDown = false;
@@ -1718,9 +1742,14 @@ function createPrebidAdLayer(contentVideo, options) {
1718
1742
  }
1719
1743
  teardownCurrentPlayback();
1720
1744
  if (adVideoElement) {
1721
- adVideoElement.pause();
1722
- adVideoElement.removeAttribute("src");
1723
- adVideoElement.remove();
1745
+ if (singleElementMode && adVideoElement === contentVideo) {
1746
+ contentVideo.removeAttribute("src");
1747
+ contentVideo.load();
1748
+ } else {
1749
+ adVideoElement.pause();
1750
+ adVideoElement.removeAttribute("src");
1751
+ adVideoElement.remove();
1752
+ }
1724
1753
  adVideoElement = void 0;
1725
1754
  }
1726
1755
  if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
@@ -2915,11 +2944,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2915
2944
  this.video = config.videoElement;
2916
2945
  this.adTransitionGapMs = (_this_config_adTransitionGapMs = this.config.adTransitionGapMs) !== null && _this_config_adTransitionGapMs !== void 0 ? _this_config_adTransitionGapMs : 100;
2917
2946
  logBrowserInfo(config.debugAdTiming);
2918
- this.prebidManager = createPrebidManager(config.debugAdTiming !== void 0 ? {
2947
+ this.vastManager = createVastManager(config.debugAdTiming !== void 0 ? {
2919
2948
  debug: !!config.debugAdTiming
2920
2949
  } : {});
2921
- this.adLayer = createPrebidAdLayer(this.video, {
2950
+ var browserForAdLayer = detectBrowser();
2951
+ this.adLayer = createVastAdLayer(this.video, {
2922
2952
  continueLiveStreamDuringAds: false,
2953
+ smartTVMode: browserForAdLayer.isSmartTV,
2954
+ singleElementMode: browserForAdLayer.isSmartTV,
2923
2955
  debug: !!config.debugAdTiming
2924
2956
  });
2925
2957
  }
@@ -2931,19 +2963,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2931
2963
  return _ts_generator(this, function(_state) {
2932
2964
  switch(_state.label){
2933
2965
  case 0:
2934
- if (this.config.disablePrebid) return [
2966
+ if (this.config.disableAds) return [
2935
2967
  2,
2936
2968
  []
2937
2969
  ];
2938
2970
  return [
2939
2971
  4,
2940
- this.prebidManager.initialize()
2972
+ this.vastManager.initialize()
2941
2973
  ];
2942
2974
  case 1:
2943
2975
  _state.sent();
2944
2976
  return [
2945
2977
  2,
2946
- this.prebidManager.requestBidsUntilResponse(context)
2978
+ this.vastManager.requestBidsUntilResponse(context)
2947
2979
  ];
2948
2980
  }
2949
2981
  });
@@ -2978,7 +3010,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2978
3010
  adBehavior: "vod (main video pauses during ads)"
2979
3011
  });
2980
3012
  }
2981
- if (!this.config.disablePrebid) {
3013
+ if (!this.config.disableAds) {
2982
3014
  this.adLayer.updateOptions({
2983
3015
  continueLiveStreamDuringAds: false,
2984
3016
  mainHlsInstance: null
@@ -3046,7 +3078,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3046
3078
  adBehavior: adBehavior
3047
3079
  });
3048
3080
  }
3049
- if (!this.config.disablePrebid) {
3081
+ if (!this.config.disableAds) {
3050
3082
  ;
3051
3083
  this.adLayer.updateOptions({
3052
3084
  continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),
@@ -3367,7 +3399,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3367
3399
  {
3368
3400
  key: "getAdSource",
3369
3401
  value: function getAdSource() {
3370
- return "prebid";
3402
+ return "vast";
3371
3403
  }
3372
3404
  },
3373
3405
  {
@@ -3613,7 +3645,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3613
3645
  this.attached = true;
3614
3646
  this.video.autoplay = !!this.config.autoplay;
3615
3647
  this.video.muted = !!this.config.muted;
3616
- if (!this.config.disablePrebid) {
3648
+ if (!this.config.disableAds) {
3617
3649
  this.adLayer.initialize();
3618
3650
  if (!this.config.disableFiller) {
3619
3651
  this.ensureFillerVideo();
@@ -3809,7 +3841,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3809
3841
  key: "onScte35Marker",
3810
3842
  value: function onScte35Marker(marker) {
3811
3843
  var _this = this;
3812
- if (this.config.disablePrebid) return;
3844
+ if (this.config.disableAds) return;
3813
3845
  if (this.config.debugAdTiming) {
3814
3846
  console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
3815
3847
  type: marker.type,
@@ -4281,13 +4313,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4281
4313
  if (!this.isLiveStream) {
4282
4314
  return false;
4283
4315
  }
4316
+ var browser = detectBrowser();
4317
+ if (browser.isSmartTV) {
4318
+ return false;
4319
+ }
4284
4320
  return true;
4285
4321
  }
4286
4322
  },
4287
4323
  {
4288
4324
  key: "startAdPrefetch",
4289
4325
  value: function startAdPrefetch(marker, fragmentSn) {
4290
- if (this.config.disablePrebid) return;
4326
+ if (this.config.disableAds) return;
4291
4327
  if (this.pendingAdBreak || this.inAdBreak) {
4292
4328
  return;
4293
4329
  }
@@ -4309,25 +4345,75 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4309
4345
  key: "runAdPrefetch",
4310
4346
  value: function runAdPrefetch(marker) {
4311
4347
  return _async_to_generator(function() {
4312
- var _this, _marker_durationSeconds, durSec, estimatedCount, context, fetches, results, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, result, token;
4348
+ var _this, _marker_durationSeconds, _ref, _firstBids_, durSec, context, firstBids, unused, adDurationSec, estimatedCount, firstToken, remaining, results, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, result, token;
4313
4349
  return _ts_generator(this, function(_state) {
4314
4350
  switch(_state.label){
4315
4351
  case 0:
4316
4352
  _this = this;
4317
4353
  durSec = (_marker_durationSeconds = marker.durationSeconds) !== null && _marker_durationSeconds !== void 0 ? _marker_durationSeconds : 60;
4318
- estimatedCount = Math.min(4, Math.max(1, Math.ceil(durSec / 30)));
4319
- if (this.config.debugAdTiming) {
4320
- console.log("[PREFETCH] Firing ".concat(estimatedCount, " parallel bid request(s) for ").concat(durSec, "s break"));
4321
- }
4322
4354
  context = {
4323
4355
  breakDurationSec: durSec,
4324
4356
  remainingBreakSec: durSec
4325
4357
  };
4326
- fetches = Array.from({
4327
- length: estimatedCount
4358
+ _state.label = 1;
4359
+ case 1:
4360
+ _state.trys.push([
4361
+ 1,
4362
+ 3,
4363
+ ,
4364
+ 4
4365
+ ]);
4366
+ return [
4367
+ 4,
4368
+ this.adRequest(_object_spread_props(_object_spread({}, context), {
4369
+ adIndex: 1
4370
+ }))
4371
+ ];
4372
+ case 2:
4373
+ firstBids = _state.sent();
4374
+ return [
4375
+ 3,
4376
+ 4
4377
+ ];
4378
+ case 3:
4379
+ unused = _state.sent();
4380
+ firstBids = [];
4381
+ return [
4382
+ 3,
4383
+ 4
4384
+ ];
4385
+ case 4:
4386
+ if (this.inAdBreak) return [
4387
+ 2
4388
+ ];
4389
+ if (firstBids.length === 0) {
4390
+ if (this.config.debugAdTiming) {
4391
+ console.log("[PREFETCH] First VAST request returned no ad, aborting prefetch");
4392
+ }
4393
+ return [
4394
+ 2
4395
+ ];
4396
+ }
4397
+ adDurationSec = (_ref = (_firstBids_ = firstBids[0]) === null || _firstBids_ === void 0 ? void 0 : _firstBids_.durationSec) !== null && _ref !== void 0 ? _ref : 30;
4398
+ estimatedCount = Math.max(1, Math.ceil(durSec / adDurationSec));
4399
+ if (this.config.debugAdTiming) {
4400
+ console.log("[PREFETCH] Ad duration=".concat(adDurationSec, "s, break=").concat(durSec, "s → ").concat(estimatedCount, " ad(s) needed"));
4401
+ }
4402
+ firstToken = "preload_".concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 7));
4403
+ this.preloadedTokens.push(firstToken);
4404
+ void this.adLayer.preloadAd(firstBids, firstToken);
4405
+ if (this.config.debugAdTiming) {
4406
+ console.log("[PREFETCH] First ad preloading, token=".concat(firstToken));
4407
+ }
4408
+ if (!(estimatedCount > 1)) return [
4409
+ 3,
4410
+ 6
4411
+ ];
4412
+ remaining = Array.from({
4413
+ length: estimatedCount - 1
4328
4414
  }, function(_, i) {
4329
4415
  return _this.adRequest(_object_spread_props(_object_spread({}, context), {
4330
- adIndex: i + 1
4416
+ adIndex: i + 2
4331
4417
  })).then(function(bids) {
4332
4418
  return {
4333
4419
  ok: true,
@@ -4341,9 +4427,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4341
4427
  });
4342
4428
  return [
4343
4429
  4,
4344
- Promise.all(fetches)
4430
+ Promise.all(remaining)
4345
4431
  ];
4346
- case 1:
4432
+ case 5:
4347
4433
  results = _state.sent();
4348
4434
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4349
4435
  try {
@@ -4355,7 +4441,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4355
4441
  this.preloadedTokens.push(token);
4356
4442
  void this.adLayer.preloadAd(result.value, token);
4357
4443
  if (this.config.debugAdTiming) {
4358
- console.log("[PREFETCH] Bid received, preloading video token=".concat(token));
4444
+ console.log("[PREFETCH] Additional ad preloading, token=".concat(token));
4359
4445
  }
4360
4446
  }
4361
4447
  }
@@ -4373,6 +4459,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4373
4459
  }
4374
4460
  }
4375
4461
  }
4462
+ _state.label = 6;
4463
+ case 6:
4376
4464
  if (this.config.debugAdTiming) {
4377
4465
  console.log("[PREFETCH] Pre-fetch complete: ".concat(this.preloadedTokens.length, " ad(s) queued"));
4378
4466
  }
@@ -4436,7 +4524,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4436
4524
  switch(_state.label){
4437
4525
  case 0:
4438
4526
  _loop = function() {
4439
- var remaining, prefetchContext, bids, err, bids1, remainingNow, delay, elapsed, remaining1, context, bids2, remainingNow1, err1;
4527
+ var remaining, prefetchContext, bids, err, bids1, remainingNow, urgentNeedAd, delay, elapsed, remaining1, context, bids2, remainingNow1, err1, sleepMs;
4440
4528
  return _ts_generator(this, function(_state) {
4441
4529
  switch(_state.label){
4442
4530
  case 0:
@@ -4487,6 +4575,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4487
4575
  if (bids.length > 0) {
4488
4576
  _this.consecutiveFailures = 0;
4489
4577
  _this.pendingNextAdBids = bids;
4578
+ _this.totalAdsInBreak = Math.max(_this.totalAdsInBreak, _this.currentAdIndex + _this.preloadedTokens.length + 1);
4490
4579
  if (_this.config.debugAdTiming) {
4491
4580
  console.log("[CONTINUOUS-FETCH] Pre-fetched next ad stored as pending");
4492
4581
  }
@@ -4571,7 +4660,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4571
4660
  "continue"
4572
4661
  ];
4573
4662
  case 12:
4574
- delay = _this.lastAdRequestTime ? _this.minAdRequestIntervalMs + (_this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;
4663
+ urgentNeedAd = _this.inAdBreak && !_this.adLayer.isAdPlaying();
4664
+ delay = _this.lastAdRequestTime ? _this.minAdRequestIntervalMs + (!urgentNeedAd && _this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;
4575
4665
  elapsed = Date.now() - _this.lastAdRequestTime;
4576
4666
  if (!(elapsed < delay && _this.lastAdRequestTime > 0)) return [
4577
4667
  3,
@@ -4626,6 +4716,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4626
4716
  17
4627
4717
  ];
4628
4718
  _this.pendingNextAdBids = bids2;
4719
+ _this.totalAdsInBreak = Math.max(_this.totalAdsInBreak, _this.currentAdIndex + _this.preloadedTokens.length + 1);
4629
4720
  if (_this.config.debugAdTiming) {
4630
4721
  console.log("[CONTINUOUS-FETCH] Next ad response stored (ad currently playing or in transition)");
4631
4722
  }
@@ -4689,10 +4780,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4689
4780
  24
4690
4781
  ];
4691
4782
  case 24:
4783
+ sleepMs = _this.inAdBreak && !_this.adLayer.isAdPlaying() ? 0 : backoffMs();
4692
4784
  return [
4693
4785
  4,
4694
4786
  new Promise(function(r) {
4695
- return setTimeout(r, backoffMs());
4787
+ return setTimeout(r, sleepMs);
4696
4788
  })
4697
4789
  ];
4698
4790
  case 25:
@@ -4779,7 +4871,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4779
4871
  this.inAdBreak = true;
4780
4872
  this.currentAdBreakStartWallClockMs = Date.now();
4781
4873
  this.currentAdIndex = 0;
4782
- this.totalAdsInBreak = 1;
4874
+ this.totalAdsInBreak = Math.max(1, this.preloadedTokens.length);
4783
4875
  this.adPodQueue = [];
4784
4876
  if (!this.config.disableFiller) this.showAds = true;
4785
4877
  if (adBreakDurationMs != null) {
@@ -5004,6 +5096,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5004
5096
  3
5005
5097
  ];
5006
5098
  this.pendingNextAdBids = bids;
5099
+ this.totalAdsInBreak = Math.max(this.totalAdsInBreak, this.currentAdIndex + this.preloadedTokens.length);
5007
5100
  return [
5008
5101
  3,
5009
5102
  5
@@ -5372,40 +5465,45 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5372
5465
  var browser = detectBrowser();
5373
5466
  var isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0;
5374
5467
  if (isSmartTV && this.hls) {
5375
- if (!restoredMuted) {
5376
- var hlsRef = this.hls;
5377
- var savedMuted = restoredMuted;
5378
- var savedVolume = restoredVolume;
5379
- var onManifestParsedRestore = function onManifestParsedRestore1() {
5380
- hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5381
- if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5382
- if (_this.video.muted !== savedMuted) _this.video.muted = savedMuted;
5383
- if (Math.abs(_this.video.volume - savedVolume) > 0.01) _this.video.volume = savedVolume;
5384
- if (_this.config.debugAdTiming) {
5385
- console.log("[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach");
5386
- }
5468
+ var hlsRef = this.hls;
5469
+ var savedMuted = restoredMuted;
5470
+ var savedVolume = restoredVolume;
5471
+ var onManifestParsedRestore = function onManifestParsedRestore1() {
5472
+ hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5473
+ if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5474
+ var _this_video_play;
5475
+ if (_this.video.muted !== savedMuted) _this.video.muted = savedMuted;
5476
+ if (Math.abs(_this.video.volume - savedVolume) > 0.01) _this.video.volume = savedVolume;
5477
+ if (_this.config.debugAdTiming) {
5478
+ console.log("[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach");
5387
5479
  }
5388
- };
5389
- hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5390
- }
5480
+ hlsRef.startLoad(-1);
5481
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5482
+ if (_this.config.debugAdTiming) {
5483
+ console.log("[StormcloudVideoPlayer] Smart TV: seeking to live edge and resuming playback after re-attach");
5484
+ }
5485
+ }
5486
+ };
5487
+ hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5391
5488
  this.hls.attachMedia(this.video);
5392
5489
  if (this.config.debugAdTiming) {
5393
5490
  console.log("[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline");
5394
5491
  }
5395
- }
5396
- if (this.shouldContinueLiveStreamDuringAds()) {
5397
- var _this_video_play;
5398
- if (this.config.debugAdTiming) {
5399
- if (this.video.paused) {
5400
- console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
5401
- } else {
5402
- console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
5492
+ } else {
5493
+ if (this.shouldContinueLiveStreamDuringAds()) {
5494
+ var _this_video_play;
5495
+ if (this.config.debugAdTiming) {
5496
+ if (this.video.paused) {
5497
+ console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
5498
+ } else {
5499
+ console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
5500
+ }
5403
5501
  }
5502
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5503
+ } else if (this.video.paused) {
5504
+ var _this_video_play1;
5505
+ (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});
5404
5506
  }
5405
- (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5406
- } else if (this.video.paused) {
5407
- var _this_video_play1;
5408
- (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});
5409
5507
  }
5410
5508
  this.syncMainContentAudioWhenVisible();
5411
5509
  if (!restoredMuted) {
@@ -5456,6 +5554,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5456
5554
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max consecutive failures reached (".concat(this.consecutiveFailures, "), ending ad break gracefully"));
5457
5555
  }
5458
5556
  this.handleAdPodComplete();
5557
+ return;
5558
+ }
5559
+ if (this.inAdBreak && !this.config.disableFiller) {
5560
+ if (this.config.debugAdTiming) {
5561
+ console.log("[CONTINUOUS-FETCH] Ad failure in active break \u2014 showing filler while awaiting next ad");
5562
+ }
5563
+ this.showPlaceholderLayer();
5564
+ this.adLayer.showPlaceholder();
5459
5565
  }
5460
5566
  }
5461
5567
  },
@@ -5860,7 +5966,7 @@ var HlsPlayer = /*#__PURE__*/ function(_import_react_Component) {
5860
5966
  if (_this1.props.licenseKey !== void 0) config.licenseKey = _this1.props.licenseKey;
5861
5967
  if (_this1.props.adFailsafeTimeoutMs !== void 0) config.adFailsafeTimeoutMs = _this1.props.adFailsafeTimeoutMs;
5862
5968
  if (_this1.props.minSegmentsBeforePlay !== void 0) config.minSegmentsBeforePlay = _this1.props.minSegmentsBeforePlay;
5863
- if (_this1.props.disablePrebid !== void 0) config.disablePrebid = _this1.props.disablePrebid;
5969
+ if (_this1.props.disableAds !== void 0) config.disableAds = _this1.props.disableAds;
5864
5970
  _this1.player = new StormcloudVideoPlayer(config);
5865
5971
  (_this_props_onMount = (_this_props = _this1.props).onMount) === null || _this_props_onMount === void 0 ? void 0 : _this_props_onMount.call(_this_props, _this1);
5866
5972
  return [