@eluvio/elv-player-js 2.1.33 → 2.1.35

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,4 +1,4 @@
1
- import { c as DI, r as tI, a as TA, b as rI, d as oA, e as uA, f as PA, g as cI } from "./index-DjFcABDu.mjs";
1
+ import { c as DI, r as tI, a as TA, b as rI, d as oA, e as uA, f as PA, g as cI } from "./index-2H2xCtem.mjs";
2
2
  class BA {
3
3
  constructor(B) {
4
4
  this.wasm = B;
@@ -1095,6 +1095,19 @@ class PlayerControls {
1095
1095
  this.player.Destroy();
1096
1096
  }
1097
1097
 
1098
+ OverlayAvailable() {
1099
+ return !!this.player.__poseOverlayTags;
1100
+ }
1101
+
1102
+ OverlayVisible() {
1103
+ return this.player.__showOverlay;
1104
+ }
1105
+
1106
+ ToggleOverlayVisibility() {
1107
+ this.player.__showOverlay = !this.player.__showOverlay;
1108
+ this.player.__SettingsUpdate();
1109
+ }
1110
+
1098
1111
  GetDebugInfo() {
1099
1112
  const sourceOptions = JSON.parse(JSON.stringify(this.player.sourceOptions));
1100
1113
  delete sourceOptions.playoutOptions;
@@ -330,6 +330,16 @@ export class EluvioPlayer {
330
330
 
331
331
  const offset = (properties || {}).start_offset_float || 0;
332
332
  const thumbnailOffset = (clipStart || 0) + (offset || 0);
333
+ let frameRate = (properties || {}).rate;
334
+ if(frameRate && typeof frameRate === "string") {
335
+ const [num, denom] = frameRate.split("/");
336
+
337
+ if(!denom) {
338
+ frameRate = parseInt(num);
339
+ } else {
340
+ frameRate = parseInt(num) / parseInt(denom);
341
+ }
342
+ }
333
343
 
334
344
  return {
335
345
  playoutParameters: {
@@ -351,6 +361,8 @@ export class EluvioPlayer {
351
361
  clipEnd: options.clip_end,
352
362
  trimOffset: offset,
353
363
  thumbnailOffset,
364
+ frameRateRat: properties.rate,
365
+ frameRate,
354
366
  sessionId: this.sourceOptions.playoutOptions.sessionId,
355
367
  multiviewOptions: {
356
368
  enabled: this.sourceOptions.playoutOptions.multiview,
@@ -552,7 +564,9 @@ export class EluvioPlayer {
552
564
  offering,
553
565
  compositionKey,
554
566
  clipStart,
555
- clipEnd
567
+ clipEnd,
568
+ frameRate,
569
+ frameRateRat
556
570
  } = await this.__PlayoutOptions();
557
571
 
558
572
  this.playoutInfo = {
@@ -563,7 +577,9 @@ export class EluvioPlayer {
563
577
  trimOffset,
564
578
  thumbnailOffset,
565
579
  clipStart,
566
- clipEnd
580
+ clipEnd,
581
+ frameRate,
582
+ frameRateRat
567
583
  };
568
584
 
569
585
  this.contentHash = versionHash;
@@ -618,6 +634,15 @@ export class EluvioPlayer {
618
634
  .catch(error => this.Log(error, true));
619
635
  }
620
636
 
637
+ if(this.playerOptions.loadPoseOverlay) {
638
+ this.__LoadPoseOverlayTags({...(this.playoutInfo || {})})
639
+ .then(poseOverlayTags => {
640
+ this.__poseOverlayTags = poseOverlayTags;
641
+ this.__showOverlay = true;
642
+ })
643
+ .catch(error => this.Log(error, true));
644
+ }
645
+
621
646
  if(this.playerOptions.playerCallback) {
622
647
  this.playerOptions.playerCallback({
623
648
  player: this,
@@ -1534,6 +1559,49 @@ export class EluvioPlayer {
1534
1559
  }));
1535
1560
  }
1536
1561
 
1562
+ async __LoadPoseOverlayTags({objectId, offering, compositionKey, clipStart, clipEnd}) {
1563
+ const {tracks} = await this.__QueryAIAPI({
1564
+ objectId,
1565
+ path: UrlJoin("/tagstore", objectId, "tracks"),
1566
+ queryParams: {
1567
+ has_frame_info: true
1568
+ },
1569
+ format: "JSON"
1570
+ });
1571
+
1572
+ if(!tracks.find(track => track.name === "pose")) {
1573
+ return;
1574
+ }
1575
+
1576
+ let frameTags = {};
1577
+ ((await this.__QueryAIAPI({
1578
+ objectId,
1579
+ path: offering || compositionKey ?
1580
+ UrlJoin("/tagstore", objectId, "compositions", "tags") :
1581
+ UrlJoin("/tagstore", objectId, "tags"),
1582
+ queryParams: {
1583
+ has_frame_info: true,
1584
+ channel_key: compositionKey,
1585
+ offering_key: offering,
1586
+ limit: 1000000,
1587
+ track: "pose",
1588
+ clip_start: clipStart,
1589
+ clip_end: clipEnd
1590
+ },
1591
+ format: "JSON"
1592
+ })).tags || [])
1593
+ .forEach(tag => {
1594
+ const frame = parseInt(tag.frame_info.frame_idx);
1595
+ if(!frameTags[frame]) {
1596
+ frameTags[frame] = [];
1597
+ }
1598
+
1599
+ frameTags[frame].push(tag);
1600
+ });
1601
+
1602
+ return frameTags;
1603
+ }
1604
+
1537
1605
  async __QueryAIAPI({
1538
1606
  server="ai",
1539
1607
  method="GET",
@@ -108,6 +108,10 @@ export const PlayerParameters = {
108
108
  loadChapters: {
109
109
  OFF: false,
110
110
  ON: true
111
+ },
112
+ loadPoseOverlay: {
113
+ OFF: false,
114
+ ON: true
111
115
  }
112
116
  };
113
117
 
@@ -190,6 +194,7 @@ export const DefaultParameters = {
190
194
  allowCasting: PlayerParameters.allowCasting.ON,
191
195
  preferNativeHLS: PlayerParameters.preferNativeHLS.OFF,
192
196
  loadChapters: PlayerParameters.loadChapters.OFF,
197
+ loadPoseOverlay: PlayerParameters.loadPoseOverlay.OFF,
193
198
  startTime: undefined,
194
199
  startProgress: undefined,
195
200
  hlsjsOptions: undefined,
@@ -188,7 +188,7 @@ class ThumbnailHandler {
188
188
 
189
189
  if(!thumbnailIndex) { return; }
190
190
 
191
- const tag = this.thumbnails && this.thumbnails[thumbnailIndex?.toString()];
191
+ const tag = this.thumbnails && this.thumbnails[thumbnailIndex.toString()];
192
192
 
193
193
  if(!tag) {
194
194
  return;
@@ -35,3 +35,4 @@ export const CopyIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\"
35
35
  export const AirplayIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-airplay\"><path d=\"M5 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-1\"></path><polygon points=\"12 15 17 21 7 21 12 15\"></polygon></svg>";
36
36
  export const ChromecastIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-cast\"><path d=\"M2 16.1A5 5 0 0 1 5.9 20M2 12.05A9 9 0 0 1 9.95 20M2 8V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6\"></path><line x1=\"2\" y1=\"20\" x2=\"2.01\" y2=\"20\"></line></svg>";
37
37
  export const InfoIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-info\"><circle cx=\"12\" cy=\"12\" r=\"10\"></circle><line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"></line><line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"></line></svg>";
38
+ export const OverlayIcon = "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.16602 7.29169H6.45768C6.91792 7.29169 7.29102 6.91859 7.29102 6.45835V5.16669H12.9576V6.45835C12.9576 6.91859 13.3307 7.29169 13.7909 7.29169H15.0826V12.9584H13.7909C13.3307 12.9584 12.9576 13.3314 12.9576 13.7917V15.0834H7.29102V13.7917C7.29102 13.3314 6.91792 12.9584 6.45768 12.9584H5.16602V7.29169Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.75 4.14352C3.75 4.03915 3.79146 3.93906 3.86526 3.86526C3.93906 3.79146 4.03915 3.75 4.14352 3.75H6.89815C7.00252 3.75 7.10261 3.79146 7.17641 3.86526C7.25021 3.93906 7.29167 4.03915 7.29167 4.14352V6.89815C7.29167 7.00252 7.25021 7.10261 7.17641 7.17641C7.10261 7.25021 7.00252 7.29167 6.89815 7.29167H4.14352C4.03915 7.29167 3.93906 7.25021 3.86526 7.17641C3.79146 7.10261 3.75 7.00252 3.75 6.89815V4.14352Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.75 13.3518C3.75 13.2475 3.79146 13.1474 3.86526 13.0736C3.93906 12.9998 4.03915 12.9583 4.14352 12.9583H6.89815C7.00252 12.9583 7.10261 12.9998 7.17641 13.0736C7.25021 13.1474 7.29167 13.2475 7.29167 13.3518V16.1065C7.29167 16.2108 7.25021 16.3109 7.17641 16.3847C7.10261 16.4585 7.00252 16.5 6.89815 16.5H4.14352C4.03915 16.5 3.93906 16.4585 3.86526 16.3847C3.79146 16.3109 3.75 16.2108 3.75 16.1065V13.3518Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12.959 13.3518C12.959 13.2475 13.0004 13.1474 13.0742 13.0736C13.148 12.9998 13.2481 12.9583 13.3525 12.9583H16.1071C16.2115 12.9583 16.3116 12.9998 16.3854 13.0736C16.4592 13.1474 16.5007 13.2475 16.5007 13.3518V16.1065C16.5007 16.2108 16.4592 16.3109 16.3854 16.3847C16.3116 16.4585 16.2115 16.5 16.1071 16.5H13.3525C13.2481 16.5 13.148 16.4585 13.0742 16.3847C13.0004 16.3109 12.959 16.2108 12.959 16.1065V13.3518Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12.959 4.14352C12.959 4.03915 13.0004 3.93906 13.0742 3.86526C13.148 3.79146 13.2481 3.75 13.3525 3.75H16.1071C16.2115 3.75 16.3116 3.79146 16.3854 3.86526C16.4592 3.93906 16.5007 4.03915 16.5007 4.14352V6.89815C16.5007 7.00252 16.4592 7.10261 16.3854 7.17641C16.3116 7.25021 16.2115 7.29167 16.1071 7.29167H13.3525C13.2481 7.29167 13.148 7.25021 13.0742 7.17641C13.0004 7.10261 12.959 7.00252 12.959 6.89815V4.14352Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>";
@@ -0,0 +1,7 @@
1
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M5.16602 7.29169H6.45768C6.91792 7.29169 7.29102 6.91859 7.29102 6.45835V5.16669H12.9576V6.45835C12.9576 6.91859 13.3307 7.29169 13.7909 7.29169H15.0826V12.9584H13.7909C13.3307 12.9584 12.9576 13.3314 12.9576 13.7917V15.0834H7.29102V13.7917C7.29102 13.3314 6.91792 12.9584 6.45768 12.9584H5.16602V7.29169Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <path d="M3.75 4.14352C3.75 4.03915 3.79146 3.93906 3.86526 3.86526C3.93906 3.79146 4.03915 3.75 4.14352 3.75H6.89815C7.00252 3.75 7.10261 3.79146 7.17641 3.86526C7.25021 3.93906 7.29167 4.03915 7.29167 4.14352V6.89815C7.29167 7.00252 7.25021 7.10261 7.17641 7.17641C7.10261 7.25021 7.00252 7.29167 6.89815 7.29167H4.14352C4.03915 7.29167 3.93906 7.25021 3.86526 7.17641C3.79146 7.10261 3.75 7.00252 3.75 6.89815V4.14352Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M3.75 13.3518C3.75 13.2475 3.79146 13.1474 3.86526 13.0736C3.93906 12.9998 4.03915 12.9583 4.14352 12.9583H6.89815C7.00252 12.9583 7.10261 12.9998 7.17641 13.0736C7.25021 13.1474 7.29167 13.2475 7.29167 13.3518V16.1065C7.29167 16.2108 7.25021 16.3109 7.17641 16.3847C7.10261 16.4585 7.00252 16.5 6.89815 16.5H4.14352C4.03915 16.5 3.93906 16.4585 3.86526 16.3847C3.79146 16.3109 3.75 16.2108 3.75 16.1065V13.3518Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M12.959 13.3518C12.959 13.2475 13.0004 13.1474 13.0742 13.0736C13.148 12.9998 13.2481 12.9583 13.3525 12.9583H16.1071C16.2115 12.9583 16.3116 12.9998 16.3854 13.0736C16.4592 13.1474 16.5007 13.2475 16.5007 13.3518V16.1065C16.5007 16.2108 16.4592 16.3109 16.3854 16.3847C16.3116 16.4585 16.2115 16.5 16.1071 16.5H13.3525C13.2481 16.5 13.148 16.4585 13.0742 16.3847C13.0004 16.3109 12.959 16.2108 12.959 16.1065V13.3518Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
6
+ <path d="M12.959 4.14352C12.959 4.03915 13.0004 3.93906 13.0742 3.86526C13.148 3.79146 13.2481 3.75 13.3525 3.75H16.1071C16.2115 3.75 16.3116 3.79146 16.3854 3.86526C16.4592 3.93906 16.5007 4.03915 16.5007 4.14352V6.89815C16.5007 7.00252 16.4592 7.10261 16.3854 7.17641C16.3116 7.25021 16.2115 7.29167 16.1071 7.29167H13.3525C13.2481 7.29167 13.148 7.25021 13.0742 7.17641C13.0004 7.10261 12.959 7.00252 12.959 6.89815V4.14352Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
7
+ </svg>
@@ -84,6 +84,10 @@
84
84
  }
85
85
  }
86
86
 
87
+ &--no-padding {
88
+ padding: 0;
89
+ }
90
+
87
91
  &:disabled {
88
92
  opacity: 0.5;
89
93
  }
@@ -12,6 +12,7 @@
12
12
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
13
13
  height: 100%;
14
14
  inset: 0;
15
+ overflow: hidden;
15
16
  position: absolute;
16
17
  width: 100%;
17
18
 
@@ -130,6 +131,12 @@
130
131
  }
131
132
  }
132
133
 
134
+ .overlay {
135
+ pointer-events: none;
136
+ position: absolute;
137
+ z-index: 1000;
138
+ }
139
+
133
140
  :global(.__eluvio-player--size-md),
134
141
  :global(.__eluvio-player--size-sm) {
135
142
  .error-message {
@@ -37,7 +37,8 @@ const iconSource = {
37
37
  CopyIcon: Path.resolve(__dirname, "../static/icons/svgs/copy.svg"),
38
38
  AirplayIcon: Path.resolve(__dirname, "../static/icons/svgs/airplay.svg"),
39
39
  ChromecastIcon: Path.resolve(__dirname, "../static/icons/svgs/cast.svg"),
40
- InfoIcon: Path.resolve(__dirname, "../static/icons/svgs/info.svg")
40
+ InfoIcon: Path.resolve(__dirname, "../static/icons/svgs/info.svg"),
41
+ OverlayIcon: Path.resolve(__dirname, "../static/icons/svgs/overlay.svg")
41
42
  };
42
43
 
43
44
  let iconFile = "// WARNING: Do not edit this file manually\n";
@@ -0,0 +1,159 @@
1
+ import PlayerStyles from "../static/stylesheets/player.module.scss";
2
+ import {useEffect, useState} from "react";
3
+
4
+ const POINT_CONNECTIONS = [["Nose","LEyeIn"],["LEyeIn","LEye"],["LEye","REyeOut"],["REyeOut","LEar"],["Nose","REyeIn"],["REyeIn","REye"],["REye","REyeOut"],["REyeOut","REar"],["MouthL","MouthR"],["LShoulder","RShoulder"],["LShoulder","LElbow"],["LElbow","LWrist"],["LWrist","LPinky"],["LWrist","LIndex"],["LWrist","LThumb"],["LPinky","LIndex"],["RShoulder","RElbow"],["RElbow","RWrist"],["RWrist","RPinky"],["RWrist","RIndex"],["RWrist","RThumb"],["RPinky","RIndex"],["LShoulder","LHip"],["RShoulder","RHip"],["LHip","RHip"],["LHip","LKnee"],["RHip","RKnee"],["LKnee","LAnkle"],["RKnee","RAnkle"],["LAnkle","LHeel"],["RAnkle","RHeel"],["LHeel","LFootIdx"],["RHeel","RFootIdx"],["LAnkle","LFootIdx"],["RAnkle","RFootIdx"]];
5
+
6
+ let frameSpread = 5;
7
+ const Canvas = ({tags, portalDimensions, videoDimensions}) => {
8
+ const [canvas, setCanvas] = useState(null);
9
+
10
+ useEffect(() => {
11
+ if(!canvas || !portalDimensions || videoDimensions.videoWidth === 0) { return; }
12
+
13
+ canvas.width = canvas.getBoundingClientRect().width;
14
+ canvas.height = canvas.getBoundingClientRect().height;
15
+
16
+ const color = {
17
+ r: 255,
18
+ g: 255,
19
+ b: 255
20
+ };
21
+
22
+ // Draw
23
+ const context = canvas.getContext("2d");
24
+ const width = context.canvas.width;
25
+ const height = context.canvas.height;
26
+ const toHex = n => n.toString(16).padStart(2, "0");
27
+
28
+ context.clearRect(0, 0, context.canvas.width, context.canvas.height);
29
+ context.lineWidth = 3;
30
+
31
+ if(!tags || tags.length === 0) { return; }
32
+
33
+ tags.forEach(tag => {
34
+ if(!tag || !tag.additional_info || !tag.additional_info.pose) {
35
+ return;
36
+ }
37
+
38
+ context.lineWidth = 3;
39
+ context.strokeStyle = `#${toHex(color.r)}${toHex(color.g)}${toHex(color.b)}`;
40
+ context.fillStyle = `#${toHex(color.r)}${toHex(color.g)}${toHex(color.b)}`;
41
+
42
+ context.globalAlpha = 0.7;
43
+
44
+ Object.values(tag.additional_info.pose).forEach(([x, y]) => {
45
+ context.beginPath();
46
+ context.arc(x * width, y * height, 1.5, 0, 2 * Math.PI);
47
+ context.fill();
48
+ context.stroke();
49
+ });
50
+
51
+ POINT_CONNECTIONS
52
+ .forEach(([start, end]) => {
53
+ if(!tag.additional_info.pose[start] || !tag.additional_info.pose[end]) {
54
+ return;
55
+ }
56
+ const [startX, startY] = tag.additional_info.pose[start];
57
+ const [endX, endY] = tag.additional_info.pose[end];
58
+
59
+ context.beginPath();
60
+ context.moveTo(startX * width, startY * height);
61
+ context.lineTo(endX * width, endY * height);
62
+ context.stroke();
63
+ });
64
+ });
65
+ }, [tags]);
66
+
67
+
68
+ if(!portalDimensions || videoDimensions.videoWidth === 0) { return null; }
69
+
70
+ const portalAspectRatio = portalDimensions.width / portalDimensions.height;
71
+ const videoAspectRatio = videoDimensions.videoWidth / videoDimensions.videoHeight;
72
+
73
+ let params = {};
74
+ if(portalAspectRatio < videoAspectRatio) {
75
+ // Vertical padding
76
+ params.width = portalDimensions.width;
77
+ params.height = portalDimensions.width / videoAspectRatio;
78
+ params.left = 0;
79
+ params.top = (portalDimensions.height - (portalDimensions.width / videoAspectRatio)) / 2;
80
+ } else {
81
+ // Horizontal padding
82
+ params.height = portalDimensions.height;
83
+ params.width = portalDimensions.height * videoAspectRatio;
84
+ params.top = 0;
85
+ params.left = (portalDimensions.width - (portalDimensions.height * videoAspectRatio)) / 2;
86
+ }
87
+
88
+ return (
89
+ <canvas
90
+ ref={setCanvas}
91
+ style={params}
92
+ className={PlayerStyles["overlay"]}
93
+ />
94
+ );
95
+ };
96
+
97
+ const Overlay = ({player}) => {
98
+ const [portalDimensions, setPortalDimensions] = useState(null);
99
+ const [frame, setFrame] = useState(null);
100
+
101
+ useEffect(() => {
102
+ const resizeObserver = new ResizeObserver(() =>
103
+ setPortalDimensions(player.video.getBoundingClientRect())
104
+ );
105
+
106
+ resizeObserver.observe(player.video);
107
+
108
+ return () => {
109
+ resizeObserver.disconnect();
110
+ };
111
+ }, [player.video]);
112
+
113
+ useEffect(() => {
114
+ const frameRate = (player.playoutInfo || {}).frameRate;
115
+
116
+ if(!frameRate) { return; }
117
+
118
+ const StartInterval = () => {
119
+ clearInterval(player.__frameInterval);
120
+
121
+ player.__frameInterval = setInterval(
122
+ () => setFrame(Math.floor(player.video.currentTime * frameRate)),
123
+ 1000 / player.playoutInfo.frameRate
124
+ );
125
+ };
126
+
127
+ player.controls.RegisterVideoEventListener("play", StartInterval);
128
+ player.controls.RegisterVideoEventListener(
129
+ "pause",
130
+ () => clearInterval(player.__frameInterval)
131
+ );
132
+
133
+ if(!player.video.paused) {
134
+ StartInterval();
135
+ }
136
+ }, [(player.playoutInfo || {}).frameRate]);
137
+
138
+ let tags;
139
+ for(let i = frame; i > frame - frameSpread; i--) {
140
+ tags = player.__poseOverlayTags && player.__poseOverlayTags[i];
141
+
142
+ if(tags && tags.length > 0) {
143
+ break;
144
+ }
145
+ }
146
+
147
+ return (
148
+ <Canvas
149
+ tags={tags}
150
+ portalDimensions={portalDimensions}
151
+ videoDimensions={{
152
+ videoWidth: player.video.videoWidth,
153
+ videoHeight: player.video.videoHeight
154
+ }}
155
+ />
156
+ );
157
+ };
158
+
159
+ export default Overlay;
@@ -20,6 +20,7 @@ import TVControls from "./TVControls.jsx";
20
20
  import PlayerProfileForm from "./PlayerProfileForm.jsx";
21
21
  import {ImageUrl, MergeDefaultParameters, MergeParameters} from "./Common.js";
22
22
  import * as Icons from "../static/icons/Icons";
23
+ import Overlay from "./Overlay";
23
24
 
24
25
  const Poster = ({player}) => {
25
26
  const [imageUrl, setImageUrl] = useState(undefined);
@@ -75,6 +76,7 @@ const PlayerUI = ({
75
76
  const [recentUserAction, setRecentUserAction] = useState(undefined);
76
77
  const [allowRotation, setAllowRotation] = useState(undefined);
77
78
  const [casting, setCasting] = useState(false);
79
+ const [showOverlay, setShowOverlay] = useState(false);
78
80
  const videoRef = useRef();
79
81
 
80
82
  const playerSet = !!player;
@@ -126,6 +128,7 @@ const PlayerUI = ({
126
128
  setPlayerInitialized(!newPlayer.loading);
127
129
  setShowPlayerProfileForm(newPlayer.__showPlayerProfileForm);
128
130
  setCasting(newPlayer && newPlayer.casting);
131
+ setShowOverlay(newPlayer.controls.OverlayVisible());
129
132
  }
130
133
  );
131
134
 
@@ -254,6 +257,10 @@ const PlayerUI = ({
254
257
  (playbackStarted && !parameters.playerOptions.permanentPoster) ? null :
255
258
  <Poster player={player} />
256
259
  }
260
+ {
261
+ !showOverlay ? null :
262
+ <Overlay player={player} />
263
+ }
257
264
  {
258
265
  playerInitialized || errorMessage || !parameters.playerOptions.showLoader ? null :
259
266
  <div className={PlayerStyles["spinner-container"]}>
@@ -290,6 +297,8 @@ const PlayerUI = ({
290
297
  canPlay={canPlay}
291
298
  recentlyInteracted={recentlyInteracted}
292
299
  setRecentUserAction={onUserAction}
300
+ showOverlay={showOverlay}
301
+ setShowOverlay={setShowOverlay}
293
302
  className={PlayerStyles.controls}
294
303
  /> :
295
304
  <TVControls
@@ -198,7 +198,14 @@ const ContentVerificationControls = ({player}) => {
198
198
  );
199
199
  };
200
200
 
201
- const WebControls = ({player, playbackStarted, canPlay, recentlyInteracted, setRecentUserAction, className=""}) => {
201
+ const WebControls = ({
202
+ player,
203
+ playbackStarted,
204
+ canPlay,
205
+ recentlyInteracted,
206
+ setRecentUserAction,
207
+ className=""
208
+ }) => {
202
209
  const [videoState, setVideoState] = useState(undefined);
203
210
  const [playerClickHandler, setPlayerClickHandler] = useState(undefined);
204
211
  const [menuVisible, setMenuVisible] = useState(player.controls.IsMenuVisible());
@@ -292,6 +299,19 @@ const WebControls = ({player, playbackStarted, canPlay, recentlyInteracted, setR
292
299
  />
293
300
  }
294
301
 
302
+ {
303
+ !player.controls.OverlayAvailable() ? null :
304
+ <IconButton
305
+ aria-label="Toggle Overlay"
306
+ onClick={() => player.controls.ToggleOverlayVisibility()}
307
+ icon={Icons.OverlayIcon}
308
+ className={[
309
+ ControlStyles["icon-button--no-padding"],
310
+ player.controls.OverlayVisible() ? ControlStyles["icon-button-active"] : ""
311
+ ].join(" ")}
312
+ />
313
+ }
314
+
295
315
  {
296
316
  !player.controls.IsRotatable() ? null :
297
317
  <IconButton
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-player-js",
3
- "version": "2.1.33",
3
+ "version": "2.1.35",
4
4
  "description": "![Eluvio Logo](lib/static/images/Logo.png \"Eluvio Logo\")",
5
5
  "main": "dist/elv-player-js.es.js",
6
6
  "license": "MIT",