@mux/mux-player 0.1.0-beta.21 → 0.1.0-beta.24
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/CHANGELOG.md +24 -0
- package/README.md +36 -36
- package/coverage/lcov-report/index.html +29 -29
- package/coverage/lcov-report/src/dialog.ts.html +1 -1
- package/coverage/lcov-report/src/errors.ts.html +1 -1
- package/coverage/lcov-report/src/helpers.ts.html +20 -71
- package/coverage/lcov-report/src/html.ts.html +159 -9
- package/coverage/lcov-report/src/index.html +52 -52
- package/coverage/lcov-report/src/index.ts.html +79 -79
- package/coverage/lcov-report/src/logger.ts.html +1 -1
- package/coverage/lcov-report/src/media-chrome/dialog.ts.html +1 -1
- package/coverage/lcov-report/src/media-chrome/index.html +1 -1
- package/coverage/lcov-report/src/media-chrome/time-display.ts.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/airplay.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/captions-off.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/captions-on.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/cast-enter.svg.html +103 -0
- package/coverage/lcov-report/src/media-theme-mux/icons/cast-exit.svg.html +106 -0
- package/coverage/lcov-report/src/media-theme-mux/icons/fullscreen-enter.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/fullscreen-exit.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/index.html +33 -3
- package/coverage/lcov-report/src/media-theme-mux/icons/pause.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/pip-enter.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/pip-exit.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/play.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/seek-backward.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/seek-forward.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/volume-high.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/volume-low.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/volume-medium.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons/volume-off.svg.html +1 -1
- package/coverage/lcov-report/src/media-theme-mux/icons.ts.html +18 -6
- package/coverage/lcov-report/src/media-theme-mux/index.html +24 -24
- package/coverage/lcov-report/src/media-theme-mux/media-theme-mux.ts.html +129 -150
- package/coverage/lcov-report/src/media-theme-mux/styles.css.html +121 -19
- package/coverage/lcov-report/src/styles.css.html +1 -1
- package/coverage/lcov-report/src/template.ts.html +106 -64
- package/coverage/lcov-report/src/utils.ts.html +1 -1
- package/coverage/lcov-report/src/video-api.ts.html +91 -13
- package/coverage/lcov.info +1515 -1372
- package/dist/index.cjs.js +439 -301
- package/dist/index.mjs +245 -199
- package/dist/mux-player.js +494 -356
- package/dist/mux-player.mjs +494 -356
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/helpers.d.ts +1 -3
- package/dist/types/html.d.ts +5 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/media-theme-mux/icons.d.ts +2 -0
- package/dist/types/media-theme-mux/media-theme-mux.d.ts +12 -13
- package/dist/types/video-api.d.ts +4 -0
- package/dist/types-ts3.4/helpers.d.ts +1 -3
- package/dist/types-ts3.4/html.d.ts +5 -0
- package/dist/types-ts3.4/index.d.ts +3 -3
- package/dist/types-ts3.4/media-theme-mux/icons.d.ts +2 -0
- package/dist/types-ts3.4/media-theme-mux/media-theme-mux.d.ts +12 -13
- package/dist/types-ts3.4/video-api.d.ts +2 -0
- package/package.json +5 -5
- package/src/helpers.ts +7 -24
- package/src/html.ts +50 -0
- package/src/index.ts +42 -42
- package/src/media-theme-mux/icons/cast-enter.svg +6 -0
- package/src/media-theme-mux/icons/cast-exit.svg +7 -0
- package/src/media-theme-mux/icons.ts +4 -0
- package/src/media-theme-mux/media-theme-mux.ts +76 -83
- package/src/media-theme-mux/styles.css +49 -15
- package/src/template.ts +70 -56
- package/src/types.d.ts +1 -3
- package/src/video-api.ts +27 -1
- package/test/player.test.js +34 -0
- package/test/template.test.js +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import 'media-chrome';
|
|
1
|
+
import { MediaTheme } from 'media-chrome';
|
|
2
2
|
import { html, render } from '../html';
|
|
3
3
|
import '../media-chrome/time-display';
|
|
4
4
|
|
|
@@ -14,27 +14,60 @@ const MediaChromeSizes = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
type ThemeMuxTemplateProps = {
|
|
17
|
-
streamType: string;
|
|
17
|
+
streamType: string | null;
|
|
18
18
|
audio: boolean;
|
|
19
|
-
playerSize: string;
|
|
19
|
+
playerSize: string | null;
|
|
20
20
|
defaultHiddenCaptions: boolean;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
backwardSeekOffset: number;
|
|
21
|
+
forwardSeekOffset: string | null;
|
|
22
|
+
backwardSeekOffset: string | null;
|
|
24
23
|
};
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
export default class MediaThemeMux extends MediaTheme {
|
|
26
|
+
static get observedAttributes() {
|
|
27
|
+
return [
|
|
28
|
+
'audio',
|
|
29
|
+
'stream-type',
|
|
30
|
+
'player-size',
|
|
31
|
+
'default-hidden-captions',
|
|
32
|
+
'forward-seek-offset',
|
|
33
|
+
'backward-seek-offset',
|
|
34
|
+
];
|
|
35
|
+
}
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
attributeChangedCallback() {
|
|
38
|
+
this.render();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
render() {
|
|
42
|
+
const props = {
|
|
43
|
+
audio: this.hasAttribute('audio'),
|
|
44
|
+
streamType: this.getAttribute('stream-type'),
|
|
45
|
+
playerSize: this.getAttribute('player-size'),
|
|
46
|
+
defaultHiddenCaptions: this.hasAttribute('default-hidden-captions'),
|
|
47
|
+
forwardSeekOffset: this.getAttribute('forward-seek-offset'),
|
|
48
|
+
backwardSeekOffset: this.getAttribute('backward-seek-offset'),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
render(
|
|
52
|
+
html`
|
|
53
|
+
<style>
|
|
54
|
+
${cssStr}
|
|
55
|
+
</style>
|
|
56
|
+
<media-controller audio="${props.audio || false}" class="size-${props.playerSize}">
|
|
57
|
+
<slot name="media" slot="media"></slot>
|
|
58
|
+
<media-loading-indicator slot="centered-chrome" no-auto-hide></media-loading-indicator>
|
|
59
|
+
${ChromeRenderer(props)}
|
|
60
|
+
<slot></slot>
|
|
61
|
+
</media-controller>
|
|
62
|
+
`,
|
|
63
|
+
this.shadowRoot as Node
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!customElements.get('media-theme-mux')) {
|
|
69
|
+
customElements.define('media-theme-mux', MediaThemeMux);
|
|
70
|
+
}
|
|
38
71
|
|
|
39
72
|
const ChromeRenderer = (props: ThemeMuxTemplateProps) => {
|
|
40
73
|
const { streamType, playerSize, audio } = props;
|
|
@@ -42,7 +75,7 @@ const ChromeRenderer = (props: ThemeMuxTemplateProps) => {
|
|
|
42
75
|
switch (streamType) {
|
|
43
76
|
case StreamTypes.LIVE:
|
|
44
77
|
case StreamTypes.LL_LIVE: {
|
|
45
|
-
return AudioLiveChrome(
|
|
78
|
+
return AudioLiveChrome();
|
|
46
79
|
}
|
|
47
80
|
case StreamTypes.DVR:
|
|
48
81
|
case StreamTypes.LL_DVR: {
|
|
@@ -152,6 +185,13 @@ const MediaFullscreenButton = () => html`
|
|
|
152
185
|
${icons.FullscreenExit()}
|
|
153
186
|
</media-fullscreen-button>`;
|
|
154
187
|
|
|
188
|
+
// prettier-ignore
|
|
189
|
+
const MediaCastButton = () => html`
|
|
190
|
+
<media-cast-button>
|
|
191
|
+
${icons.CastEnter()}
|
|
192
|
+
${icons.CastExit()}
|
|
193
|
+
</media-cast-button>`;
|
|
194
|
+
|
|
155
195
|
export const AudioVodChrome = (props: ThemeMuxTemplateProps) => html`
|
|
156
196
|
<media-control-bar>
|
|
157
197
|
${MediaPlayButton()} ${MediaSeekBackwardButton(props)} ${MediaSeekForwardButton(props)}
|
|
@@ -160,8 +200,7 @@ export const AudioVodChrome = (props: ThemeMuxTemplateProps) => html`
|
|
|
160
200
|
${MediaMuteButton()}
|
|
161
201
|
<media-volume-range></media-volume-range>
|
|
162
202
|
<media-playback-rate-button></media-playback-rate-button>
|
|
163
|
-
${MediaAirplayButton()}
|
|
164
|
-
<media-cast-button></media-cast-button>
|
|
203
|
+
${MediaAirplayButton()} ${MediaCastButton()}
|
|
165
204
|
</media-control-bar>
|
|
166
205
|
`;
|
|
167
206
|
|
|
@@ -175,29 +214,27 @@ export const AudioDvrChrome = (props: ThemeMuxTemplateProps) => html`
|
|
|
175
214
|
${MediaMuteButton()}
|
|
176
215
|
<media-volume-range></media-volume-range>
|
|
177
216
|
<media-playback-rate-button></media-playback-rate-button>
|
|
178
|
-
${MediaAirplayButton()}
|
|
179
|
-
<media-cast-button></media-cast-button>
|
|
217
|
+
${MediaAirplayButton()} ${MediaCastButton()}
|
|
180
218
|
</media-control-bar>
|
|
181
219
|
`;
|
|
182
220
|
|
|
183
|
-
export const AudioLiveChrome = (
|
|
221
|
+
export const AudioLiveChrome = () => html`
|
|
184
222
|
<media-control-bar>
|
|
185
223
|
${MediaPlayButton()}
|
|
186
224
|
<slot name="seek-to-live-button"></slot>
|
|
187
225
|
${MediaMuteButton()}
|
|
188
226
|
<media-volume-range></media-volume-range>
|
|
189
|
-
${MediaAirplayButton()}
|
|
190
|
-
<media-cast-button></media-cast-button>
|
|
227
|
+
${MediaAirplayButton()} ${MediaCastButton()}
|
|
191
228
|
</media-control-bar>
|
|
192
229
|
`;
|
|
193
230
|
|
|
194
231
|
// prettier-ignore
|
|
195
232
|
export const VodChromeExtraSmall = (props: ThemeMuxTemplateProps) => html`
|
|
196
233
|
<media-control-bar slot="top-chrome">
|
|
197
|
-
${
|
|
234
|
+
${MediaCaptionsButton(props)}
|
|
198
235
|
<div class="mxp-spacer"></div>
|
|
199
236
|
${MediaAirplayButton()}
|
|
200
|
-
|
|
237
|
+
${MediaCastButton()}
|
|
201
238
|
${MediaPipButton()}
|
|
202
239
|
</media-control-bar>
|
|
203
240
|
<div slot="centered-chrome" class="mxp-center-controls">
|
|
@@ -213,9 +250,9 @@ export const VodChromeExtraSmall = (props: ThemeMuxTemplateProps) => html`
|
|
|
213
250
|
// prettier-ignore
|
|
214
251
|
export const VodChromeSmall = (props: ThemeMuxTemplateProps) => html`
|
|
215
252
|
<media-control-bar slot="top-chrome" style="justify-content: flex-end;">
|
|
216
|
-
${
|
|
253
|
+
${MediaCaptionsButton(props)}
|
|
217
254
|
${MediaAirplayButton()}
|
|
218
|
-
|
|
255
|
+
${MediaCastButton()}
|
|
219
256
|
${MediaPipButton()}
|
|
220
257
|
</media-control-bar>
|
|
221
258
|
<div slot="centered-chrome" class="mxp-center-controls">
|
|
@@ -250,9 +287,9 @@ export const VodChromeLarge = (props: ThemeMuxTemplateProps) => html`
|
|
|
250
287
|
<media-volume-range></media-volume-range>
|
|
251
288
|
<div class="mxp-spacer"></div>
|
|
252
289
|
<media-playback-rate-button></media-playback-rate-button>
|
|
253
|
-
${
|
|
290
|
+
${MediaCaptionsButton(props)}
|
|
254
291
|
${MediaAirplayButton()}
|
|
255
|
-
|
|
292
|
+
${MediaCastButton()}
|
|
256
293
|
${MediaPipButton()}
|
|
257
294
|
${MediaFullscreenButton()}
|
|
258
295
|
<div class="mxp-padding-2"></div>
|
|
@@ -267,9 +304,9 @@ export const LiveChromeSmall = (props: ThemeMuxTemplateProps) => html`
|
|
|
267
304
|
<media-control-bar slot="top-chrome">
|
|
268
305
|
<slot name="seek-to-live-button"></slot>
|
|
269
306
|
<div class="mxp-spacer"></div>
|
|
270
|
-
${
|
|
307
|
+
${MediaCaptionsButton(props)}
|
|
271
308
|
${MediaAirplayButton()}
|
|
272
|
-
|
|
309
|
+
${MediaCastButton()}
|
|
273
310
|
${MediaPipButton()}
|
|
274
311
|
</media-control-bar>
|
|
275
312
|
<div slot="centered-chrome" class="mxp-center-controls">
|
|
@@ -295,9 +332,9 @@ export const LiveChromeLarge = (props: ThemeMuxTemplateProps) => html`
|
|
|
295
332
|
${MediaMuteButton()}
|
|
296
333
|
<media-volume-range></media-volume-range>
|
|
297
334
|
<div class="mxp-spacer"></div>
|
|
298
|
-
${
|
|
335
|
+
${MediaCaptionsButton(props)}
|
|
299
336
|
${MediaAirplayButton()}
|
|
300
|
-
|
|
337
|
+
${MediaCastButton()}
|
|
301
338
|
${MediaPipButton()}
|
|
302
339
|
${MediaFullscreenButton()}
|
|
303
340
|
</media-control-bar>
|
|
@@ -309,9 +346,9 @@ export const DvrChromeExtraSmall = VodChromeExtraSmall;
|
|
|
309
346
|
// prettier-ignore
|
|
310
347
|
export const DvrChromeSmall = (props: ThemeMuxTemplateProps) => html`
|
|
311
348
|
<media-control-bar slot="top-chrome" style="justify-content: flex-end;">
|
|
312
|
-
${
|
|
349
|
+
${MediaCaptionsButton(props)}
|
|
313
350
|
${MediaAirplayButton()}
|
|
314
|
-
|
|
351
|
+
${MediaCastButton()}
|
|
315
352
|
${MediaPipButton()}
|
|
316
353
|
</media-control-bar>
|
|
317
354
|
<div slot="centered-chrome" class="mxp-center-controls">
|
|
@@ -344,55 +381,11 @@ export const DvrChromeLarge = (props: ThemeMuxTemplateProps) => html`
|
|
|
344
381
|
<media-volume-range></media-volume-range>
|
|
345
382
|
<slot name="seek-to-live-button"></slot>
|
|
346
383
|
<div class="mxp-spacer"></div>
|
|
347
|
-
${
|
|
384
|
+
${MediaCaptionsButton(props)}
|
|
348
385
|
${MediaAirplayButton()}
|
|
349
|
-
|
|
386
|
+
${MediaCastButton()}
|
|
350
387
|
${MediaPipButton()}
|
|
351
388
|
${MediaFullscreenButton()}
|
|
352
389
|
<div class="mxp-padding-2"></div>
|
|
353
390
|
</media-control-bar>
|
|
354
391
|
`;
|
|
355
|
-
|
|
356
|
-
function getProps(el: MediaThemeMux, state?: any): ThemeMuxTemplateProps {
|
|
357
|
-
return {
|
|
358
|
-
audio: el.hasAttribute('audio'),
|
|
359
|
-
streamType: el.getAttribute('stream-type'),
|
|
360
|
-
playerSize: el.getAttribute('player-size'),
|
|
361
|
-
defaultHiddenCaptions: el.hasAttribute('default-hidden-captions'),
|
|
362
|
-
hasCaptions: el.hasAttribute('has-captions'),
|
|
363
|
-
forwardSeekOffset: el.getAttribute('forward-seek-offset'),
|
|
364
|
-
backwardSeekOffset: el.getAttribute('backward-seek-offset'),
|
|
365
|
-
...state,
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
class MediaThemeMux extends HTMLElement {
|
|
370
|
-
static get observedAttributes() {
|
|
371
|
-
return [
|
|
372
|
-
'audio',
|
|
373
|
-
'stream-type',
|
|
374
|
-
'player-size',
|
|
375
|
-
'default-hidden-captions',
|
|
376
|
-
'has-captions',
|
|
377
|
-
'forward-seek-offset',
|
|
378
|
-
'backward-seek-offset',
|
|
379
|
-
];
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
constructor() {
|
|
383
|
-
super();
|
|
384
|
-
|
|
385
|
-
this.attachShadow({ mode: 'open' });
|
|
386
|
-
render(template(getProps(this)), this.shadowRoot as Node);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
attributeChangedCallback() {
|
|
390
|
-
render(template(getProps(this)), this.shadowRoot as Node);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (!customElements.get('media-theme-mux')) {
|
|
395
|
-
customElements.define('media-theme-mux', MediaThemeMux);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
export default MediaThemeMux;
|
|
@@ -3,20 +3,44 @@
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
:host {
|
|
6
|
-
color: var(--primary-color);
|
|
7
|
-
|
|
8
|
-
--media-
|
|
9
|
-
--media-range-
|
|
6
|
+
--_primary-color: var(--primary-color, #fff);
|
|
7
|
+
|
|
8
|
+
--media-icon-color: var(--_primary-color);
|
|
9
|
+
--media-range-thumb-background: var(--_primary-color);
|
|
10
|
+
--media-range-bar-color: var(--_primary-color);
|
|
10
11
|
--media-control-background: var(--secondary-color);
|
|
11
12
|
--media-control-hover-background: var(--secondary-color);
|
|
12
|
-
--media-time-buffered-color: rgba(255, 255, 255, 0.
|
|
13
|
+
--media-time-buffered-color: rgba(255, 255, 255, 0.4);
|
|
13
14
|
--media-range-track-background: rgba(255, 255, 255, 0.5);
|
|
14
15
|
--media-range-track-border-radius: 3px;
|
|
16
|
+
--media-preview-thumbnail-border: 1px solid #fff;
|
|
17
|
+
--media-preview-thumbnail-border-radius: 2px;
|
|
18
|
+
--media-preview-time-margin: 5px 0 2px;
|
|
19
|
+
color: var(--_primary-color);
|
|
15
20
|
display: inline-block;
|
|
16
21
|
width: 100%;
|
|
17
22
|
height: 100%;
|
|
18
23
|
}
|
|
19
24
|
|
|
25
|
+
:host(.two-tone:not([audio])) {
|
|
26
|
+
--mux-time-range-padding: 0px; /* px is needed in calc() */
|
|
27
|
+
--media-preview-thumbnail-border: 0;
|
|
28
|
+
--media-preview-thumbnail-border-radius: 2px 2px 0 0;
|
|
29
|
+
--media-preview-time-border-radius: 0 0 2px 2px;
|
|
30
|
+
--media-preview-time-margin: 0 0 8px;
|
|
31
|
+
--media-preview-time-text-shadow: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
:host([audio]) {
|
|
35
|
+
--media-preview-time-border-radius: 3px;
|
|
36
|
+
--media-preview-time-margin: 0 0 5px;
|
|
37
|
+
--media-preview-time-text-shadow: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
:host(.two-tone:not([audio])) media-time-range {
|
|
41
|
+
--media-range-track-border-radius: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
20
44
|
:host([audio]) ::slotted([slot='media']) {
|
|
21
45
|
height: 0px;
|
|
22
46
|
}
|
|
@@ -36,7 +60,8 @@
|
|
|
36
60
|
media-airplay-button[media-airplay-unavailable],
|
|
37
61
|
media-cast-button[media-cast-unavailable],
|
|
38
62
|
media-volume-range[media-volume-unavailable],
|
|
39
|
-
media-airplay-button[media-airplay-unavailable]
|
|
63
|
+
media-airplay-button[media-airplay-unavailable],
|
|
64
|
+
media-captions-button:not(:is([media-captions-list], [media-subtitles-list])) {
|
|
40
65
|
display: none;
|
|
41
66
|
}
|
|
42
67
|
|
|
@@ -53,13 +78,26 @@ media-controller {
|
|
|
53
78
|
height: 100%;
|
|
54
79
|
}
|
|
55
80
|
|
|
81
|
+
:host media-time-range {
|
|
82
|
+
color: var(--_primary-color);
|
|
83
|
+
}
|
|
84
|
+
|
|
56
85
|
:host(:not([audio])) media-time-range {
|
|
57
|
-
padding: var(--mux-time-range-padding,
|
|
58
|
-
|
|
86
|
+
--media-range-padding-left: var(--mux-time-range-padding, 10px);
|
|
87
|
+
--media-range-padding-right: var(--mux-time-range-padding, 10px);
|
|
59
88
|
width: 100%;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
89
|
+
z-index: 10;
|
|
90
|
+
height: 10px;
|
|
91
|
+
bottom: -2px;
|
|
92
|
+
background: linear-gradient(
|
|
93
|
+
180deg,
|
|
94
|
+
transparent,
|
|
95
|
+
transparent 3px,
|
|
96
|
+
var(--media-control-background) 3px,
|
|
97
|
+
var(--media-control-background) 8px,
|
|
98
|
+
transparent 8px,
|
|
99
|
+
transparent
|
|
100
|
+
);
|
|
63
101
|
}
|
|
64
102
|
|
|
65
103
|
media-control-bar {
|
|
@@ -70,10 +108,6 @@ media-control-bar :is([role='button'], [role='switch'], button) {
|
|
|
70
108
|
height: 44px;
|
|
71
109
|
}
|
|
72
110
|
|
|
73
|
-
media-cast-button {
|
|
74
|
-
width: 40px;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
111
|
.size-extra-small media-control-bar [role='button'],
|
|
78
112
|
.size-extra-small media-control-bar [role='switch'] {
|
|
79
113
|
height: auto;
|
package/src/template.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import './media-theme-mux/media-theme-mux';
|
|
2
2
|
import './dialog';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
castThemeName,
|
|
5
|
+
getSrcFromPlaybackId,
|
|
6
|
+
getPosterURLFromPlaybackId,
|
|
7
|
+
getStoryboardURLFromPlaybackId,
|
|
8
|
+
} from './helpers';
|
|
9
|
+
import { html, unsafeStatic } from './html';
|
|
5
10
|
// @ts-ignore
|
|
6
11
|
import cssStr from './styles.css';
|
|
7
12
|
import { i18n, stylePropsToString } from './utils';
|
|
@@ -17,18 +22,17 @@ export const template = (props: MuxTemplateProps) => html`
|
|
|
17
22
|
`;
|
|
18
23
|
|
|
19
24
|
export const content = (props: MuxTemplateProps) => html`
|
|
20
|
-
|
|
25
|
+
<${unsafeStatic(castThemeName(props.theme) ?? 'media-theme-mux')}
|
|
21
26
|
audio="${props.audio || false}"
|
|
22
|
-
style="${
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
class="size-${props.playerSize}"
|
|
27
|
+
style="${
|
|
28
|
+
stylePropsToString({
|
|
29
|
+
'--primary-color': props.primaryColor,
|
|
30
|
+
'--secondary-color': props.secondaryColor,
|
|
31
|
+
}) ?? false
|
|
32
|
+
}"
|
|
33
|
+
class="size-${props.playerSize}${props.secondaryColor ? ' two-tone' : ''}"
|
|
29
34
|
stream-type="${props.streamType}"
|
|
30
35
|
player-size="${props.playerSize}"
|
|
31
|
-
has-captions="${props.hasCaptions}"
|
|
32
36
|
default-hidden-captions="${props.defaultHiddenCaptions}"
|
|
33
37
|
forward-seek-offset="${props.forwardSeekOffset}"
|
|
34
38
|
backward-seek-offset="${props.backwardSeekOffset}"
|
|
@@ -44,49 +48,57 @@ export const content = (props: MuxTemplateProps) => html`
|
|
|
44
48
|
debug="${props.debug ?? false}"
|
|
45
49
|
prefer-mse="${props.preferMse ?? false}"
|
|
46
50
|
start-time="${props.startTime != null ? props.startTime : false}"
|
|
47
|
-
metadata-video-id="${props.metadataVideoId ??
|
|
48
|
-
metadata-video-title="${props.metadataVideoTitle ??
|
|
49
|
-
metadata-viewer-user-id="${props.metadataViewerUserId ??
|
|
51
|
+
metadata-video-id="${props.metadataVideoId ?? false}"
|
|
52
|
+
metadata-video-title="${props.metadataVideoTitle ?? false}"
|
|
53
|
+
metadata-viewer-user-id="${props.metadataViewerUserId ?? false}"
|
|
50
54
|
beacon-collection-domain="${props.beaconCollectionDomain ?? false}"
|
|
51
55
|
player-software-name="${props.playerSoftwareName}"
|
|
52
56
|
player-software-version="${props.playerSoftwareVersion}"
|
|
53
57
|
env-key="${props.envKey ?? false}"
|
|
54
58
|
stream-type="${props.streamType ?? false}"
|
|
55
59
|
custom-domain="${props.customDomain ?? false}"
|
|
56
|
-
src="${
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
60
|
+
src="${
|
|
61
|
+
!!props.src
|
|
62
|
+
? props.src
|
|
63
|
+
: props.playbackId
|
|
64
|
+
? getSrcFromPlaybackId(props.playbackId, { domain: props.customDomain, token: props.tokens.playback })
|
|
65
|
+
: false
|
|
66
|
+
}"
|
|
67
|
+
poster="${
|
|
68
|
+
!!props.poster
|
|
69
|
+
? props.poster
|
|
70
|
+
: props.playbackId && !props.audio
|
|
71
|
+
? getPosterURLFromPlaybackId(props.playbackId, {
|
|
72
|
+
domain: props.customDomain,
|
|
73
|
+
thumbnailTime: props.thumbnailTime ?? props.startTime,
|
|
74
|
+
token: props.tokens.thumbnail,
|
|
75
|
+
})
|
|
76
|
+
: false
|
|
77
|
+
}"
|
|
78
|
+
cast-src="${
|
|
79
|
+
!!props.src
|
|
80
|
+
? props.src
|
|
81
|
+
: props.playbackId
|
|
82
|
+
? getSrcFromPlaybackId(props.playbackId, { domain: props.customDomain, token: props.tokens.playback })
|
|
83
|
+
: false
|
|
84
|
+
}"
|
|
75
85
|
cast-stream-type="${[StreamTypes.LIVE, StreamTypes.LL_LIVE].includes(props.streamType as any) ? 'live' : false}"
|
|
76
86
|
>
|
|
77
|
-
${
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
${
|
|
88
|
+
props.playbackId &&
|
|
89
|
+
!props.audio &&
|
|
90
|
+
![StreamTypes.LIVE, StreamTypes.LL_LIVE, StreamTypes.DVR, StreamTypes.LL_DVR].includes(props.streamType as any)
|
|
91
|
+
? html`<track
|
|
92
|
+
label="thumbnails"
|
|
93
|
+
default
|
|
94
|
+
kind="metadata"
|
|
95
|
+
src="${getStoryboardURLFromPlaybackId(props.playbackId, {
|
|
96
|
+
domain: props.customDomain,
|
|
97
|
+
token: props.tokens.storyboard,
|
|
98
|
+
})}"
|
|
99
|
+
/>`
|
|
100
|
+
: html``
|
|
101
|
+
}
|
|
90
102
|
</mux-video>
|
|
91
103
|
<button
|
|
92
104
|
slot="seek-to-live-button"
|
|
@@ -111,16 +123,18 @@ export const content = (props: MuxTemplateProps) => html`
|
|
|
111
123
|
${props.dialog?.title ? html`<h3>${props.dialog.title}</h3>` : html``}
|
|
112
124
|
<p>
|
|
113
125
|
${props.dialog?.message}
|
|
114
|
-
${
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
${
|
|
127
|
+
props.dialog?.linkUrl
|
|
128
|
+
? html`<a
|
|
129
|
+
href="${props.dialog.linkUrl}"
|
|
130
|
+
target="_blank"
|
|
131
|
+
rel="external noopener"
|
|
132
|
+
aria-label="${props.dialog.linkText ?? ''} ${i18n(`(opens in a new window)`)}"
|
|
133
|
+
>${props.dialog.linkText ?? props.dialog.linkUrl}</a
|
|
134
|
+
>`
|
|
135
|
+
: html``
|
|
136
|
+
}
|
|
123
137
|
</p>
|
|
124
138
|
</mxp-dialog>
|
|
125
|
-
|
|
139
|
+
</${unsafeStatic(castThemeName(props.theme) ?? 'media-theme-mux')}>
|
|
126
140
|
`;
|
package/src/types.d.ts
CHANGED
|
@@ -6,11 +6,9 @@ export type MuxPlayerProps = Partial<MuxVideoElement> & {
|
|
|
6
6
|
|
|
7
7
|
export type MuxTemplateProps = Partial<MuxPlayerProps> & {
|
|
8
8
|
audio: boolean;
|
|
9
|
+
theme?: string;
|
|
9
10
|
playerSize: string;
|
|
10
11
|
showLoading: boolean;
|
|
11
|
-
hasCaptions: boolean;
|
|
12
|
-
supportsAirPlay: boolean;
|
|
13
|
-
supportsVolume: boolean;
|
|
14
12
|
thumbnailTime: number;
|
|
15
13
|
primaryColor: string;
|
|
16
14
|
secondaryColor: string;
|
package/src/video-api.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { VideoEvents } from '@mux/mux-video';
|
|
2
2
|
import type MuxVideoElement from '@mux/mux-video';
|
|
3
3
|
import * as logger from './logger';
|
|
4
|
+
import { toNumberOrUndefined } from './utils';
|
|
4
5
|
|
|
5
6
|
export type CastOptions = {
|
|
6
7
|
receiverApplicationId: string;
|
|
@@ -99,6 +100,7 @@ class VideoApiElement extends HTMLElement {
|
|
|
99
100
|
case CustomVideoAttributes.MUTED: {
|
|
100
101
|
if (this.media) {
|
|
101
102
|
this.media.muted = newValue != null;
|
|
103
|
+
this.media.defaultMuted = newValue != null;
|
|
102
104
|
}
|
|
103
105
|
return;
|
|
104
106
|
}
|
|
@@ -113,6 +115,7 @@ class VideoApiElement extends HTMLElement {
|
|
|
113
115
|
const val = +newValue;
|
|
114
116
|
if (this.media && !Number.isNaN(val)) {
|
|
115
117
|
this.media.playbackRate = val;
|
|
118
|
+
this.media.defaultPlaybackRate = val;
|
|
116
119
|
}
|
|
117
120
|
return;
|
|
118
121
|
}
|
|
@@ -217,6 +220,19 @@ class VideoApiElement extends HTMLElement {
|
|
|
217
220
|
}
|
|
218
221
|
}
|
|
219
222
|
|
|
223
|
+
get defaultPlaybackRate() {
|
|
224
|
+
return toNumberOrUndefined(this.getAttribute(CustomVideoAttributes.PLAYBACKRATE)) ?? 1;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
set defaultPlaybackRate(val) {
|
|
228
|
+
if (val != null) {
|
|
229
|
+
this.setAttribute(CustomVideoAttributes.PLAYBACKRATE, `${val}`);
|
|
230
|
+
} else {
|
|
231
|
+
// Remove boolean attribute if false, 0, '', null, undefined.
|
|
232
|
+
this.removeAttribute(CustomVideoAttributes.PLAYBACKRATE);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
220
236
|
get crossOrigin() {
|
|
221
237
|
return getVideoAttribute(this, AllowedVideoAttributes.CROSSORIGIN);
|
|
222
238
|
}
|
|
@@ -252,10 +268,20 @@ class VideoApiElement extends HTMLElement {
|
|
|
252
268
|
}
|
|
253
269
|
|
|
254
270
|
get muted() {
|
|
255
|
-
return
|
|
271
|
+
return this.media?.muted ?? false;
|
|
256
272
|
}
|
|
257
273
|
|
|
258
274
|
set muted(val) {
|
|
275
|
+
if (this.media) {
|
|
276
|
+
this.media.muted = Boolean(val);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
get defaultMuted() {
|
|
281
|
+
return getVideoAttribute(this, AllowedVideoAttributes.MUTED) != null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
set defaultMuted(val) {
|
|
259
285
|
if (val) {
|
|
260
286
|
this.setAttribute(AllowedVideoAttributes.MUTED, '');
|
|
261
287
|
} else {
|
package/test/player.test.js
CHANGED
|
@@ -283,17 +283,29 @@ describe('<mux-player>', () => {
|
|
|
283
283
|
assert(muxVideo.muted, 'muxVideo.muted is true');
|
|
284
284
|
assert(nativeVideo.muted, 'nativeVideo.muted is true');
|
|
285
285
|
|
|
286
|
+
assert(player.defaultMuted, 'player.defaultMuted is true');
|
|
287
|
+
assert(muxVideo.defaultMuted, 'muxVideo.defaultMuted is true');
|
|
288
|
+
assert(nativeVideo.defaultMuted, 'nativeVideo.defaultMuted is true');
|
|
289
|
+
|
|
286
290
|
player.removeAttribute('muted');
|
|
287
291
|
|
|
288
292
|
assert(!player.muted, 'player.muted is false');
|
|
289
293
|
assert(!muxVideo.muted, 'muxVideo.muted is false');
|
|
290
294
|
assert(!nativeVideo.muted, 'nativeVideo.muted is false');
|
|
291
295
|
|
|
296
|
+
assert(!player.defaultMuted, 'player.defaultMuted is false');
|
|
297
|
+
assert(!muxVideo.defaultMuted, 'muxVideo.defaultMuted is false');
|
|
298
|
+
assert(!nativeVideo.defaultMuted, 'nativeVideo.defaultMuted is false');
|
|
299
|
+
|
|
292
300
|
player.setAttribute('muted', '');
|
|
293
301
|
|
|
294
302
|
assert(player.muted, 'player.muted is true');
|
|
295
303
|
assert(muxVideo.muted, 'muxVideo.muted is true');
|
|
296
304
|
assert(nativeVideo.muted, 'nativeVideo.muted is true');
|
|
305
|
+
|
|
306
|
+
assert(player.defaultMuted, 'player.defaultMuted is true');
|
|
307
|
+
assert(muxVideo.defaultMuted, 'muxVideo.defaultMuted is true');
|
|
308
|
+
assert(nativeVideo.defaultMuted, 'nativeVideo.defaultMuted is true');
|
|
297
309
|
});
|
|
298
310
|
|
|
299
311
|
it('volume attribute behaves like expected', async function () {
|
|
@@ -342,6 +354,28 @@ describe('<mux-player>', () => {
|
|
|
342
354
|
assert.equal(nativeVideo.playbackRate, 0.7, 'nativeVideo.playbackRate is 0.7');
|
|
343
355
|
});
|
|
344
356
|
|
|
357
|
+
it('defaultPlaybackRate property behaves like expected', async function () {
|
|
358
|
+
const player = await fixture(`<mux-player
|
|
359
|
+
playback-id="DS00Spx1CV902MCtPj5WknGlR102V5HFkDe"
|
|
360
|
+
stream-type="on-demand"
|
|
361
|
+
></mux-player>`);
|
|
362
|
+
|
|
363
|
+
assert.equal(player.defaultPlaybackRate, 1);
|
|
364
|
+
|
|
365
|
+
const muxVideo = player.media;
|
|
366
|
+
const nativeVideo = muxVideo.shadowRoot.querySelector('video');
|
|
367
|
+
|
|
368
|
+
assert.equal(player.defaultPlaybackRate, 1, 'player.defaultPlaybackRate is 1');
|
|
369
|
+
assert.equal(muxVideo.defaultPlaybackRate, 1, 'muxVideo.defaultPlaybackRate is 1');
|
|
370
|
+
assert.equal(nativeVideo.defaultPlaybackRate, 1, 'nativeVideo.defaultPlaybackRate is 1');
|
|
371
|
+
|
|
372
|
+
player.defaultPlaybackRate = 0.7;
|
|
373
|
+
|
|
374
|
+
assert.equal(player.defaultPlaybackRate, 0.7, 'player.defaultPlaybackRate is 0.7');
|
|
375
|
+
assert.equal(muxVideo.defaultPlaybackRate, 0.7, 'muxVideo.defaultPlaybackRate is 0.7');
|
|
376
|
+
assert.equal(nativeVideo.defaultPlaybackRate, 0.7, 'nativeVideo.defaultPlaybackRate is 0.7');
|
|
377
|
+
});
|
|
378
|
+
|
|
345
379
|
it("signing tokens generate correct asset URL's", async function () {
|
|
346
380
|
// tokens expire in 10 years
|
|
347
381
|
const player = await fixture(`<mux-player
|