npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@htmlbricks/hb-player-live

v0.76.5

Published

Live streaming `<video>` player for HLS (hls.js or native), WebSocket WebRTC (`simple-webrtc-element`), or WHEP (MediaMTX). Polls the manifest for HLS liveness, exposes the element via `getVideoElement`, and emits `liveStatus` and `htmlVideoInit`. When th

Downloads

7,629

Readme

hb-player-live — integrator guide

Category: media · Tags: media, video, streaming · Package: @htmlbricks/hb-player-live

Summary

Live streaming player built on a native <video> element. It supports HLS (via hls.js when Media Source Extensions are available, or the browser’s built-in HLS where supported), WebRTC over WebSocket (simple-webrtc-element), and WHEP (MediaMTXWebRTCReader for MediaMTX-style endpoints).

For HLS, the component periodically fetches the manifest URL to decide whether the source is reachable (“live” for overlay purposes). For WebRTC and WHEP, online/offline is driven by the underlying player callbacks, which also update liveStatus.

When the URI is missing, the stream is considered offline, or you force a cover state, the component can show a full-area overlay (default copy, replacewithtext JSON, and optional slots).

Custom element tag

<hb-player-live …></hb-player-live>

Attributes (snake_case; string values in HTML)

Web component attributes are always strings. Use yes / no for boolean-like flags where noted. Pass JSON as a single string for object props (for example replacewithtext='{"title":"…"}').

| Attribute | Required | Description | | --- | --- | --- | | mediauri | Yes | Stream endpoint: HLS playlist (.m3u8), WebSocket signaling URL for webrtc, or WHEP URL for whep. Use an empty string if you intentionally have no URI (placeholder state). | | media_type | No | Playback mode: hls, webrtc, whep, or auto (see Media type). Default in the implementation is auto. The <video> node is only rendered when both mediauri and media_type are non-empty. | | forcecover | No | Any non-empty value (commonly yes) forces the structured overlay when the conditions in the template are met (together with replacewithtext shape). | | replacewithtext | No | JSON string: { "title": string, "subtitle"?: string, "text"?: string }. Used for default overlay copy; the component also parses a string value into an object when possible. | | no_controls | No | Hide native <video> controls when set to any truthy value except the strings no or false (for example yes). | | id | No | Passed through on custom events and when exposing the video element. |

The authoring Component type also allows style; styling is normally done via CSS variables, ::part, and host layout.


Media type

Set media_type explicitly for working playback:

  • hls — Loads mediauri with hls.js (or assigns src on Safari / browsers that report native HLS support). Autoplay is attempted with muted video.
  • webrtc — Uses simple-webrtc-element with wsUri: mediauri on the bound <video>.
  • whep — Uses MediaMTXWebRTCReader with url: mediauri; the first stream track is assigned to video.srcObject.

The literal value auto appears in the public type union and is the Svelte default, but the internal setVideo path only wires hls, webrtc, and whep. Treat auto as reserved / not implemented for playback until a future version adds detection.


Live status and polling

  • hls: loadLive() performs a fetch(mediauri) on the manifest. A response in the 1xx–299 range sets internal “live” to true and dispatches liveStatus with live: true. On failure, it dispatches live: false and retries after 5 seconds (also when mediauri is empty).
  • webrtc / whep: liveStatus is dispatched from online/offline handlers in the respective integrations (live: true / live: false).

Overlay and fallback UI

The dark 16:9 surface uses Bulma variables --bulma-dark and --bulma-dark-invert (see Styling).

Rough behavior (see component.wc.svelte for exact conditions):

  1. forcecover is set, or mediauri is set, isLive is false, and replacewithtext includes at least one of title, subtitle, or text — shows the replacewithtext part with the default slot layout (one, two, or three lines depending on which JSON fields are present), unless you override the replacewithtext slot entirely.
  2. Otherwise, if there is a mediauri but the stream is not live and there is no replacewithtext copy — shows the literal offline label in the overlay.
  3. If there is no mediauri — shows nouri in the overlay.

If you supply the replacewithtext slot, you replace the entire default overlay markup for that branch; the inner slots (replacetitle, replacesubtitle, replacetext) only apply inside the default structure.


Events

Listen with addEventListener on the host element (names are camelCase in the type definitions).

| Event | detail (runtime) | | --- | --- | | liveStatus | { live: boolean; id: string } | | htmlVideoInit | { htmlVideoElement: HTMLVideoElement; id: string } — fired when the <video> is bound. |

TypeScript typings (authoring)

types/webcomponent.type.d.ts defines Component, Events (liveStatus, htmlVideoInit with htmlVideoElement), and nested shapes for replacewithtext.

Host API

After upgrade, the custom element exposes:

  • getVideoElement() — Returns the internal HTMLVideoElement when it exists, otherwise undefined.

Styling (CSS custom properties)

Set on the host or an ancestor. The video frame and overlay use Bulma dark tokens.

| Variable | Role | | --- | --- | | --bulma-dark | Background of the 16:9 video area and offline/cover overlay. | | --bulma-dark-invert | Foreground (text) on that surface. |

See Bulma CSS variables for theme-wide tuning.


CSS parts (::part(...))

| Part | Purpose | | --- | --- | | container | Root wrapper around the player and overlay; sizing and positioning of the whole component. | | replacewithtext | Full-bleed overlay when the stream is missing, not live, forcecover applies, or placeholder copy is shown. | | video | The native <video> element (streaming surface, native controls when enabled). |


HTML slots

| Slot | When it matters | Purpose | | --- | --- | --- | | replacewithtext | Overlay branch with default structure | Replace the entire offline/cover layout. If you fill this slot, the default grid and nested slots are not used unless you reintroduce them in your markup. | | replacetitle | Default overlay only | Title line; falls back to replacewithtext.title. | | replacesubtitle | Default overlay (two- or three-line layout) | Subtitle line; falls back to replacewithtext.subtitle when the prop defines both title and subtitle. | | replacetext | Default three-line layout | Body copy; falls back to replacewithtext.text. |


Usage notes

  • Autoplay: The implementation sets muted and calls play() where possible; browser policies may still block autoplay with sound or without user gesture.
  • Changing mediauri: When the URI changes, WHEP readers are closed, live state is reset, and the video is reinitialized.
  • Accessibility: The markup includes a captions <track> placeholder; provide real captions/tracks in your integration if you need accessibility compliance.

Examples

HLS (public test stream)

<hb-player-live
  mediauri="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
  media_type="hls"
></hb-player-live>

WHEP endpoint (replace with your server URL)

<hb-player-live
  mediauri="https://example.com/path/to/whep"
  media_type="whep"
></hb-player-live>

Forced cover with JSON copy (replacewithtext must be a valid JSON string attribute)

<hb-player-live
  mediauri="https://example.com/stream/whep"
  media_type="whep"
  forcecover="yes"
  replacewithtext='{"title":"Stream paused","subtitle":"We will be back soon","text":"Thank you for waiting."}'
></hb-player-live>

Hide native controls

<hb-player-live
  mediauri="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
  media_type="hls"
  no_controls="yes"
></hb-player-live>

Listen for live state and grab the video element

<hb-player-live
  id="cam1"
  mediauri="https://example.com/live.m3u8"
  media_type="hls"
></hb-player-live>
<script>
  const el = document.querySelector("#cam1");
  el.addEventListener("liveStatus", (e) => {
    console.log(e.detail.live, e.detail.id);
  });
  el.addEventListener("htmlVideoInit", (e) => {
    console.log(e.detail.htmlVideoElement, e.detail.id);
  });
  customElements.whenDefined("hb-player-live").then(() => {
    const v = el.getVideoElement?.();
    if (v) console.log("video", v);
  });
</script>