@htmlbricks/hb-player-live 0.71.34 → 0.71.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -18
- package/manifest.json +36 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,36 +1,136 @@
|
|
|
1
|
-
|
|
1
|
+
# `hb-player-live`
|
|
2
2
|
|
|
3
3
|
**Category:** media
|
|
4
4
|
**Tags:** media, video, streaming
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Live streaming player built on a native `<video>` element. It supports **HLS** (via [hls.js](https://github.com/video-dev/hls.js/) when Media Source Extensions are available, or the browser’s built-in HLS where supported), **WebRTC over WebSocket** ([`simple-webrtc-element`](https://www.npmjs.com/package/simple-webrtc-element)), and **WHEP** ([`MediaMTXWebRTCReader`](https://www.npmjs.com/package/simple-webrtc-element-whep) for MediaMTX-style endpoints).
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
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`.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
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).
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Custom element
|
|
11
15
|
|
|
12
16
|
`hb-player-live`
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Attributes (snake_case; string values in HTML)
|
|
21
|
+
|
|
22
|
+
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":"…"}'`).
|
|
23
|
+
|
|
24
|
+
| Attribute | Required | Description |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| `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). |
|
|
27
|
+
| `media_type` | No | Playback mode: `hls`, `webrtc`, `whep`, or `auto` (see [Media type](#media-type)). Default in the implementation is `auto`. The `<video>` node is only rendered when both `mediauri` and `media_type` are non-empty. |
|
|
28
|
+
| `forcecover` | No | Any non-empty value (commonly `yes`) forces the structured overlay when the conditions in the template are met (together with `replacewithtext` shape). |
|
|
29
|
+
| `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. |
|
|
30
|
+
| `no_controls` | No | Hide native `<video>` controls when set to any truthy value except the strings `no` or `false` (for example `yes`). |
|
|
31
|
+
| `id` | No | Passed through on custom events and when exposing the video element. |
|
|
32
|
+
|
|
33
|
+
The authoring `Component` type also allows `style`; styling is normally done via CSS variables, `::part`, and host layout.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Media type
|
|
38
|
+
|
|
39
|
+
Set `media_type` explicitly for working playback:
|
|
40
|
+
|
|
41
|
+
- **`hls`** — Loads `mediauri` with hls.js (or assigns `src` on Safari / browsers that report native HLS support). Autoplay is attempted with **muted** video.
|
|
42
|
+
- **`webrtc`** — Uses `simple-webrtc-element` with `wsUri: mediauri` on the bound `<video>`.
|
|
43
|
+
- **`whep`** — Uses `MediaMTXWebRTCReader` with `url: mediauri`; the first stream track is assigned to `video.srcObject`.
|
|
44
|
+
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Live status and polling
|
|
50
|
+
|
|
51
|
+
- **`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).
|
|
52
|
+
- **`webrtc` / `whep`**: `liveStatus` is dispatched from **online/offline** handlers in the respective integrations (`live: true` / `live: false`).
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Overlay and fallback UI
|
|
57
|
+
|
|
58
|
+
The dark **16:9** surface uses Bulma variables `--bulma-dark` and `--bulma-dark-invert` (see [Styling](#styling)).
|
|
59
|
+
|
|
60
|
+
Rough behavior (see `component.wc.svelte` for exact conditions):
|
|
61
|
+
|
|
62
|
+
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.
|
|
63
|
+
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.
|
|
64
|
+
3. If there is **no `mediauri`** — shows **`nouri`** in the overlay.
|
|
65
|
+
|
|
66
|
+
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.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Events
|
|
71
|
+
|
|
72
|
+
Listen with `addEventListener` on the host element (names are camelCase in the type definitions).
|
|
73
|
+
|
|
74
|
+
| Event | `detail` (runtime) |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| `liveStatus` | `{ live: boolean; id: string }` |
|
|
77
|
+
| `htmlVideoInit` | `{ htmlVideoElement: HTMLVideoElement; id: string }` — fired when the `<video>` is bound. The authoring `Events` type may use a `video` field name; the implementation uses **`htmlVideoElement`**. |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Host API
|
|
82
|
+
|
|
83
|
+
After upgrade, the custom element exposes:
|
|
84
|
+
|
|
85
|
+
- **`getVideoElement()`** — Returns the internal `HTMLVideoElement` when it exists, otherwise `undefined`.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Styling (CSS custom properties)
|
|
90
|
+
|
|
91
|
+
Set on the host or an ancestor. The video frame and overlay use Bulma dark tokens.
|
|
92
|
+
|
|
93
|
+
| Variable | Role |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| `--bulma-dark` | Background of the 16:9 video area and offline/cover overlay. |
|
|
96
|
+
| `--bulma-dark-invert` | Foreground (text) on that surface. |
|
|
97
|
+
|
|
98
|
+
See [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/) for theme-wide tuning.
|
|
15
99
|
|
|
16
|
-
|
|
17
|
-
- `mediauri` (required): string — stream URL (HLS, WebRTC, WHEP as configured).
|
|
18
|
-
- `media_type` (optional): `"hls"` | `"webrtc"` | `"auto"` | `"whep"` (empty string allowed in examples).
|
|
19
|
-
- `forcecover` (optional): string — e.g. `"yes"` to force cover layout with placeholder text.
|
|
20
|
-
- `replacewithtext` (optional): JSON string — `{ title; subtitle?; text? }` when offline.
|
|
21
|
-
- `no_controls` (optional): boolean string — hide native/custom controls.
|
|
100
|
+
---
|
|
22
101
|
|
|
23
|
-
|
|
102
|
+
## CSS parts (`::part(...)`)
|
|
24
103
|
|
|
25
|
-
|
|
26
|
-
|
|
104
|
+
| Part | Purpose |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `container` | Root wrapper around the player and overlay; sizing and positioning of the whole component. |
|
|
107
|
+
| `replacewithtext` | Full-bleed overlay when the stream is missing, not live, `forcecover` applies, or placeholder copy is shown. |
|
|
108
|
+
| `video` | The native `<video>` element (streaming surface, native controls when enabled). |
|
|
27
109
|
|
|
28
|
-
|
|
110
|
+
---
|
|
29
111
|
|
|
30
|
-
|
|
31
|
-
- Pick `media_type` to match your pipeline (`whep` for WHEP examples in docs).
|
|
112
|
+
## HTML slots
|
|
32
113
|
|
|
33
|
-
|
|
114
|
+
| Slot | When it matters | Purpose |
|
|
115
|
+
| --- | --- | --- |
|
|
116
|
+
| `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. |
|
|
117
|
+
| `replacetitle` | Default overlay only | Title line; falls back to `replacewithtext.title`. |
|
|
118
|
+
| `replacesubtitle` | Default overlay (two- or three-line layout) | Subtitle line; falls back to `replacewithtext.subtitle` when the prop defines both title and subtitle. |
|
|
119
|
+
| `replacetext` | Default three-line layout | Body copy; falls back to `replacewithtext.text`. |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Usage notes
|
|
124
|
+
|
|
125
|
+
- **Autoplay**: The implementation sets **`muted`** and calls **`play()`** where possible; browser policies may still block autoplay with sound or without user gesture.
|
|
126
|
+
- **Changing `mediauri`**: When the URI changes, WHEP readers are closed, live state is reset, and the video is reinitialized.
|
|
127
|
+
- **Accessibility**: The markup includes a captions `<track>` placeholder; provide real captions/tracks in your integration if you need accessibility compliance.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Examples
|
|
132
|
+
|
|
133
|
+
**HLS (public test stream)**
|
|
34
134
|
|
|
35
135
|
```html
|
|
36
136
|
<hb-player-live
|
|
@@ -38,3 +138,56 @@ Live streaming `<video>` player for HLS (hls.js or native), WebSocket WebRTC (`s
|
|
|
38
138
|
media_type="hls"
|
|
39
139
|
></hb-player-live>
|
|
40
140
|
```
|
|
141
|
+
|
|
142
|
+
**WHEP endpoint** (replace with your server URL)
|
|
143
|
+
|
|
144
|
+
```html
|
|
145
|
+
<hb-player-live
|
|
146
|
+
mediauri="https://example.com/path/to/whep"
|
|
147
|
+
media_type="whep"
|
|
148
|
+
></hb-player-live>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Forced cover with JSON copy** (`replacewithtext` must be a valid JSON string attribute)
|
|
152
|
+
|
|
153
|
+
```html
|
|
154
|
+
<hb-player-live
|
|
155
|
+
mediauri="https://example.com/stream/whep"
|
|
156
|
+
media_type="whep"
|
|
157
|
+
forcecover="yes"
|
|
158
|
+
replacewithtext='{"title":"Stream paused","subtitle":"We will be back soon","text":"Thank you for waiting."}'
|
|
159
|
+
></hb-player-live>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Hide native controls**
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<hb-player-live
|
|
166
|
+
mediauri="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
|
167
|
+
media_type="hls"
|
|
168
|
+
no_controls="yes"
|
|
169
|
+
></hb-player-live>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Listen for live state and grab the video element**
|
|
173
|
+
|
|
174
|
+
```html
|
|
175
|
+
<hb-player-live
|
|
176
|
+
id="cam1"
|
|
177
|
+
mediauri="https://example.com/live.m3u8"
|
|
178
|
+
media_type="hls"
|
|
179
|
+
></hb-player-live>
|
|
180
|
+
<script>
|
|
181
|
+
const el = document.querySelector("#cam1");
|
|
182
|
+
el.addEventListener("liveStatus", (e) => {
|
|
183
|
+
console.log(e.detail.live, e.detail.id);
|
|
184
|
+
});
|
|
185
|
+
el.addEventListener("htmlVideoInit", (e) => {
|
|
186
|
+
console.log(e.detail.htmlVideoElement, e.detail.id);
|
|
187
|
+
});
|
|
188
|
+
customElements.whenDefined("hb-player-live").then(() => {
|
|
189
|
+
const v = el.getVideoElement?.();
|
|
190
|
+
if (v) console.log("video", v);
|
|
191
|
+
});
|
|
192
|
+
</script>
|
|
193
|
+
```
|
package/manifest.json
CHANGED
|
@@ -146,24 +146,54 @@
|
|
|
146
146
|
}
|
|
147
147
|
},
|
|
148
148
|
"styleSetup": {
|
|
149
|
-
"vars": [
|
|
149
|
+
"vars": [
|
|
150
|
+
{
|
|
151
|
+
"name": "--bulma-dark",
|
|
152
|
+
"valueType": "color",
|
|
153
|
+
"defaultValue": "",
|
|
154
|
+
"description": "Background of the 16:9 video area and offline/cover overlay; pair with `--bulma-dark-invert` for readable contrast."
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"name": "--bulma-dark-invert",
|
|
158
|
+
"valueType": "color",
|
|
159
|
+
"defaultValue": "",
|
|
160
|
+
"description": "Foreground (text) color on the dark video/placeholder surface."
|
|
161
|
+
}
|
|
162
|
+
],
|
|
150
163
|
"parts": [
|
|
151
164
|
{
|
|
152
165
|
"name": "container",
|
|
153
|
-
"description": ""
|
|
166
|
+
"description": "Root wrapper around the player and overlay; use for layout, sizing, or positioning the whole component."
|
|
154
167
|
},
|
|
155
168
|
{
|
|
156
169
|
"name": "replacewithtext",
|
|
157
|
-
"description": ""
|
|
170
|
+
"description": "Full-bleed overlay shown when `forcecover` is set, the stream is not live, or there is no URI; contains default copy or slotted content."
|
|
158
171
|
},
|
|
159
172
|
{
|
|
160
173
|
"name": "video",
|
|
161
|
-
"description": ""
|
|
174
|
+
"description": "The native `<video>` element (HLS / WebRTC / WHEP); style dimensions, object-fit, or controls appearance from the host page."
|
|
162
175
|
}
|
|
163
176
|
]
|
|
164
177
|
},
|
|
165
178
|
"contributors": [],
|
|
166
|
-
"htmlSlots": [
|
|
179
|
+
"htmlSlots": [
|
|
180
|
+
{
|
|
181
|
+
"name": "replacewithtext",
|
|
182
|
+
"description": "Replaces the entire offline/cover layout when shown. Use for custom markup; inner slots (`replacetitle`, `replacesubtitle`, `replacetext`) only apply inside the default structure when you do not override this slot."
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"name": "replacetitle",
|
|
186
|
+
"description": "Heading line in the default overlay; falls back to `replacewithtext.title` from the JSON prop when empty."
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"name": "replacesubtitle",
|
|
190
|
+
"description": "Secondary line in the default overlay; falls back to `replacewithtext.subtitle` when empty (only when both title and subtitle are defined in props)."
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"name": "replacetext",
|
|
194
|
+
"description": "Body copy in the default overlay; falls back to `replacewithtext.text` when empty (three-line layout only)."
|
|
195
|
+
}
|
|
196
|
+
],
|
|
167
197
|
"i18n": [],
|
|
168
198
|
"examples": [
|
|
169
199
|
{
|
|
@@ -247,5 +277,5 @@
|
|
|
247
277
|
"size": {},
|
|
248
278
|
"iifePath": "main.iife.js",
|
|
249
279
|
"repoName": "@htmlbricks/hb-player-live",
|
|
250
|
-
"version": "0.71.
|
|
280
|
+
"version": "0.71.36"
|
|
251
281
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@htmlbricks/hb-player-live",
|
|
3
|
-
"version": "0.71.
|
|
3
|
+
"version": "0.71.36",
|
|
4
4
|
"contributors": [],
|
|
5
5
|
"description": "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 the stream is offline or missing, shows optional title/subtitle/text from `replacewithtext`, `forcecover`, or fallback labels.",
|
|
6
6
|
"licenses": [
|