Skip to main content
The player can be used in headless mode if you want to build your own user-interface on top of it. If the player is initialized without a target, the UI will be disabled and it will be mounted at the end of the <body> tag. Alternatively, you can set showUserInterface: false when initializing the player to disable the UI:
new BeyondWords.Player({
  projectId: <ID>,
  contentId: '<ID>',
  target: "#my-div",
  showUserInterface: false,
});
Note that the player will always be mounted in the DOM, even when you are using headless mode. This is because the player is built on top of a native media element (a <video> tag). If playerStyle: "video", showUserInterface: false is set then the <video> tag will show without any controls.

Overview

The simplest way to build your own UI is to repeatedly query the player instance and re-render. For example, you can get player.playbackState and player.currentTime then update your UI accordingly. More complex features like progress bars can be built using this technique. The simplest way to repeatedly query the player is by registering an event listener for all events:
player.addEventListener("<any>", rerenderCustomUserInterface);

const rerenderCustomUserInterface = () => {
  // Update your user-interface by querying the player object.
};
Your function will then be called whenever anything changes in the player, such as the currentTime being updated. See Listening to Events and Player Events for more information.

Using React

If you’re using React, here’s how you might implement the above technique in a component:
import { useEffect, useState } from "react";

const CustomUserInterface = ({ player }) => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const listener = player.addEventListener("<any>", () => setCounter(i => i + 1));
    return () => player.removeEventListener("<any>", listener);
  }, []);

  return (
    <span>Current time: {player.currentTime}</span>
    <button onClick={() => player.playbackState = "playing"}>Play</button>
  );
};
In this example, the component is forced to re-render when the counter is updated. Note that the counter isn’t actually displayed, we are just using it to force the component to rerender.

Cleaning up

The return value of addEventListener is a string that is a handle to the listener. This allows you remove the listener, for example, if a React component is unmounted:
useEffect(() => {
  const listener = player.addEventListener("<any>", console.log);
  return () => player.removeEventListener("<any>", listener);
}, []);
Or when your Svelte component is unmounted:
onMount(() => {
  const listener = player.addEventListener("<any>", console.log);
  return () => player.removeEventListener("<any>", listener);
});
Otherwise, the callback function will continue to be called which may result in an error in your application.