Cue Points

Overview

Cue points are timestamped markers that you can display on the Fastevo MP2 Player's seek bar. When playback reaches a cue point, the player emits an event so your page can react — display a note, update surrounding UI, log progress, show related material, and so on. Viewers can also click (or tap) a cue point on the seek bar to seek directly to that moment.

Cue points are injected at runtime from your page: you supply the list and the player paints the ticks and handles all the interaction.

Typical use cases:

  • Chapter-style navigation on long content.
  • Highlighting notable moments (goals, key scenes, quiz boundaries).
  • Triggering UI changes, overlays, or call-to-actions at specific times.
  • User-driven bookmarking or tagging.

Compatibility

  • VOD only. Cue points are disabled for live streams. Since seekable ranges shift over time on live content, cue point positions become ambiguous.
  • Video content only. Cue points do not apply to audio or image content types.

Cue Point Object Shape

Each cue point is a plain object with two required fields:

FieldTypeDescription
timenumberTimestamp in milliseconds from the start of the video.
textstringLabel shown in the tooltip when the tick is hovered. Kept short is best (single line).

Example list:

var cuePointsList = [
  { time: 5000,  text: "Introduction" },
  { time: 15000, text: "Chapter 1" },
  { time: 30000, text: "Key takeaway" },
  { time: 45000, text: "Chapter 2" },
  { time: 60000, text: "Conclusion" }
];
ℹ️

Cue points whose time falls beyond the video's duration are silently ignored — they are not painted and they do not fire events.


Injecting Cue Points

You inject the list by sending a setCuePoints command to the player, with the cue points array under data.cuePoints.

As with every other player command, you have two equivalent ways to send it:

Method 1 — player.sendCommand

var container = document.getElementById("my-video-container");
 
container.addEventListener("playerInitialized", function (e) {
  var player = window.players[e.detail.playerId];
 
  player.sendCommand("setCuePoints", {
    cuePoints: [
      { time: 5000,  text: "Introduction" },
      { time: 15000, text: "Chapter 1" },
      { time: 30000, text: "Key takeaway" }
    ]
  });
});

Method 2 — Dispatching a playerCommand event

var container = document.getElementById("my-video-container");
 
container.addEventListener("playerInitialized", function () {
  var setCuePointsEvent = new CustomEvent("playerCommand", {
    detail: {
      eventName: "setCuePoints",
      data: {
        cuePoints: [
          { time: 5000,  text: "Introduction" },
          { time: 15000, text: "Chapter 1" },
          { time: 30000, text: "Key takeaway" }
        ]
      }
    }
  });
 
  container.dispatchEvent(setCuePointsEvent);
});

Both approaches produce the same result. Use whichever matches your project's style.

When Can I Inject?

Any time after the player is ready. The safe signals are:

  1. playerInitialized on the container — fires once the player instance has been created and registered at window.players[containerId]. This is the earliest reliable point.
  2. loadedMetadata — fires slightly later, once the media metadata (duration, dimensions) has loaded. Useful if you want to compute cue point times based on the video's duration.

You can inject before or after playback starts, multiple times, at any moment during the session.

Replacing Cue Points

Every call to setCuePoints replaces the entire list. The player does not merge or append — it normalizes the new list, wipes the old ticks, and repaints.

// Set an initial list.
player.sendCommand("setCuePoints", {
  cuePoints: [
    { time: 5000, text: "Intro" }
  ]
});
 
// Later, replace it entirely with a different set.
player.sendCommand("setCuePoints", {
  cuePoints: [
    { time: 10000, text: "Act 1" },
    { time: 60000, text: "Act 2" }
  ]
});
 
// To clear all cue points, send an empty list.
player.sendCommand("setCuePoints", { cuePoints: [] });
ℹ️

When you replace the list mid-playback, cue points whose time is already behind the current playhead do not fire retroactively. Only cue points that the playhead crosses going forward will emit cuePointReached.


Listening to Cue Point Events

Two events are emitted by the player. You can listen to them with either player.on(eventName, handler) or a DOM listener on the container.

cuePointReached

Description: Fired when the playhead crosses a cue point's timestamp during playback.

Event Data:

  • time (number) — The cue point time in milliseconds (matches the original injected value).
  • text (string) — The cue point label.
  • index (number) — The index of the cue point in the list that was most recently passed to setCuePoints.

Applicable to: Video

Example:

player.on("cuePointReached", function (data) {
  console.log("Reached cue point:", data.text, "at", data.time, "ms");
});
 
// or via DOM event:
container.addEventListener("cuePointReached", function (e) {
  console.log("Reached cue point:", e.detail.text, "at", e.detail.time, "ms");
});

cuePointClicked

Description: Fired when the viewer clicks or taps a cue point tick on the seek bar. The player automatically seeks to the cue point's time when this happens.

Event Data:

  • time (number) — The cue point time in milliseconds.
  • text (string) — The cue point label.
  • index (number) — The index of the cue point in the current list.
  • currentTimeAtClickInSeconds (number) — Where the playhead was (in seconds) before the click triggered the seek.

Applicable to: Video

Example:

player.on("cuePointClicked", function (data) {
  console.log(
    "User jumped from", data.currentTimeAtClickInSeconds, "s",
    "to cue point:", data.text
  );
});
 
// or via DOM event:
container.addEventListener("cuePointClicked", function (e) {
  console.log("Cue point clicked:", e.detail);
});

Firing Behavior In Detail

The rules for when cuePointReached fires are designed to feel predictable and avoid floods:

  • Forward playback: as the playhead crosses a cue point, the event fires once for that cue point.
  • Forward seek that crosses several cue points at once (e.g. the viewer drags the scrubber past three markers): only the last cue point in the jumped range fires. This prevents burst-firing.
  • Backward seek: no cue points refire when moving backward. If the viewer later plays forward and crosses the same cue point again, it will fire then.
  • Looping: when the video loops back to the start, subsequent forward crossings fire cue points again as expected.
  • Exact-time matching: the player compares against a half-open range, so brief skips in the native timeupdate cadence never miss a cue point.

Customizing the Look

Color

Cue points are rendered as small circular markers on the seek bar. The fill color is configurable through your player configuration's playerColorsConfiguration object, via the cuePointColor field. If you do not specify one, the player uses white, which contrasts well against the default seek bar.

See Player Configurations for how to create/update a player configuration.

{
  "playerColorsConfiguration": {
    "base": "#1F1F1F",
    "buffered": "#323232",
    "played": "#0078D7",
    "cuePointColor": "#FF3366"
  }
}

On hover, ticks brighten automatically via a CSS filter — regardless of the color you pick.

Hiding the Markers While Keeping the Events

If you want the events (cuePointReached, cuePointClicked) without drawing anything on the seek bar, set cuePointsVisibleOnTimeline to false in your player configuration:

{
  "cuePointsVisibleOnTimeline": false
}
ℹ️

If the player is configured with displayControls: false, the seek bar is not rendered and the cue point feature is inactive (no ticks, no events). Cue points require the standard UI.


Complete Example

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Cue Points Example</title>
  </head>
  <body>
    <!-- Player container -->
    <div
      id="my-video-container"
      data-token="YOUR_PLAYBACK_TOKEN"
      data-config='{"autoPlay":"false"}'
    ></div>
 
    <!-- Fastevo MP2 Player embedder -->
    <script src="https://player.fastevo.net/release/index.js"></script>
 
    <script>
      var container = document.getElementById("my-video-container");
 
      // Wait for the player to be ready, then inject cue points.
      container.addEventListener("playerInitialized", function (e) {
        var player = window.players[e.detail.playerId];
 
        player.sendCommand("setCuePoints", {
          cuePoints: [
            { time: 5000,  text: "Introduction" },
            { time: 15000, text: "Chapter 1"    },
            { time: 30000, text: "Key takeaway" },
            { time: 45000, text: "Chapter 2"    },
            { time: 60000, text: "Conclusion"   }
          ]
        });
      });
 
      // React when the playhead crosses a cue point.
      container.addEventListener("cuePointReached", function (e) {
        var sidebar = document.getElementById("current-note");
        sidebar.textContent = e.detail.text;
      });
 
      // React when the viewer clicks a cue point tick.
      container.addEventListener("cuePointClicked", function (e) {
        console.log(
          "Viewer jumped to",
          e.detail.text,
          "(was at",
          e.detail.currentTimeAtClickInSeconds,
          "s)"
        );
      });
    </script>
 
    <aside>
      <h3>Current section</h3>
      <p id="current-note">Waiting…</p>
    </aside>
  </body>
</html>

Migrating from Radiant Media Player (RMP)

The injection shape ({ time, text }) and the cuePointsVisibleOnTimeline flag are intentionally compatible with RMP's cue-points API, so migration is mostly a rename:

RMPFastevo MP2 Player
cuePoints: [{ time, text }, …] settingsendCommand("setCuePoints", { cuePoints: [...] })
cuePointsCallback functioncuePointReached event
rmp.cuePointData getterdata payload on cuePointReached
cuePointsVisibleOnTimeline settingcuePointsVisibleOnTimeline player configuration field

RMP does not define a click behavior on ticks; the Fastevo MP2 Player adds it as cuePointClicked.


Additional Resources