@guardvideo/player-sdk 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/core/player.d.ts +21 -0
- package/dist/core/player.d.ts.map +1 -1
- package/dist/core/types.d.ts +33 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.esm.js +395 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +395 -1
- package/dist/index.js.map +1 -1
- package/dist/react/GuardVideoPlayer.d.ts +4 -1
- package/dist/react/GuardVideoPlayer.d.ts.map +1 -1
- package/dist/react/hooks.d.ts +5 -2
- package/dist/react/hooks.d.ts.map +1 -1
- package/dist/vanilla/core/player.d.ts +21 -0
- package/dist/vanilla/core/player.d.ts.map +1 -1
- package/dist/vanilla/core/types.d.ts +33 -0
- package/dist/vanilla/core/types.d.ts.map +1 -1
- package/dist/vanilla/guardvideo-player.js +391 -0
- package/dist/vanilla/guardvideo-player.js.map +1 -1
- package/dist/vanilla/guardvideo-player.min.js +391 -0
- package/dist/vanilla/guardvideo-player.min.js.map +1 -1
- package/dist/vanilla/react/GuardVideoPlayer.d.ts +4 -1
- package/dist/vanilla/react/GuardVideoPlayer.d.ts.map +1 -1
- package/dist/vanilla/react/hooks.d.ts +5 -2
- package/dist/vanilla/react/hooks.d.ts.map +1 -1
- package/dist/vanilla/vanilla/index.d.ts +2 -2
- package/dist/vanilla/vanilla/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -36636,14 +36636,44 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
|
|
|
36636
36636
|
PlayerState["ERROR"] = "error";
|
|
36637
36637
|
})(exports.PlayerState || (exports.PlayerState = {}));
|
|
36638
36638
|
|
|
36639
|
+
const DEFAULT_BRANDING = {
|
|
36640
|
+
name: 'GuardVideo',
|
|
36641
|
+
url: 'https://guardvid.com',
|
|
36642
|
+
logoUrl: '',
|
|
36643
|
+
accentColor: '#44c09b',
|
|
36644
|
+
};
|
|
36645
|
+
const DEFAULT_SECURITY = {
|
|
36646
|
+
disableRightClick: false,
|
|
36647
|
+
disableSelection: true,
|
|
36648
|
+
disableDrag: true,
|
|
36649
|
+
enableWatermark: false,
|
|
36650
|
+
watermarkText: '',
|
|
36651
|
+
disablePiP: false,
|
|
36652
|
+
disableScreenCapture: false,
|
|
36653
|
+
blockDevTools: false,
|
|
36654
|
+
maxPlaybackRate: 2,
|
|
36655
|
+
allowedDomains: [],
|
|
36656
|
+
};
|
|
36639
36657
|
let GuardVideoPlayer$1 = class GuardVideoPlayer {
|
|
36640
36658
|
constructor(videoElement, videoId, config) {
|
|
36641
36659
|
this.videoId = videoId;
|
|
36660
|
+
this.container = null;
|
|
36642
36661
|
this.hls = null;
|
|
36643
36662
|
this.state = exports.PlayerState.IDLE;
|
|
36644
36663
|
this.embedToken = null;
|
|
36645
36664
|
this.currentQuality = null;
|
|
36665
|
+
this.ctxMenu = null;
|
|
36666
|
+
this.ctxStyleTag = null;
|
|
36667
|
+
this.watermarkEl = null;
|
|
36668
|
+
this.watermarkObserver = null;
|
|
36669
|
+
this._onCtx = this.handleContextMenu.bind(this);
|
|
36670
|
+
this._onDocClick = this.hideContextMenu.bind(this);
|
|
36671
|
+
this._onKeyDown = this.handleKeyDown.bind(this);
|
|
36672
|
+
this._onRateChange = this.enforceMaxRate.bind(this);
|
|
36673
|
+
this._onSelectStart = (e) => e.preventDefault();
|
|
36674
|
+
this._onDragStart = (e) => e.preventDefault();
|
|
36646
36675
|
this.videoElement = videoElement;
|
|
36676
|
+
this.container = videoElement.parentElement;
|
|
36647
36677
|
this.config = {
|
|
36648
36678
|
embedTokenEndpoint: config.embedTokenEndpoint,
|
|
36649
36679
|
apiBaseUrl: config.apiBaseUrl || '',
|
|
@@ -36653,12 +36683,21 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
|
|
|
36653
36683
|
className: config.className || '',
|
|
36654
36684
|
style: config.style || {},
|
|
36655
36685
|
hlsConfig: config.hlsConfig || {},
|
|
36686
|
+
branding: { ...DEFAULT_BRANDING, ...config.branding },
|
|
36687
|
+
contextMenuItems: config.contextMenuItems || [],
|
|
36688
|
+
security: { ...DEFAULT_SECURITY, ...config.security },
|
|
36689
|
+
viewerName: config.viewerName || '',
|
|
36690
|
+
viewerEmail: config.viewerEmail || '',
|
|
36691
|
+
forensicWatermark: config.forensicWatermark || false,
|
|
36656
36692
|
onReady: config.onReady || (() => { }),
|
|
36657
36693
|
onError: config.onError || (() => { }),
|
|
36658
36694
|
onQualityChange: config.onQualityChange || (() => { }),
|
|
36659
36695
|
onStateChange: config.onStateChange || (() => { }),
|
|
36660
36696
|
};
|
|
36661
36697
|
this.log('Initializing GuardVideo Player', { videoId, config });
|
|
36698
|
+
if (!this.checkAllowedDomain())
|
|
36699
|
+
return;
|
|
36700
|
+
this.applySecurity();
|
|
36662
36701
|
this.initialize();
|
|
36663
36702
|
}
|
|
36664
36703
|
log(message, data) {
|
|
@@ -36676,12 +36715,321 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
|
|
|
36676
36715
|
this.log(`State changed to: ${newState}`);
|
|
36677
36716
|
}
|
|
36678
36717
|
}
|
|
36718
|
+
checkAllowedDomain() {
|
|
36719
|
+
const domains = this.config.security.allowedDomains;
|
|
36720
|
+
if (!domains || domains.length === 0)
|
|
36721
|
+
return true;
|
|
36722
|
+
const currentOrigin = typeof window !== 'undefined' ? window.location.origin : '';
|
|
36723
|
+
const allowed = domains.some((d) => currentOrigin === d || currentOrigin.endsWith(`.${d.replace(/^https?:\/\//, '')}`));
|
|
36724
|
+
if (!allowed) {
|
|
36725
|
+
this.handleError({
|
|
36726
|
+
code: 'DOMAIN_NOT_ALLOWED',
|
|
36727
|
+
message: `This player is not authorized to run on ${currentOrigin}`,
|
|
36728
|
+
fatal: true,
|
|
36729
|
+
});
|
|
36730
|
+
return false;
|
|
36731
|
+
}
|
|
36732
|
+
return true;
|
|
36733
|
+
}
|
|
36734
|
+
applySecurity() {
|
|
36735
|
+
const sec = this.config.security;
|
|
36736
|
+
const target = this.container || this.videoElement;
|
|
36737
|
+
target.addEventListener('contextmenu', this._onCtx);
|
|
36738
|
+
document.addEventListener('click', this._onDocClick);
|
|
36739
|
+
if (sec.disableSelection) {
|
|
36740
|
+
target.addEventListener('selectstart', this._onSelectStart);
|
|
36741
|
+
target.style.userSelect = 'none';
|
|
36742
|
+
target.style.webkitUserSelect = 'none';
|
|
36743
|
+
}
|
|
36744
|
+
if (sec.disableDrag) {
|
|
36745
|
+
this.videoElement.addEventListener('dragstart', this._onDragStart);
|
|
36746
|
+
this.videoElement.draggable = false;
|
|
36747
|
+
}
|
|
36748
|
+
if (sec.disablePiP) {
|
|
36749
|
+
this.videoElement.disablePictureInPicture = true;
|
|
36750
|
+
}
|
|
36751
|
+
if (sec.disableScreenCapture) {
|
|
36752
|
+
if ('mediaKeys' in this.videoElement && typeof navigator.requestMediaKeySystemAccess === 'function') {
|
|
36753
|
+
this.log('Screen-capture protection: EME hint applied');
|
|
36754
|
+
}
|
|
36755
|
+
target.style.setProperty('-webkit-app-region', 'no-drag');
|
|
36756
|
+
}
|
|
36757
|
+
if (sec.blockDevTools) {
|
|
36758
|
+
document.addEventListener('keydown', this._onKeyDown);
|
|
36759
|
+
}
|
|
36760
|
+
if (sec.maxPlaybackRate) {
|
|
36761
|
+
this.videoElement.addEventListener('ratechange', this._onRateChange);
|
|
36762
|
+
}
|
|
36763
|
+
if (sec.enableWatermark && sec.watermarkText && this.container) {
|
|
36764
|
+
this.createWatermark(sec.watermarkText);
|
|
36765
|
+
}
|
|
36766
|
+
this.injectProtectiveStyles();
|
|
36767
|
+
}
|
|
36768
|
+
handleContextMenu(e) {
|
|
36769
|
+
e.preventDefault();
|
|
36770
|
+
e.stopPropagation();
|
|
36771
|
+
const sec = this.config.security;
|
|
36772
|
+
if (sec.disableRightClick)
|
|
36773
|
+
return;
|
|
36774
|
+
const me = e;
|
|
36775
|
+
this.showContextMenu(me.clientX, me.clientY);
|
|
36776
|
+
}
|
|
36777
|
+
showContextMenu(x, y) {
|
|
36778
|
+
this.hideContextMenu();
|
|
36779
|
+
const branding = this.config.branding;
|
|
36780
|
+
const extraItems = this.config.contextMenuItems;
|
|
36781
|
+
const menu = document.createElement('div');
|
|
36782
|
+
menu.className = 'gv-ctx-menu';
|
|
36783
|
+
menu.setAttribute('role', 'menu');
|
|
36784
|
+
const header = document.createElement('a');
|
|
36785
|
+
header.className = 'gv-ctx-header';
|
|
36786
|
+
header.href = branding.url;
|
|
36787
|
+
header.target = '_blank';
|
|
36788
|
+
header.rel = 'noopener noreferrer';
|
|
36789
|
+
header.setAttribute('role', 'menuitem');
|
|
36790
|
+
if (branding.logoUrl) {
|
|
36791
|
+
const logo = document.createElement('img');
|
|
36792
|
+
logo.src = branding.logoUrl;
|
|
36793
|
+
logo.alt = branding.name;
|
|
36794
|
+
logo.className = 'gv-ctx-logo';
|
|
36795
|
+
logo.width = 20;
|
|
36796
|
+
logo.height = 20;
|
|
36797
|
+
header.appendChild(logo);
|
|
36798
|
+
}
|
|
36799
|
+
else {
|
|
36800
|
+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
36801
|
+
svg.setAttribute('width', '18');
|
|
36802
|
+
svg.setAttribute('height', '18');
|
|
36803
|
+
svg.setAttribute('viewBox', '0 0 24 24');
|
|
36804
|
+
svg.setAttribute('fill', 'none');
|
|
36805
|
+
svg.setAttribute('stroke', branding.accentColor);
|
|
36806
|
+
svg.setAttribute('stroke-width', '2');
|
|
36807
|
+
svg.setAttribute('stroke-linecap', 'round');
|
|
36808
|
+
svg.setAttribute('stroke-linejoin', 'round');
|
|
36809
|
+
svg.innerHTML = '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>';
|
|
36810
|
+
header.appendChild(svg);
|
|
36811
|
+
}
|
|
36812
|
+
const nameSpan = document.createElement('span');
|
|
36813
|
+
nameSpan.className = 'gv-ctx-brand-name';
|
|
36814
|
+
nameSpan.textContent = branding.name;
|
|
36815
|
+
header.appendChild(nameSpan);
|
|
36816
|
+
const tagSpan = document.createElement('span');
|
|
36817
|
+
tagSpan.className = 'gv-ctx-tag';
|
|
36818
|
+
tagSpan.textContent = 'Secure Video Player';
|
|
36819
|
+
header.appendChild(tagSpan);
|
|
36820
|
+
menu.appendChild(header);
|
|
36821
|
+
if (extraItems.length > 0) {
|
|
36822
|
+
extraItems.forEach((item) => {
|
|
36823
|
+
if (item.separator) {
|
|
36824
|
+
const sep = document.createElement('div');
|
|
36825
|
+
sep.className = 'gv-ctx-sep';
|
|
36826
|
+
menu.appendChild(sep);
|
|
36827
|
+
}
|
|
36828
|
+
const row = document.createElement('div');
|
|
36829
|
+
row.className = 'gv-ctx-item';
|
|
36830
|
+
row.setAttribute('role', 'menuitem');
|
|
36831
|
+
row.tabIndex = 0;
|
|
36832
|
+
if (item.icon) {
|
|
36833
|
+
const ico = document.createElement('img');
|
|
36834
|
+
ico.src = item.icon;
|
|
36835
|
+
ico.width = 14;
|
|
36836
|
+
ico.height = 14;
|
|
36837
|
+
ico.className = 'gv-ctx-item-icon';
|
|
36838
|
+
row.appendChild(ico);
|
|
36839
|
+
}
|
|
36840
|
+
const label = document.createElement('span');
|
|
36841
|
+
label.textContent = item.label;
|
|
36842
|
+
row.appendChild(label);
|
|
36843
|
+
row.addEventListener('click', (ev) => {
|
|
36844
|
+
ev.stopPropagation();
|
|
36845
|
+
this.hideContextMenu();
|
|
36846
|
+
if (item.onClick) {
|
|
36847
|
+
item.onClick();
|
|
36848
|
+
}
|
|
36849
|
+
else if (item.href) {
|
|
36850
|
+
window.open(item.href, '_blank', 'noopener,noreferrer');
|
|
36851
|
+
}
|
|
36852
|
+
});
|
|
36853
|
+
menu.appendChild(row);
|
|
36854
|
+
});
|
|
36855
|
+
}
|
|
36856
|
+
const sep = document.createElement('div');
|
|
36857
|
+
sep.className = 'gv-ctx-sep';
|
|
36858
|
+
menu.appendChild(sep);
|
|
36859
|
+
const version = document.createElement('div');
|
|
36860
|
+
version.className = 'gv-ctx-version';
|
|
36861
|
+
version.textContent = `${branding.name} Player v1.0`;
|
|
36862
|
+
menu.appendChild(version);
|
|
36863
|
+
document.body.appendChild(menu);
|
|
36864
|
+
const rect = menu.getBoundingClientRect();
|
|
36865
|
+
const vw = window.innerWidth;
|
|
36866
|
+
const vh = window.innerHeight;
|
|
36867
|
+
menu.style.left = `${x + rect.width > vw ? vw - rect.width - 8 : x}px`;
|
|
36868
|
+
menu.style.top = `${y + rect.height > vh ? vh - rect.height - 8 : y}px`;
|
|
36869
|
+
this.ctxMenu = menu;
|
|
36870
|
+
}
|
|
36871
|
+
hideContextMenu() {
|
|
36872
|
+
if (this.ctxMenu) {
|
|
36873
|
+
this.ctxMenu.remove();
|
|
36874
|
+
this.ctxMenu = null;
|
|
36875
|
+
}
|
|
36876
|
+
}
|
|
36877
|
+
injectProtectiveStyles() {
|
|
36878
|
+
if (this.ctxStyleTag)
|
|
36879
|
+
return;
|
|
36880
|
+
const branding = this.config.branding;
|
|
36881
|
+
const accent = branding.accentColor;
|
|
36882
|
+
const css = `
|
|
36883
|
+
/* GuardVideo branded context menu */
|
|
36884
|
+
.gv-ctx-menu {
|
|
36885
|
+
position: fixed;
|
|
36886
|
+
z-index: 2147483647;
|
|
36887
|
+
min-width: 220px;
|
|
36888
|
+
background: rgba(18, 18, 22, 0.96);
|
|
36889
|
+
backdrop-filter: blur(12px);
|
|
36890
|
+
-webkit-backdrop-filter: blur(12px);
|
|
36891
|
+
border: 1px solid rgba(255,255,255,0.08);
|
|
36892
|
+
border-radius: 10px;
|
|
36893
|
+
padding: 6px 0;
|
|
36894
|
+
box-shadow: 0 8px 32px rgba(0,0,0,0.45), 0 0 0 1px rgba(255,255,255,0.04);
|
|
36895
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
36896
|
+
font-size: 13px;
|
|
36897
|
+
color: #e4e4e7;
|
|
36898
|
+
user-select: none;
|
|
36899
|
+
animation: gv-ctx-in 0.12s ease-out;
|
|
36900
|
+
}
|
|
36901
|
+
@keyframes gv-ctx-in {
|
|
36902
|
+
from { opacity: 0; transform: scale(0.96); }
|
|
36903
|
+
to { opacity: 1; transform: scale(1); }
|
|
36904
|
+
}
|
|
36905
|
+
|
|
36906
|
+
.gv-ctx-header {
|
|
36907
|
+
display: flex;
|
|
36908
|
+
align-items: center;
|
|
36909
|
+
gap: 8px;
|
|
36910
|
+
padding: 8px 14px 8px 12px;
|
|
36911
|
+
text-decoration: none;
|
|
36912
|
+
color: inherit;
|
|
36913
|
+
transition: background 0.15s;
|
|
36914
|
+
border-radius: 6px 6px 0 0;
|
|
36915
|
+
}
|
|
36916
|
+
.gv-ctx-header:hover { background: rgba(255,255,255,0.06); }
|
|
36917
|
+
|
|
36918
|
+
.gv-ctx-logo { border-radius: 4px; }
|
|
36919
|
+
|
|
36920
|
+
.gv-ctx-brand-name {
|
|
36921
|
+
font-weight: 600;
|
|
36922
|
+
color: ${accent};
|
|
36923
|
+
white-space: nowrap;
|
|
36924
|
+
}
|
|
36925
|
+
|
|
36926
|
+
.gv-ctx-tag {
|
|
36927
|
+
margin-left: auto;
|
|
36928
|
+
font-size: 10px;
|
|
36929
|
+
color: rgba(255,255,255,0.35);
|
|
36930
|
+
white-space: nowrap;
|
|
36931
|
+
}
|
|
36932
|
+
|
|
36933
|
+
.gv-ctx-sep {
|
|
36934
|
+
height: 1px;
|
|
36935
|
+
margin: 4px 10px;
|
|
36936
|
+
background: rgba(255,255,255,0.07);
|
|
36937
|
+
}
|
|
36938
|
+
|
|
36939
|
+
.gv-ctx-item {
|
|
36940
|
+
display: flex;
|
|
36941
|
+
align-items: center;
|
|
36942
|
+
gap: 8px;
|
|
36943
|
+
padding: 7px 14px 7px 12px;
|
|
36944
|
+
cursor: pointer;
|
|
36945
|
+
transition: background 0.15s;
|
|
36946
|
+
}
|
|
36947
|
+
.gv-ctx-item:hover { background: rgba(255,255,255,0.06); }
|
|
36948
|
+
.gv-ctx-item-icon { border-radius: 2px; }
|
|
36949
|
+
|
|
36950
|
+
.gv-ctx-version {
|
|
36951
|
+
padding: 4px 14px 6px 12px;
|
|
36952
|
+
font-size: 10px;
|
|
36953
|
+
color: rgba(255,255,255,0.25);
|
|
36954
|
+
}
|
|
36955
|
+
|
|
36956
|
+
/* Watermark overlay */
|
|
36957
|
+
.gv-watermark {
|
|
36958
|
+
position: absolute;
|
|
36959
|
+
inset: 0;
|
|
36960
|
+
pointer-events: none;
|
|
36961
|
+
overflow: hidden;
|
|
36962
|
+
z-index: 10;
|
|
36963
|
+
}
|
|
36964
|
+
.gv-watermark-text {
|
|
36965
|
+
position: absolute;
|
|
36966
|
+
white-space: nowrap;
|
|
36967
|
+
font-size: 14px;
|
|
36968
|
+
font-family: monospace;
|
|
36969
|
+
color: rgba(255,255,255,0.07);
|
|
36970
|
+
transform: rotate(-30deg);
|
|
36971
|
+
user-select: none;
|
|
36972
|
+
pointer-events: none;
|
|
36973
|
+
}
|
|
36974
|
+
`;
|
|
36975
|
+
const tag = document.createElement('style');
|
|
36976
|
+
tag.setAttribute('data-guardvideo', 'player-styles');
|
|
36977
|
+
tag.textContent = css;
|
|
36978
|
+
document.head.appendChild(tag);
|
|
36979
|
+
this.ctxStyleTag = tag;
|
|
36980
|
+
}
|
|
36981
|
+
createWatermark(text) {
|
|
36982
|
+
if (!this.container)
|
|
36983
|
+
return;
|
|
36984
|
+
const overlay = document.createElement('div');
|
|
36985
|
+
overlay.className = 'gv-watermark';
|
|
36986
|
+
for (let row = 0; row < 5; row++) {
|
|
36987
|
+
for (let col = 0; col < 4; col++) {
|
|
36988
|
+
const span = document.createElement('span');
|
|
36989
|
+
span.className = 'gv-watermark-text';
|
|
36990
|
+
span.textContent = text;
|
|
36991
|
+
span.style.left = `${col * 28 + (row % 2) * 14}%`;
|
|
36992
|
+
span.style.top = `${row * 22}%`;
|
|
36993
|
+
overlay.appendChild(span);
|
|
36994
|
+
}
|
|
36995
|
+
}
|
|
36996
|
+
this.container.style.position = 'relative';
|
|
36997
|
+
this.container.appendChild(overlay);
|
|
36998
|
+
this.watermarkEl = overlay;
|
|
36999
|
+
this.watermarkObserver = new MutationObserver(() => {
|
|
37000
|
+
if (this.container && this.watermarkEl && !this.container.contains(this.watermarkEl)) {
|
|
37001
|
+
this.container.appendChild(this.watermarkEl);
|
|
37002
|
+
}
|
|
37003
|
+
});
|
|
37004
|
+
this.watermarkObserver.observe(this.container, { childList: true, subtree: false });
|
|
37005
|
+
}
|
|
37006
|
+
handleKeyDown(e) {
|
|
37007
|
+
if (e.key === 'F12') {
|
|
37008
|
+
e.preventDefault();
|
|
37009
|
+
return;
|
|
37010
|
+
}
|
|
37011
|
+
if (e.ctrlKey && e.shiftKey && ['I', 'J', 'C'].includes(e.key.toUpperCase())) {
|
|
37012
|
+
e.preventDefault();
|
|
37013
|
+
return;
|
|
37014
|
+
}
|
|
37015
|
+
if (e.ctrlKey && e.key.toUpperCase() === 'U') {
|
|
37016
|
+
e.preventDefault();
|
|
37017
|
+
}
|
|
37018
|
+
}
|
|
37019
|
+
enforceMaxRate() {
|
|
37020
|
+
const max = this.config.security.maxPlaybackRate;
|
|
37021
|
+
if (this.videoElement.playbackRate > max) {
|
|
37022
|
+
this.videoElement.playbackRate = max;
|
|
37023
|
+
this.log(`Playback rate clamped to ${max}`);
|
|
37024
|
+
}
|
|
37025
|
+
}
|
|
36679
37026
|
async initialize() {
|
|
36680
37027
|
try {
|
|
36681
37028
|
this.setState(exports.PlayerState.LOADING);
|
|
36682
37029
|
this.embedToken = await this.fetchEmbedToken();
|
|
36683
37030
|
this.log('Embed token received', this.embedToken);
|
|
36684
37031
|
await this.initializePlayer();
|
|
37032
|
+
await this.fetchAndApplyWatermark();
|
|
36685
37033
|
}
|
|
36686
37034
|
catch (err) {
|
|
36687
37035
|
this.handleError({
|
|
@@ -36692,6 +37040,35 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
|
|
|
36692
37040
|
});
|
|
36693
37041
|
}
|
|
36694
37042
|
}
|
|
37043
|
+
async fetchAndApplyWatermark() {
|
|
37044
|
+
if (!this.embedToken || !this.config.apiBaseUrl)
|
|
37045
|
+
return;
|
|
37046
|
+
try {
|
|
37047
|
+
const tokenId = this.embedToken.tokenId;
|
|
37048
|
+
const url = `${this.config.apiBaseUrl}/videos/stream/${this.videoId}/viewer-config?token=${encodeURIComponent(tokenId)}`;
|
|
37049
|
+
const resp = await fetch(url, { credentials: 'omit' });
|
|
37050
|
+
if (!resp.ok) {
|
|
37051
|
+
this.log('viewer-config fetch failed, falling back to SDK config', resp.status);
|
|
37052
|
+
const sec = this.config.security;
|
|
37053
|
+
if (sec.enableWatermark && sec.watermarkText && this.container) {
|
|
37054
|
+
this.createWatermark(sec.watermarkText);
|
|
37055
|
+
}
|
|
37056
|
+
return;
|
|
37057
|
+
}
|
|
37058
|
+
const cfg = await resp.json();
|
|
37059
|
+
this.log('Watermark config from server:', cfg);
|
|
37060
|
+
if (cfg.enableWatermark && cfg.watermarkText && this.container) {
|
|
37061
|
+
this.createWatermark(cfg.watermarkText);
|
|
37062
|
+
}
|
|
37063
|
+
}
|
|
37064
|
+
catch (err) {
|
|
37065
|
+
this.log('fetchAndApplyWatermark error (non-fatal):', err);
|
|
37066
|
+
const sec = this.config.security;
|
|
37067
|
+
if (sec.enableWatermark && sec.watermarkText && this.container) {
|
|
37068
|
+
this.createWatermark(sec.watermarkText);
|
|
37069
|
+
}
|
|
37070
|
+
}
|
|
37071
|
+
}
|
|
36695
37072
|
async fetchEmbedToken() {
|
|
36696
37073
|
const url = `${this.config.embedTokenEndpoint}/${this.videoId}`;
|
|
36697
37074
|
this.log('Fetching embed token from', url);
|
|
@@ -36704,6 +37081,9 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
|
|
|
36704
37081
|
allowedDomain: window.location.origin,
|
|
36705
37082
|
expiresInMinutes: 120,
|
|
36706
37083
|
maxViews: null,
|
|
37084
|
+
...(this.config.viewerName ? { viewerName: this.config.viewerName } : {}),
|
|
37085
|
+
...(this.config.viewerEmail ? { viewerEmail: this.config.viewerEmail } : {}),
|
|
37086
|
+
...(this.config.forensicWatermark ? { forensicWatermark: this.config.forensicWatermark } : {}),
|
|
36707
37087
|
}),
|
|
36708
37088
|
});
|
|
36709
37089
|
if (!response.ok) {
|
|
@@ -36880,6 +37260,17 @@ Schedule: ${scheduleItems.map(seg => segmentToString(seg))} pos: ${this.timeline
|
|
|
36880
37260
|
}
|
|
36881
37261
|
destroy() {
|
|
36882
37262
|
this.log('Destroying player');
|
|
37263
|
+
const target = this.container || this.videoElement;
|
|
37264
|
+
target.removeEventListener('contextmenu', this._onCtx);
|
|
37265
|
+
target.removeEventListener('selectstart', this._onSelectStart);
|
|
37266
|
+
this.videoElement.removeEventListener('dragstart', this._onDragStart);
|
|
37267
|
+
this.videoElement.removeEventListener('ratechange', this._onRateChange);
|
|
37268
|
+
document.removeEventListener('click', this._onDocClick);
|
|
37269
|
+
document.removeEventListener('keydown', this._onKeyDown);
|
|
37270
|
+
this.hideContextMenu();
|
|
37271
|
+
this.watermarkObserver?.disconnect();
|
|
37272
|
+
this.watermarkEl?.remove();
|
|
37273
|
+
this.ctxStyleTag?.remove();
|
|
36883
37274
|
if (this.hls) {
|
|
36884
37275
|
this.hls.destroy();
|
|
36885
37276
|
this.hls = null;
|