--- title: "Player UI" slug: "vpe-react-player-ui" updated: 2026-09-17T09:22:36Z published: 2026-09-17T09:22:36Z canonical: "guide.ncloud-docs.com/vpe-react-player-ui" stale: true --- > ## Documentation Index > Fetch the complete documentation index at: https://guide.ncloud-docs.com/llms.txt > Use this file to discover all available pages before exploring further. # Player UI Available in Classic and VPC It explains how to modify the script code to configure UI-related options. Note - For descriptions of properties to set options, see player settings. - The available options may vary depending on your subscription plan. ## Default option ### aspectRatio (interface ratio) This property sets the aspect ratio of the player component. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ### objectFit (Full screen) This property sets how the video fits the component. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ### Language (multilingual) Set the language used in the player. If not set, it follows the language used in the browser. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ## Control bar ### controls (show control bar) Set whether to display the default control bar UI. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ### controlBtn (control bar button UI) Individually set the visibility of control bar buttons. Note Available only with the standard plan. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ### progressBarColor (control bar color) Set the progress color of the control bar. Note Available only with the standard plan. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ### controlActiveTime (control bar display duration) Sets the duration for which the control bar is displayed. Note If set to `controlActiveTime: 0`, the control bar will not be hidden automatically and will always be displayed. This is useful for interfaces where the UI should always be shown, such as live commerce. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ### UI (fix control bar UI) Designate the UI type. Note Available only with the standard plan. - The mobile UI provides `touchGestures`, while the PC UI provides `keyboardShortcut`. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ## Subtitles ### Subtitle settings (vtt) Connect the VTT subtitle. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Video (MP4) export function App() { return ( ); } ``` ### captionType (subtitle rendering type) This option determines how subtitles are rendered. You can choose `"html"` (default) or `"native"`, and the behavior will vary depending on whether design consistency is prioritized or OS accessibility settings are prioritized. | Item | `"html"` (default) | `"native"` | | --- | --- | --- | | Rendering entity | The SDK draws subtitles directly `<div>` on top of the player. | Uses the default `::cue` rendering of the browser/OS. | | captionStyle option | Applied to all (directly controlled with inline styles) | Ignored (consistent styling not possible due to browser-specific `::cue` support differences) | | OS accessibility subtitle settings | No effect (on mobile, the native subtitle UI is blocked by `track.mode="hidden"`, ensuring consistent styling) | Directly reflected (follows iOS , and Android **Settings > Accessibility > Subtitles & Captioning** and Android **Settings > Accessibility > Caption preferences**) | | Recommended case | Design consistency prioritized (e.g., dark mode UI, brand-colored subtitles) | Web accessibility prioritized (services that must follow OS accessibility settings due to visual assistance policies) | Note According to the Web Accessibility (WCAG) guidelines, users must be able to adjust subtitle fonts, sizes, and colors themselves. `captionType: "native"` directly reflects the OS-provided accessibility subtitle settings, delivering the closest experience for users who require visual assistance. **html mode: Styled directly with captionStyle (default)** ``` ``` **Native mode: Follows OS accessibility subtitle settings as is** ``` ``` ### captionStyle (caption style) Caption font size, color, background, edge treatment, line spacing, and position are directly configurable as options. Applies only when `captionType` is set to `"html"` (default), and is ignored in `"native"` mode. Can be used when consistent subtitle styling is required, such as brand colors or dark mode UI. ``` ``` **captionStyle property** If unspecified, the default value is applied automatically, and when options are provided, they are deep-merged with the default. (Example: If only `{ fontSize: 20 }` is passed, it applies `fontSize=20` plus defaults for the rest) Responsive branching: `fontSize`, `lineHeight`, `bottomOffset`, and `sidePadding` can be designated as a single value or a `{ pc, mobile }` object. | Properties | Type | Default value | Description | | --- | --- | --- | --- | | `fontSize` | `number \\| string \\| { pc?, mobile? }` | `{ pc: 20, mobile: 14 }` | Caption font size (in px/CSS). PC/mobile branching supported | | `fontFamily` | `string` | — | Caption font (CSS font-family) | | `color` | `string` | `#ffffff` | Subtitle text color (CSS color value) | | `backgroundColor` | `string` | `transparent` | Subtitle box background color Example: `rgba(0,0,0,0.4)` | | `opacity` | `number` | `1` | Subtitle text overall opacity (0–1) | | `lineHeight` | `number \\| string \\| { pc?, mobile? }` | `{ pc: 1.3, mobile: 1.2 }` | Subtitle line spacing (multiplier) PC/mobile branching supported | | `edgeStyle` | `none \\| dropshadow \\| raised \\| depressed \\| uniform` | `uniform` | Subtitle text edge treatment method (high readability on both light and dark backgrounds) | | `bottomOffset` | `number \\| { pc?, mobile? }` | `{ pc: 30, mobile: 10 }` | Spacing from bottom of player (px) Adjust to avoid overlapping with the control bar PC/mobile branching supported | | `sidePadding` | `number \\| { pc?, mobile? }` | `{ pc: 60, mobile: 40 }` | Left/right safe component (px) PC/mobile branching supported | | `padding` | `number \\| string` | `3px 5px` | Subtitle text box inner padding (CSS padding value) | Note edgeStyle type: `none` (no effect)/`dropshadow` (shadow)/`raised` (raised effect)/`depressed` (inset effect)/`uniform` (outline in 4 directions, default recommended) ## Layout system By using the layout system, you can declaratively define the placement of control bar buttons, area composition, and insertion of custom components based on JSON. You can separately manage screen environments (PC/mobile/Full screen) and content types (VOD/Live). Note - Available only with the standard plan. - Layout JSON can be visually edited in the [UI Editor](https://vpe-player-editor.web.app/), and the results can be directly applied to the code. For detailed structure and attributes, see the [Layout system guide](https://developer.vpe.naverncp.com/docs/en/layout-system). ### Default layout configuration Use to `order` define the section order, and place rows in each section. You can insert built-in components or custom elements into the `items` of a row. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; const layout = { pc: { vod: { order: ["top", "center", "bottom"], top: [{ items: ["MetaDesc"] }], center: [{ items: ["BigPlayBtn"], align: "center" }], bottom: [ { items: ["ProgressBar"] }, { items: ["PlayBtn", "VolumeBtn", "TimeBtn"], wrapper: "Group" }, { wrapper: "Blank", items: [] }, { items: ["SettingBtn", "PipBtn", "FullscreenBtn"], wrapper: "Group" }, ], }, }, }; export function App() { return ( ); } ``` ### Layout type `layout` props can be passed in the following 3 forms. ``` // 1) Single layout — one control bar configuration without branching for Live/VOD/device type ControlBarLayout = { order?: string[]; top?: Group[]; upper?: Group[]; center?: Group[]; lower?: Group[]; bottom?: Group[]; }; // 2) Live/VOD branching type ControlBarLayoutVariant = { live: ControlBarLayout; vod: ControlBarLayout; }; // 3) Responsive (PC/mobile/Full screen branching) type ControlBarLayoutResponsive = { pc: { live: ControlBarLayout; vod: ControlBarLayout }; mobile: { live: ControlBarLayout; vod: ControlBarLayout }; fullscreen: { live: ControlBarLayout; vod: ControlBarLayout }; breakpoint?: number; // default 768 }; ``` ### Configuration structure The top-level keys are divided into `pc`, `mobile`, and `fullscreen`, and each environment defines the `vod` and `live` layouts. ``` { "pc": { "vod": { }, "live": { } }, "mobile": { "vod": { }, "live": { } }, "fullscreen": { "vod": { }, "live": { } } } ``` `layout.json` ### Section and sequence The `order` array determines the rendering order. The default sections are `top`, `upper`, `center`, `lower`, and `bottom`. ``` { "order": ["top", "upper", "center", "lower", "bottom"], "top": [ { "items": ["MetaDesc"] }, { "wrapper": "Blank", "items": [], "align": "left" }, { "items": ["ShareBtn"] } ], "center": [ { "items": ["BigPlayBtn"], "align": "center" } ], "bottom": [ { "items": ["ProgressBar"] }, { "items": ["PlayBtn", "VolumeBtn", "TimeDisplay"], "align": "left" }, { "items": ["SettingBtn", "PIPBtn", "FullscreenBtn"], "align": "right" } ] } ``` `pc.vod.json` ### Row configuration Each section is composed of multiple rows. A row places buttons or components through an `items` array, and adjusts alignment and grouping using `align` and `wrapper`. | Key | Type | Description | | --- | --- | --- | | `key` | `string` | Group identifier. For runtime `layout()` merge, replace among groups of the same `key` (recommended) | | `items` | `(string \\| ReactNode)[]` | Control list to be placed in a row (built-in keys or custom components) | | `align` | `left \\| center \\| right` | Content arrangement in rows | | `wrapper` | `"Group" \\| "Blank"` | Wrapper type to apply to a row (group = grouping, blank = empty space/spacing) | | `cap` | `number` | Limit on the number of items displayed within a row | | `noPadding` | `boolean` | Remove left and right padding from group | ### Default layout example If you assign `key` to each group, you can safely replace only specific groups during runtime merging. ``` const layout: ControlBarLayout = { top: [], center: [{ key: "bigPlayBtn", items: ["BigPlayBtn"] }], bottom: [ { key: "play", items: ["PlayBtn"], wrapper: "Group", noPadding: true }, { key: "volume", items: ["VolumeBtn"], wrapper: "Group" }, { key: "time", items: ["TimeBtn"], wrapper: "Group" }, { key: "blank", wrapper: "Blank", items: [] }, { key: "right", items: ["SubtitleBtn", "FullscreenBtn"], cap: 2, wrapper: "Group" }, ], }; ``` ### Insert a custom component If you pass your own custom components instead of built-in keys to the `items` array of the layout, you can place custom UI at the desired position within the control bar. ``` import Hls from "hls.js"; import dashjs from "dashjs"; import { VpePlayer } from "@sgrsoft/vpe-react-sdk"; // Custom logo component function Logo() { return ( ); } const layout = { pc: { vod: { order: ["top", "center", "bottom"], top: [{ items: ["MetaDesc"] }], center: [{ items: ["BigPlayBtn"], align: "center" }], bottom: [ { items: ["PlayBtn", "PrevBtn", "NextBtn"], wrapper: "Group" }, { items: ["VolumeBtn"], wrapper: "Group" }, { items: ["TimeBtn"], wrapper: "Group" }, { wrapper: "Blank", items: [] }, { items: [Logo()], wrapper: "Group" }, // Custom component { items: ["SubtitleBtn", "PipBtn", "SettingBtn", "FullscreenBtn"], cap: 2, wrapper: "Group" }, ], }, }, }; export function App() { return ( ); } ``` ### Realtime change (ref) By calling `playerRef.current?.layout(nextLayout, merge?)`, you can dynamically change the layout even during playback. The default value of the second factor `merge` is `true`. **Merge rule (merge: True)** 1. Among `top`/`upper`/`center`/`lower`/`bottom`/`order`, sections not defined in next will retain the base. 2. Group merge within a section is based on `key` as follows: - When a group has the same key in both base and next, it will be replaced by next. - Keys that exist only in base will retain the base. - Keys that exist only in next will be appended to the end of the result. - Groups without a key in next will be appended to the end of the result (considered as newly added). 3. If both groups have no key, the entire section will be replaced (backward compatibility). **Example: Replace certain groups only** ``` // base (default pcLayout.vod) // bottom: [ // { key: "play", items: ["PlayBtn"] }, // { key: "volume", items: ["VolumeBtn"] }, // { key: "time", items: ["TimeBtn"] }, // { key: "blank", wrapper: "Blank", items: [] }, // { key: "right", items: ["SubtitleBtn", "FullscreenBtn"] }, // ] playerRef.current?.layout({ bottom: [{ key: "right", items: ["SubtitleBtn", "PipBtn", "SettingBtn", "FullscreenBtn"] }], }); // Result: Keep play/volume/time/blank, replace only right. ``` **Example: Add a new group** ``` playerRef.current?.layout({ bottom: [{ key: "extra", items: ["ShareBtn"] }], }); // Result: Existing 5 groups + append extra (ShareBtn) at the end ``` **Example: Replace all sections (merge: False)** ``` playerRef.current?.layout( { bottom: [{ items: ["PlayBtn"] }] }, false, // Replace all ); ```