Skip to content

Vabu player element ​

<vabu-player> is a video player for Vabu Streams that you add to a page with one HTML tag. Give it a publishable key, the id of a live stream or video, and a function that fetches a customer token from your server. It does the rest: it opens the viewer's session, plays, switches to the next source when one fails, shows moments when the video reaches them and sends quality data.

It works in any framework and in Android and iOS WebViews. If you want your own player and buttons, use the player kit instead. This element is built on it.

Add it to a page ​

The element is not on npm yet. Build packages/elements and host dist/vabu-player.js on your own site. Point src at your copy.

html
<script type="module" src="/vabu-player.js"></script>

<vabu-player
  publishable-key="vpk_live_..."
  resource="ls_..."
  api-base="https://api.vabu.live"
  collector-base="https://collect.vabu.live"
  poster="/poster.jpg"
></vabu-player>

<script type="module">
  const player = document.querySelector('vabu-player')

  player.customerToken = () => fetch('/api/vabu-token').then((res) => res.text())
</script>

Or install it and import it in your bundle:

sh
npm install @vabu/elements
ts
import '@vabu/elements'

The file carries hls.js. It is about 20 KB gzipped for the player and Lit, plus about 113 KB for the light hls.js build. It needs a browser from 2022 or later.

Your server signs the customer token. The player kit page has an example route.

Nothing opens until the viewer presses play, so a page view does not use up a view or a device. Add autoplay to start at once. Browsers usually allow autoplay only for muted video, so pair it with muted.

Attributes and properties ​

AttributeMeaning
publishable-keyYour publishable key.
resourceThe id of a live stream (ls_...) or a video (ast_...).
api-baseThe Vabu API host. Default https://api.vabu.live.
collector-baseWhere quality data goes. Leave it out to send none.
posterAn image to show before play.
autoplayStart as soon as the key, the resource and the token function are set.
mutedStart muted. The mute button changes it.
data-saverCap renditions at 360p, or the closest lower height.
momentsfeed (default for a live stream), manual or none. See below.
langen or sw. Without it the player follows the nearest lang on the page.

The property customerToken is a function that returns a token, or a promise of one. The player calls it when it starts and again before the token expires. Setting it, the key or the resource while the player runs starts it again with the new values.

Methods: play(), pause() and addMoment(moment).

Events ​

Every event bubbles and crosses the shadow boundary, so you can listen on the tag or above it.

EventWhendetail
vabu-readyThe session is open and playback is attached.{ sessionId, provider }
vabu-momentThe video reached a moment.The moment: { id, type, label, payload, occurred_at, display_ms }
vabu-sourcePlayback moved to another source.{ from, to, reason } (provider names)
vabu-endedThe session ended on the server.{ reason }, as in the kit's list
vabu-errorSomething failed.{ code, message, fatal, details, cause }
js
player.addEventListener('vabu-error', (event) => {
  console.warn(event.detail.code, event.detail.details)
})

Moments ​

With moments="feed" the player follows the viewer feed of the live stream and shows each moment when the video reaches it. With moments="manual" it does not poll. Hand moments over from your own realtime channel with addMoment:

js
realtime.on('shoutout', (shoutout) => {
  player.addMoment({
    id: shoutout.id,
    occurred_at: shoutout.paidAt, // ISO 8601 or milliseconds, on the same clock as your stream
    label: shoutout.title,
    payload: { message: shoutout.message },
    display_ms: 8000,
  })
})

moments="none" turns moments off. A video has no feed.

The default is a small toast with the label and, if payload.message is a string, that text. It draws text only, never HTML. To draw your own, put an element in the moment slot. The toast hides while something is slotted, and you listen to vabu-moment to know what to show:

html
<vabu-player ...>
  <div slot="moment" id="shoutout" hidden></div>
</vabu-player>

<script type="module">
  const player = document.querySelector('vabu-player')
  const box = document.getElementById('shoutout')

  player.addEventListener('vabu-moment', ({ detail }) => {
    box.textContent = detail.label
    box.hidden = false
    setTimeout(() => (box.hidden = true), detail.display_ms)
  })
</script>

What the viewer sees ​

A play button first. Then play and pause, a live badge for a live stream, mute, a quality menu, picture in picture where the browser has it, and full screen. The quality menu has Auto and Data saver, and adds Audio only when the stream has an audio-only rendition. The controls fade out while the video plays and come back on any movement, touch or key.

When playback stops, the player says why. These are the main messages:

CaseEnglishKiswahili
Replaced by another devicePlaying on another deviceInacheza kwenye kifaa kingine
Access endedYour access has endedUfikiaji wako umeisha
Connection lost, or every source failedCheck your connectionAngalia muunganisho wako

There are also messages for the device limit, no views left, a video that is not available and a browser that cannot play HLS. A replaced session offers "Watch here" and a connection problem or an unexpected error offers "Try again". The others are for your page to explain, for example with a link to buy.

Everything works with the keyboard. k or space plays and pauses, m mutes, f toggles full screen, arrow keys move in the quality menu and Escape closes it. Animation stops when the viewer prefers reduced motion.

Make it look like yours ​

The player is dark, because it sits on video. The coral accent and the other tokens are CSS custom properties. Set them on the tag:

css
vabu-player {
  --vabu-accent: #1f7a4d;
  --vabu-radius: 4px;
}
PropertyDefaultUsed for
--vabu-accent#ff6b57The play button, the selected menu item and the moment toast's edge.
--vabu-surfacergba(10, 10, 10, 0.86)The control bar, the menu, the toast and error panel.
--vabu-surface-hoverrgba(255, 255, 255, 0.12)A hovered button.
--vabu-text#f5f5f7Text and icons.
--vabu-text-muted#c7c7ccSecond lines of text.
--vabu-live#ef4444The live badge.
--vabu-radius8pxCorners.
--vabu-fontInter, then the system fontAll text.

The tag is a block with a 16:9 shape. Set its width, and its aspect-ratio if you want another shape. The toast has part="moment", so vabu-player::part(moment) styles it too.

Try it in test mode ​

A test key never reaches a real provider, and a test stream has no video. The player opens a session, then tells you that nothing could be played. That is enough to check your key, your token route and your event handlers. The demo page in packages/elements/demo has fields for the key, the id and a token, and lists every event. Run it with pnpm --filter @vabu/elements dev and open /demo/.

In a framework ​

The element is a plain custom element. Set customerToken as a property, not an attribute.

tsx
// React
useEffect(() => {
  ref.current!.customerToken = () => fetch('/api/vabu-token').then((res) => res.text())
}, [])

return <vabu-player ref={ref} publishable-key="vpk_live_..." resource="ls_..." />

In a WebView, load a page of your own that holds the tag, and allow inline media playback (allowsInlineMediaPlayback on iOS, mediaPlaybackRequiresUserGesture = false on Android if you use autoplay).

Vabu OS by Vabu Group