Pular para o conteúdo principal

Video

The Video component provides a video player that supports both self-hosted videos (MP4, HLS, DASH) and YouTube videos. It's a compound component: a source-agnostic Video.Root wraps a single player subcomponent that determines where the video comes from.

Video

There are two players available:

  • Video.Player — plays self-hosted videos and offers more customization (custom controls, poster, lightbox).
  • Video.YouTube — embeds a YouTube video through YouTube's official IFrame API, with less customization to stay compliant with YouTube's Terms of Service.

Video.Root owns the shared playback options (autoplay, muted, loop) and the playback events (onPlay, onPause, onEnded, onProgress, onBuffer), so those behave the same regardless of the video source.

Lazy loading
The underlying playback engine is only downloaded the first time a video is rendered on the page, so adding the component doesn't increase the initial size of your app.

Usage

Compose a Video.Root with a single player as its child.

Self-hosted video
import type { NubeSDK } from "@tiendanube/nube-sdk-types";
import { Video } from "@tiendanube/nube-sdk-jsx";

function MyComponent() {
return (
<Video.Root width="100%">
<Video.Player
src="https://cdn.example.com/product-demo.mp4"
poster="https://cdn.example.com/poster.jpg"
controls
/>
</Video.Root>
);
}

export function App(nube: NubeSDK) {
nube.render("after_product_description", <MyComponent />);
}

To embed a YouTube video, swap Video.Player for Video.YouTube. The src accepts either a YouTube video ID or any youtube.com / youtu.be URL:

YouTube video
import type { NubeSDK } from "@tiendanube/nube-sdk-types";
import { Video } from "@tiendanube/nube-sdk-jsx";

function MyComponent() {
return (
<Video.Root width="100%">
<Video.YouTube
src="https://www.youtube.com/watch?v=dlZf-eTkU7k"
controls
/>
</Video.Root>
);
}

export function App(nube: NubeSDK) {
nube.render("after_product_description", <MyComponent />);
}

Playback options

autoplay, muted and loop are set on Video.Root and apply to whichever player is used.

Autoplaying, looping video
<Video.Root autoplay loop>
<Video.Player src="https://cdn.example.com/background-loop.mp4" controls={false} />
</Video.Root>
Autoplay is always muted
Browsers only allow autoplay for muted videos. When autoplay is true the video is always started muted, regardless of the muted value.

Set lightbox on Video.Player to replace the native fullscreen button with a custom fullscreen overlay. This gives a consistent fullscreen experience across browsers and, unlike native fullscreen, keeps playback state (current time, buffered range) when opening and closing. It's not available on Video.YouTube, which uses YouTube's own native fullscreen.

Player with lightbox
<Video.Root>
<Video.Player src="https://cdn.example.com/product-demo.mp4" lightbox />
</Video.Root>

Any children placed after the player inside Video.Root are rendered as an overlay on top of the video while the lightbox is open — useful for captions, calls to action, or other content layered over the video.

Overlay content over the lightbox
<Video.Root>
<Video.Player src="https://cdn.example.com/product-demo.mp4" lightbox />
<Text modifiers={["bold"]}>Shop the look</Text>
</Video.Root>

Events

The playback lifecycle events live on Video.Root because they are the same for every video source. Each handler receives an object with type, the current SDK state, and a value payload:

Eventvalue payloadDescription
onPlay{ currentTime: number }Fired when playback starts or resumes.
onPause{ currentTime: number }Fired when playback is paused.
onEnded{ currentTime: number }Fired when the video reaches the end.
onProgress{ percent: number, currentTime: number, duration: number }Fired periodically (about once per second) during playback.
onBuffer{ buffering: boolean }Fired when buffering starts (true) or stops (false).
Listening to playback events
<Video.Root
onPlay={({ value }) => console.log("playing at", value.currentTime)}
onPause={({ value }) => console.log("paused at", value.currentTime)}
onEnded={() => console.log("finished")}
onProgress={({ value }) => console.log(`${value.percent}%`)}
onBuffer={({ value }) => console.log("buffering:", value.buffering)}
>
<Video.Player src="https://cdn.example.com/product-demo.mp4" controls />
</Video.Root>

Errors

Errors are source-specific, so onError lives on the player rather than on Video.Root. The handler receives a value payload with a source, a code, and a human-readable message.

Video.Player reports source: "video-player" with one of these codes:

CodeDescription
invalid_sourceThe src URL is missing, unsafe, or unsupported.
media_err_abortedPlayback was aborted.
media_err_networkA network error interrupted the download.
media_err_decodeThe media could not be decoded.
media_err_src_not_supportedThe source format is not supported.
playback_errorA playback failure with no more specific code.

Video.YouTube reports source: "video-youtube" with one of these codes:

CodeDescription
invalid_sourceThe src is not a recognizable YouTube video ID or URL.
invalid_video_idYouTube rejected the video ID.
html5_errorThe video can't be played in an HTML5 player.
video_not_foundThe video was not found or was removed.
embedding_not_allowedThe video owner disabled embedding.
playback_errorA playback failure with no more specific code.
Handling player errors
<Video.Root>
<Video.Player
src="https://cdn.example.com/product-demo.mp4"
onError={({ value }) => console.error(value.code, value.message)}
/>
</Video.Root>

Subcomponents

Video.Root

The source-agnostic wrapper. It controls layout and the shared playback options and events, and must contain exactly one player (Video.Player or Video.YouTube), optionally followed by overlay children.

PropertyTypeRequiredDescription
childrenNubeChildrenComponentYesA single Video.Player or Video.YouTube, optionally followed by overlay content.
widthSizeNoWidth of the video (e.g., "100%", "600px", 600). Defaults to "100%".
heightSizeNoHeight of the video.
autoplaybooleanNoStarts playback on mount. Always muted when true.
mutedbooleanNoStarts the video muted.
loopbooleanNoRestarts the video automatically when it ends.
onPlay(event) => voidNoCalled when playback starts or resumes.
onPause(event) => voidNoCalled when playback is paused.
onEnded(event) => voidNoCalled when the video reaches the end.
onProgress(event) => voidNoCalled periodically during playback.
onBuffer(event) => voidNoCalled when buffering starts or stops.
styleStyleSheetNoCustom styles for the video container.
idstringNoOptional unique identifier for the component.

Video.Player

Plays a self-hosted video (MP4, HLS or DASH) and must be a child of Video.Root.

PropertyTypeRequiredDescription
srcstringYesAbsolute http(s) URL of an MP4, HLS (.m3u8) or DASH (.mpd) video.
posterstringNoAbsolute http(s) URL of a poster image shown before playback.
controlsbooleanNoShow the player's default controls. Defaults to true.
lightboxbooleanNoReplace the native fullscreen button with a custom fullscreen overlay.
onError(event) => voidNoCalled on a source-specific playback error (see Errors ).
idstringNoOptional unique identifier for the component.

Video.YouTube

Embeds a YouTube video through YouTube's official IFrame API and must be a child of Video.Root.

PropertyTypeRequiredDescription
srcstringYesA YouTube video ID (e.g. YE7VzlLtp-4) or any youtube.com / youtu.be URL.
controlsbooleanNoShow YouTube's native control bar. Defaults to false.
allowFullscreenbooleanNoAllow fullscreen via YouTube's native fullscreen button. Defaults to true. Only reachable when controls is true.
onError(event) => voidNoCalled on a source-specific playback error (see Errors ).
idstringNoOptional unique identifier for the component.
YouTube branding
To comply with YouTube's Terms of Service, Video.YouTube cannot be visually customized. Even with controls turned off, the YouTube logo and the "Watch on YouTube" link remain visible, and they are not removable.

Help us improve NubeSDK

Found an issue or have a suggestion? Let us know on GitHub.