From a68e9ba3e78deced9ff0fd1d9553741de8a56136 Mon Sep 17 00:00:00 2001 From: Matthew Oliveira Date: Fri, 6 Dec 2024 18:00:07 -0500 Subject: [PATCH] feat(video-player): enable autoplay & load as muted (#12150) ### Related Ticket(s) [ADCMS-7129](https://jsw.ibm.com/browse/ADCMS-7129) ### Description Ports a couple of v1 player fixes to v2 that got missed to fix auto-play while maintaining background-video mode: Work that I've cherry-picked for this PR: [ADCMS-6363](https://jsw.ibm.com/browse/ADCMS-6363) https://github.com/carbon-design-system/carbon-for-ibm-dotcom/pull/12070 (3d98787c5c7b6ec26d1a4a10762f212dc1d2b23e) https://github.com/carbon-design-system/carbon-for-ibm-dotcom/pull/12081 (863dfdc3690b98a44a1c862877bd1fa106cef12b) ### Changelog **New** - Adds `muted` attribute to `video-player-container` - Adds storybook examples for `auto-play` and `muted` video player usage **Changed** - Fixes `auto-play` attribute on `video-player-container` - Make `background-video` a reflected boolean attribute all the time. - Fix a regression with auto-play video. --- .../video-player/_video-player.scss | 4 +- .../__stories__/README.stories.mdx | 2 +- .../__stories__/background-media.stories.ts | 2 +- .../leadspace/__stories__/README.stories.mdx | 2 +- .../__stories__/leadspace.stories.ts | 10 +- .../__stories__/video-player.stories.ts | 94 ++++++++++++++++++- .../video-player/video-player-composite.ts | 10 +- .../video-player/video-player-container.ts | 89 ++++++++++-------- .../components/video-player/video-player.ts | 16 +++- 9 files changed, 174 insertions(+), 55 deletions(-) diff --git a/packages/styles/scss/components/video-player/_video-player.scss b/packages/styles/scss/components/video-player/_video-player.scss index ef367a215ad..2ce8da05989 100644 --- a/packages/styles/scss/components/video-player/_video-player.scss +++ b/packages/styles/scss/components/video-player/_video-player.scss @@ -43,8 +43,8 @@ $aspect-ratios: ((16, 9), (9, 16), (2, 1), (1, 2), (4, 3), (3, 4), (1, 1)); } } - :host(#{$c4d-prefix}-video-player[background-mode='true']), - .#{$c4d-prefix}--video-player[background-mode='true'] { + :host(#{$c4d-prefix}-video-player[background-mode]), + .#{$c4d-prefix}--video-player[background-mode] { .#{$c4d-prefix}--video-player__video-container { padding: 0; block-size: 100%; diff --git a/packages/web-components/src/components/background-media/__stories__/README.stories.mdx b/packages/web-components/src/components/background-media/__stories__/README.stories.mdx index ef2a8303ce8..dcd52ac423f 100644 --- a/packages/web-components/src/components/background-media/__stories__/README.stories.mdx +++ b/packages/web-components/src/components/background-media/__stories__/README.stories.mdx @@ -69,7 +69,7 @@ import '@carbon/ibmdotcom-web-components/es/components/background-media/index.js + background-mode> ``` diff --git a/packages/web-components/src/components/background-media/__stories__/background-media.stories.ts b/packages/web-components/src/components/background-media/__stories__/background-media.stories.ts index 55c83f31d64..99fb2a33d23 100644 --- a/packages/web-components/src/components/background-media/__stories__/background-media.stories.ts +++ b/packages/web-components/src/components/background-media/__stories__/background-media.stories.ts @@ -56,7 +56,7 @@ export const WithVideo = (args) => { opacity="${ifDefined(backgroundOpacity)}"> + background-mode> `; diff --git a/packages/web-components/src/components/leadspace/__stories__/README.stories.mdx b/packages/web-components/src/components/leadspace/__stories__/README.stories.mdx index f0f0a3882a7..acd4f68f7c4 100644 --- a/packages/web-components/src/components/leadspace/__stories__/README.stories.mdx +++ b/packages/web-components/src/components/leadspace/__stories__/README.stories.mdx @@ -87,7 +87,7 @@ such: + background-mode> ``` diff --git a/packages/web-components/src/components/leadspace/__stories__/leadspace.stories.ts b/packages/web-components/src/components/leadspace/__stories__/leadspace.stories.ts index c61fa9c8b52..a7e32479e50 100644 --- a/packages/web-components/src/components/leadspace/__stories__/leadspace.stories.ts +++ b/packages/web-components/src/components/leadspace/__stories__/leadspace.stories.ts @@ -190,7 +190,7 @@ export const SuperWithVideo = (args) => { + background-mode> `; @@ -335,7 +335,7 @@ export const TallWithVideo = (args) => { + background-mode> `; @@ -480,7 +480,7 @@ export const MediumWithVideo = (args) => { + background-mode> `; @@ -635,7 +635,7 @@ export const ShortWithVideo = (args) => { + background-mode> `; @@ -754,7 +754,7 @@ export const CenteredWithVideo = (args) => { + background-mode> `; diff --git a/packages/web-components/src/components/video-player/__stories__/video-player.stories.ts b/packages/web-components/src/components/video-player/__stories__/video-player.stories.ts index 521036ddb05..2c04e1a1904 100644 --- a/packages/web-components/src/components/video-player/__stories__/video-player.stories.ts +++ b/packages/web-components/src/components/video-player/__stories__/video-player.stories.ts @@ -1,7 +1,7 @@ /** * @license * - * Copyright IBM Corp. 2020, 2023 + * Copyright IBM Corp. 2020, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. @@ -82,6 +82,42 @@ export const withLightboxMediaViewer = (args) => { `; }; +export const autoplay = (args) => { + const { aspectRatio, caption, hideCaption, thumbnail, videoId } = + args?.VideoPlayer ?? {}; + return html` + + `; +}; + +export const autoplayMuted = (args) => { + const { caption, hideCaption, thumbnail, videoId } = args?.VideoPlayer ?? {}; + return html` + + + `; +}; + aspectRatio4x3.story = { name: 'Aspect ratio 4:3', parameters: { @@ -171,6 +207,62 @@ withLightboxMediaViewer.story = { }, }; +autoplay.story = { + name: 'Autoplay', + parameters: { + knobs: { + VideoPlayer: () => { + return { + aspectRatio: '4x3', + caption: text('Custom caption (caption):', ''), + hideCaption: boolean('Hide caption (hideCaption):', false), + thumbnail: text('Custom thumbnail (thumbnail):', ''), + videoId: '0_ibuqxqbe', + }; + }, + }, + propsSet: { + default: { + VideoPlayer: { + aspectRatio: '4x3', + caption: '', + hideCaption: false, + thumbnail: '', + videoId: '0_ibuqxqbe', + }, + }, + }, + }, +}; + +autoplayMuted.story = { + name: 'Autoplay muted', + parameters: { + knobs: { + VideoPlayer: () => { + return { + aspectRatio: '4x3', + caption: text('Custom caption (caption):', ''), + hideCaption: boolean('Hide caption (hideCaption):', false), + thumbnail: text('Custom thumbnail (thumbnail):', ''), + videoId: '0_ibuqxqbe', + }; + }, + }, + propsSet: { + default: { + VideoPlayer: { + aspectRatio: '4x3', + caption: '', + hideCaption: false, + thumbnail: '', + videoId: '0_ibuqxqbe', + }, + }, + }, + }, +}; + export default { title: 'Components/Video player', decorators: [ diff --git a/packages/web-components/src/components/video-player/video-player-composite.ts b/packages/web-components/src/components/video-player/video-player-composite.ts index a7fd888a819..5ada0cbdaeb 100644 --- a/packages/web-components/src/components/video-player/video-player-composite.ts +++ b/packages/web-components/src/components/video-player/video-player-composite.ts @@ -143,6 +143,12 @@ class C4DVideoPlayerComposite extends HybridRenderMixin( @property({ type: Boolean, attribute: 'auto-play' }) autoPlay = false; + /** + * `true` load videos with sound muted. + */ + @property({ type: Boolean, attribute: 'muted' }) + muted = false; + /** * The embedded Kaltura player element (that has `.sendNotification()`, etc. APIs), keyed by the video ID. */ @@ -190,7 +196,7 @@ class C4DVideoPlayerComposite extends HybridRenderMixin( /** * `true` to autoplay, mute, and hide player UI. */ - @property({ type: Boolean, attribute: 'background-mode' }) + @property({ type: Boolean, attribute: 'background-mode', reflect: true }) backgroundMode = false; /** @@ -214,7 +220,7 @@ class C4DVideoPlayerComposite extends HybridRenderMixin( /** * The current playback state */ - @property() + @property({ type: Boolean }) isPlaying = false; /** diff --git a/packages/web-components/src/components/video-player/video-player-container.ts b/packages/web-components/src/components/video-player/video-player-container.ts index 6ac26b6a0b9..d725b49bbac 100644 --- a/packages/web-components/src/components/video-player/video-player-container.ts +++ b/packages/web-components/src/components/video-player/video-player-container.ts @@ -168,45 +168,54 @@ export const C4DVideoPlayerContainerMixin = < const storedValue = localStorage.getItem( `${this.prefersAutoplayStorageKey}` ); - const returnValue = - storedValue === null ? null : Boolean(parseInt(storedValue, 10)); - return returnValue; + + if (storedValue === null) { + return !window.matchMedia('(prefers-reduced-motion: reduce)').matches; + } else { + return Boolean(parseInt(storedValue, 10)); + } } - _getPlayerOptions(backgroundMode = false) { + _getPlayerOptions() { + const { backgroundMode, autoPlay, muted } = + this as unknown as C4DVideoPlayerComposite; let playerOptions = {}; - - if (backgroundMode) { - const storedMotionPreference: boolean | null = - this._getAutoplayPreference(); - - let autoplayPreference: boolean | undefined; - - if (storedMotionPreference === null) { - autoplayPreference = !window.matchMedia( - '(prefers-reduced-motion: reduce)' - ).matches; - } else { - autoplayPreference = storedMotionPreference; - } - playerOptions = { - 'topBarContainer.plugin': false, - 'controlBarContainer.plugin': false, - 'largePlayBtn.plugin': false, - 'loadingSpinner.plugin': false, - 'unMuteOverlayButton.plugin': false, - 'EmbedPlayer.DisableVideoTagSupport': false, - loop: true, - autoMute: true, - autoPlay: autoplayPreference, - // Turn off CTA's including mid-roll card and end cards. - 'ibm.callToActions': false, - // Turn off captions display, background/ambient videos have no - // audio. - closedCaptions: { - plugin: false, - }, - }; + const autoplayPreference = this._getAutoplayPreference(); + + switch (true) { + case autoPlay: + playerOptions = { + autoMute: muted, + autoPlay: autoplayPreference, + }; + break; + + case backgroundMode: + playerOptions = { + 'topBarContainer.plugin': false, + 'controlBarContainer.plugin': false, + 'largePlayBtn.plugin': false, + 'loadingSpinner.plugin': false, + 'unMuteOverlayButton.plugin': false, + 'EmbedPlayer.DisableVideoTagSupport': false, + loop: true, + autoMute: true, + autoPlay: autoplayPreference, + // Turn off CTA's including mid-roll card and end cards. + 'ibm.callToActions': false, + // Turn off captions display, background/ambient videos have no + // audio. + closedCaptions: { + plugin: false, + }, + }; + break; + + default: + playerOptions = { + autoMute: muted, + }; + break; } return playerOptions; @@ -219,7 +228,7 @@ export const C4DVideoPlayerContainerMixin = < * @private */ // Not using TypeScript `private` due to: microsoft/TypeScript#17744 - async _embedVideoImpl(videoId: string, backgroundMode = false) { + async _embedVideoImpl(videoId: string) { const doc = Object.prototype.hasOwnProperty.call(this, 'getRootNode') ? (this.getRootNode() as Document | ShadowRoot) : this.ownerDocument; @@ -240,7 +249,7 @@ export const C4DVideoPlayerContainerMixin = < const embedVideoHandle = await KalturaPlayerAPI.embedMedia( videoId, playerId, - this._getPlayerOptions(backgroundMode) + this._getPlayerOptions() ); const { width, height } = await KalturaPlayerAPI.api(videoId); videoPlayer.style.setProperty('--native-file-width', `${width}px`); @@ -264,7 +273,7 @@ export const C4DVideoPlayerContainerMixin = < * @param videoId The video ID. * @internal */ - _embedMedia = async (videoId: string, backgroundMode = false) => { + _embedMedia = async (videoId: string) => { const { _requestsEmbedVideo: requestsEmbedVideo } = this; const requestEmbedVideo = requestsEmbedVideo[videoId]; @@ -272,7 +281,7 @@ export const C4DVideoPlayerContainerMixin = < return requestEmbedVideo; } - const promiseEmbedVideo = this._embedVideoImpl(videoId, backgroundMode); + const promiseEmbedVideo = this._embedVideoImpl(videoId); this._setRequestEmbedVideoInProgress(videoId, promiseEmbedVideo); try { diff --git a/packages/web-components/src/components/video-player/video-player.ts b/packages/web-components/src/components/video-player/video-player.ts index 7926516f724..e4790a1062c 100644 --- a/packages/web-components/src/components/video-player/video-player.ts +++ b/packages/web-components/src/components/video-player/video-player.ts @@ -80,7 +80,8 @@ class C4DVideoPlayer extends FocusMixin(StableSelectorMixin(LitElement)) { private _renderContent() { const { contentState, name, thumbnailUrl, backgroundMode } = this; return contentState === VIDEO_PLAYER_CONTENT_STATE.THUMBNAIL && - !backgroundMode + !backgroundMode && + !this.autoplay ? html`