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

Prev Next

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        aspectRatio: "16/9", // Set the aspect ratio
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        objectFit: "cover", // Specifies how the video is displayed
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        lang: "ko", // language setting
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        controls: true, // Set whether to display the control bar
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        controlBtn: {
          play: true,             // Playback
          progressBar: true,      // Control bar
          fullscreen: true,       // Full screen
          volume: true,           // Volume
          times: true,            // Remaining time
          pictureInPicture: true, // PIP
          setting: true,           // Settings
          subtitle: true,         // Subtitle
        },
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        progressBarColor: "#2e6ae0", // Specifies the control bar progress color
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        controlActiveTime: 3000, // Sets the control bar display duration (ms)
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        ui: "mobile", // UI type setting
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      options={{
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
            poster: "https://CDNdomain/example_video_01.png",
            vtt: [
              {
                id: "ko",
                file: "https://CDNdomain/example_video_01.vtt",
                label: "Korean",
                default: true, // Default subtitle settings
              },
            ],
          },
        ],
      }}
    />
  );
}

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)

<VpePlayer
  accessKey="YOUR_ACCESS_KEY"
  hls={Hls}
  options={{
    captionType: "html", // Optional. Default value
    captionStyle: {
      fontSize: 20,
      color: "#FFFF00",
      edgeStyle: "uniform",
    },
    playlist: [
      {
        file: "https://CDNdomain/example_video_01.mp4",
        vtt: [{ id: "ko", file: "https://CDNdomain/example_video_01.vtt", label: "Korean", default: true }],
      },
    ],
  }}
/>

Native mode: Follows OS accessibility subtitle settings as is

<VpePlayer
  accessKey="YOUR_ACCESS_KEY"
  hls={Hls}
  options={{
    captionType: "native",
    // captionStyle is not applied.
    playlist: [
      {
        file: "https://CDNdomain/example_video_01.mp4",
        vtt: [{ id: "ko", file: "https://CDNdomain/example_video_01.vtt", label: "Korean", default: true }],
      },
    ],
  }}
/>

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.

<VpePlayer
  accessKey="YOUR_ACCESS_KEY"
  hls={Hls}
  options={{
    playlist: [
      {
        file: "https://CDNdomain/example_video_01.mp4",
        vtt: [
          {
            id: "ko",
            file: "https://CDNdomain/example_video_01.vtt",
            label: "Korean",
            default: true,
          },
        ],
      },
    ],
    captionStyle: {
      fontSize: {
        pc: 18,      // caption font size (px or %)
        mobile: 14,
      },
      color: "#ffffff",
      edgeStyle: "uniform",  // Text edge style (dropshadow, raised, depressed, uniform)
      bottomOffset: {
        pc: 30,      // Move higher to avoid overlapping with the control bar
        mobile: 50,
      },
      sidePadding: {
        pc: 60,      // Wider left and right margins
        mobile: 40,
      },
      lineHeight: {
        pc: 1,       // Tighter subtitle line spacing
        mobile: 1.2,
      },
    },
  }}
/>

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, and the results can be directly applied to the code. For detailed structure and attributes, see the Layout system guide.

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      layout={layout}
      options={{
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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 (
    <div style={{ padding: "0 15px" }}>
      <a href="https://example.com" target="_blank">
        <img
          src="https://example.com/logo.webp"
          style={{ height: 24 }}
          alt="Logo" />
      </a>
    </div>
  );
}

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 (
    <VpePlayer
      accessKey="YOUR_ACCESS_KEY"
      hls={Hls}
      dashjs={dashjs}
      platform="pub"
      layout={layout}
      options={{
        playlist: [
          {
            file: "https://CDNdomain/example_video_01.mp4",
          },
        ],
      }}
    />
  );
}

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
);