streamit-player 1.0.0
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/CHANGELOG.md +35 -0
- package/LICENSE +203 -0
- package/README.md +552 -0
- package/dist/Player-BfmqCREY.cjs +11616 -0
- package/dist/Player-YpukGRGt.js +11617 -0
- package/dist/PlayerController-Bt7Po42U.cjs +14093 -0
- package/dist/PlayerController-CW0pxrIt.js +14072 -0
- package/dist/core/index.cjs +194 -0
- package/dist/core/index.js +194 -0
- package/dist/core/src/AdScheduler.d.ts +56 -0
- package/dist/core/src/AdScheduler.d.ts.map +1 -0
- package/dist/core/src/AdsController.d.ts +48 -0
- package/dist/core/src/AdsController.d.ts.map +1 -0
- package/dist/core/src/AdsManager.d.ts +181 -0
- package/dist/core/src/AdsManager.d.ts.map +1 -0
- package/dist/core/src/DrmManager.d.ts +162 -0
- package/dist/core/src/DrmManager.d.ts.map +1 -0
- package/dist/core/src/DrmValidator.d.ts +36 -0
- package/dist/core/src/DrmValidator.d.ts.map +1 -0
- package/dist/core/src/KeyboardManager.d.ts +73 -0
- package/dist/core/src/KeyboardManager.d.ts.map +1 -0
- package/dist/core/src/PictureInPictureManager.d.ts +47 -0
- package/dist/core/src/PictureInPictureManager.d.ts.map +1 -0
- package/dist/core/src/PlayerController.d.ts +231 -0
- package/dist/core/src/PlayerController.d.ts.map +1 -0
- package/dist/core/src/PlaylistManager.d.ts +63 -0
- package/dist/core/src/PlaylistManager.d.ts.map +1 -0
- package/dist/core/src/SourceManager.d.ts +142 -0
- package/dist/core/src/SourceManager.d.ts.map +1 -0
- package/dist/core/src/SubtitleManager.d.ts +77 -0
- package/dist/core/src/SubtitleManager.d.ts.map +1 -0
- package/dist/core/src/TimelineMath.d.ts +14 -0
- package/dist/core/src/TimelineMath.d.ts.map +1 -0
- package/dist/core/src/html-overlay/HtmlOverlayRenderer.d.ts +103 -0
- package/dist/core/src/html-overlay/HtmlOverlayRenderer.d.ts.map +1 -0
- package/dist/core/src/index.d.ts +21 -0
- package/dist/core/src/index.d.ts.map +1 -0
- package/dist/core/src/providers/ImaProvider.d.ts +135 -0
- package/dist/core/src/providers/ImaProvider.d.ts.map +1 -0
- package/dist/core/src/providers/ThumbnailProviders.d.ts +102 -0
- package/dist/core/src/providers/ThumbnailProviders.d.ts.map +1 -0
- package/dist/core/src/providers/VastProvider.d.ts +202 -0
- package/dist/core/src/providers/VastProvider.d.ts.map +1 -0
- package/dist/core/src/providers/VmapProvider.d.ts +98 -0
- package/dist/core/src/providers/VmapProvider.d.ts.map +1 -0
- package/dist/core/src/providers/fetchXmlWithPolicy.d.ts +9 -0
- package/dist/core/src/providers/fetchXmlWithPolicy.d.ts.map +1 -0
- package/dist/core/src/simid/SimidBridge.d.ts +44 -0
- package/dist/core/src/simid/SimidBridge.d.ts.map +1 -0
- package/dist/core/src/simid/SimidManager.d.ts +21 -0
- package/dist/core/src/simid/SimidManager.d.ts.map +1 -0
- package/dist/core/src/simid/SimidRuntime.d.ts +113 -0
- package/dist/core/src/simid/SimidRuntime.d.ts.map +1 -0
- package/dist/core/src/simid/SimidSession.d.ts +48 -0
- package/dist/core/src/simid/SimidSession.d.ts.map +1 -0
- package/dist/core/src/simid/types.d.ts +115 -0
- package/dist/core/src/simid/types.d.ts.map +1 -0
- package/dist/core/src/storage.d.ts +10 -0
- package/dist/core/src/storage.d.ts.map +1 -0
- package/dist/core/src/types.d.ts +1403 -0
- package/dist/core/src/types.d.ts.map +1 -0
- package/dist/core/src/utils.d.ts +34 -0
- package/dist/core/src/utils.d.ts.map +1 -0
- package/dist/core/src/vendorLoaders.d.ts +16 -0
- package/dist/core/src/vendorLoaders.d.ts.map +1 -0
- package/dist/index.cjs +55 -0
- package/dist/index.js +55 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/streamit-player.esm.js +26226 -0
- package/dist/streamit-player.esm.min.js +18830 -0
- package/dist/streamit-player.iife.js +26229 -0
- package/dist/streamit-player.iife.min.js +4750 -0
- package/dist/web-components/index.cjs +15 -0
- package/dist/web-components/index.js +15 -0
- package/dist/web-components/src/ChaptersButton.d.ts +27 -0
- package/dist/web-components/src/ChaptersButton.d.ts.map +1 -0
- package/dist/web-components/src/ChaptersButton.styles.d.ts +2 -0
- package/dist/web-components/src/ChaptersButton.styles.d.ts.map +1 -0
- package/dist/web-components/src/PlayButton.d.ts +17 -0
- package/dist/web-components/src/PlayButton.d.ts.map +1 -0
- package/dist/web-components/src/PlayButton.styles.d.ts +2 -0
- package/dist/web-components/src/PlayButton.styles.d.ts.map +1 -0
- package/dist/web-components/src/Player.d.ts +271 -0
- package/dist/web-components/src/Player.d.ts.map +1 -0
- package/dist/web-components/src/Player.styles.d.ts +2 -0
- package/dist/web-components/src/Player.styles.d.ts.map +1 -0
- package/dist/web-components/src/SeekButton.d.ts +18 -0
- package/dist/web-components/src/SeekButton.d.ts.map +1 -0
- package/dist/web-components/src/SeekButton.styles.d.ts +2 -0
- package/dist/web-components/src/SeekButton.styles.d.ts.map +1 -0
- package/dist/web-components/src/Seekbar.d.ts +101 -0
- package/dist/web-components/src/Seekbar.d.ts.map +1 -0
- package/dist/web-components/src/Seekbar.styles.d.ts +2 -0
- package/dist/web-components/src/Seekbar.styles.d.ts.map +1 -0
- package/dist/web-components/src/Themes.d.ts +5 -0
- package/dist/web-components/src/Themes.d.ts.map +1 -0
- package/dist/web-components/src/VerticalControls.d.ts +49 -0
- package/dist/web-components/src/VerticalControls.d.ts.map +1 -0
- package/dist/web-components/src/VerticalControls.styles.d.ts +2 -0
- package/dist/web-components/src/VerticalControls.styles.d.ts.map +1 -0
- package/dist/web-components/src/VolumeControl.d.ts +21 -0
- package/dist/web-components/src/VolumeControl.d.ts.map +1 -0
- package/dist/web-components/src/VolumeControl.styles.d.ts +2 -0
- package/dist/web-components/src/VolumeControl.styles.d.ts.map +1 -0
- package/dist/web-components/src/icons/IconRegistry.d.ts +24 -0
- package/dist/web-components/src/icons/IconRegistry.d.ts.map +1 -0
- package/dist/web-components/src/index.d.ts +10 -0
- package/dist/web-components/src/index.d.ts.map +1 -0
- package/dist/web-components/src/player-internals/GestureController.d.ts +140 -0
- package/dist/web-components/src/player-internals/GestureController.d.ts.map +1 -0
- package/dist/web-components/src/player-internals/PrefetchController.d.ts +34 -0
- package/dist/web-components/src/player-internals/PrefetchController.d.ts.map +1 -0
- package/dist/web-components/src/player-internals/SettingsMenuController.d.ts +59 -0
- package/dist/web-components/src/player-internals/SettingsMenuController.d.ts.map +1 -0
- package/dist/web-components/src/player-internals/ThumbnailCache.d.ts +64 -0
- package/dist/web-components/src/player-internals/ThumbnailCache.d.ts.map +1 -0
- package/package.json +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
# Streamit Player (`streamit-player`)
|
|
2
|
+
|
|
3
|
+
A high-performance, enterprise-grade video player SDK and Web Component for modern web applications. Featuring adaptive streaming (HLS & MPEG-DASH), multi-DRM protection (Widevine, PlayReady, FairPlay, ClearKey), comprehensive advertising monetization (VAST 2.0-4.2, VMAP, Google IMA, SIMID 1.0, HTML Overlays), Smart Seek filmstrip preview, live DVR, TikTok/Reels-style vertical feeds, and customizable glassmorphism theming.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📦 Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install streamit-player
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
npm (v7+) and pnpm also install the `hls.js` and `dashjs` peer dependencies automatically. With Yarn, add them yourself:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
yarn add streamit-player hls.js dashjs
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Both libraries are loaded on demand, only when an HLS or DASH source is played.
|
|
20
|
+
|
|
21
|
+
### CDN Installation (No Build Step)
|
|
22
|
+
|
|
23
|
+
#### Modern ESM (`<script type="module">`)
|
|
24
|
+
```html
|
|
25
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/streamit-player@1/dist/streamit-player.esm.min.js"></script>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
#### Classic Script (`IIFE` global `window.StreamitPlayer`)
|
|
29
|
+
```html
|
|
30
|
+
<script src="https://cdn.jsdelivr.net/npm/streamit-player@1/dist/streamit-player.iife.min.js"></script>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The CDN bundles download `hls.js` and `dash.js` from jsDelivr the first time an HLS or DASH source plays. To self-host them instead (for example under a strict Content-Security-Policy), load their script builds **before** the player. A page-level `window.Hls` / `window.dashjs` is always used when present:
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<script src="https://cdn.jsdelivr.net/npm/hls.js@1/dist/hls.min.js"></script>
|
|
37
|
+
<script src="https://cdn.jsdelivr.net/npm/dashjs@5/dist/modern/umd/dash.all.min.js"></script>
|
|
38
|
+
<script src="https://cdn.jsdelivr.net/npm/streamit-player@1/dist/streamit-player.iife.min.js"></script>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## ⚡ Quick Start
|
|
44
|
+
|
|
45
|
+
The fastest way to get a player on the page, with no JavaScript required. The source type is detected from the URL (`.m3u8` → HLS, `.mpd` → DASH, otherwise progressive video):
|
|
46
|
+
|
|
47
|
+
```html
|
|
48
|
+
<script src="https://cdn.jsdelivr.net/npm/streamit-player@1/dist/streamit-player.iife.min.js"></script>
|
|
49
|
+
|
|
50
|
+
<streamit-player
|
|
51
|
+
src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
|
52
|
+
poster="https://example.com/poster.jpg"
|
|
53
|
+
style="display: block; width: 100%; aspect-ratio: 16 / 9;"
|
|
54
|
+
></streamit-player>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Supported attributes include `src`, `poster`, `autoplay`, `muted`, `loop`, `playsinline`, `preload`, `crossorigin` and `captions`.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🚀 Package Architecture & Subpath Entry Points
|
|
62
|
+
|
|
63
|
+
The `streamit-player` package is distributed as a single npm package with clean, optimized subpath exports:
|
|
64
|
+
|
|
65
|
+
| Entry Point | Description | Lit / UI Included |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `streamit-player` | **Default / All-in-One**: Registers `<streamit-player>` and `<player-player>` custom elements; exports `PlayerPlayer`, sub-components, and the full core API and types. | ✅ Yes |
|
|
68
|
+
| `streamit-player/core` | **Headless Playback Engine**: `PlayerController`, DRM manager, VAST/VMAP/IMA/SIMID ad engines, thumbnail providers, and all types. | ❌ **Zero Lit / UI** |
|
|
69
|
+
| `streamit-player/web-components` | **Lit Web Component Layer**: `<streamit-player>`, theme presets (`THEME_PRESETS`, `compileTheme`), icon registry (`renderIcon`), and sub-components. | ✅ Yes |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## ⚙️ Configuration, Sources & Events
|
|
74
|
+
|
|
75
|
+
Configuration is a flat object assigned to the element's `config` **property** (not an attribute). Sources are loaded with `loadSource()` (or `loadPlaylist()` for several items):
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
const player = document.querySelector('streamit-player');
|
|
79
|
+
|
|
80
|
+
player.config = {
|
|
81
|
+
autoplay: false,
|
|
82
|
+
muted: false,
|
|
83
|
+
volume: 0.8,
|
|
84
|
+
poster: 'https://example.com/poster.jpg',
|
|
85
|
+
theme: { preset: 'glass-dark' },
|
|
86
|
+
drm: { widevine: { licenseUrl: 'https://license.example.com/widevine' } },
|
|
87
|
+
ads: { enabled: true, provider: 'VAST', tagUrl: 'https://example.com/vast.xml' },
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
player.loadSource({
|
|
91
|
+
type: 'hls', // 'hls' | 'dash' | 'mp4' | 'webm' | ...; detected from the URL when omitted
|
|
92
|
+
src: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
|
|
93
|
+
subtitles: [{ src: '/subs/en.vtt', label: 'English', srclang: 'en', default: true }],
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Every player event is dispatched on the element as a bubbling `player-<name>` DOM event, with the payload in `event.detail`. You can also subscribe with `player.on()`:
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
player.addEventListener('player-play', () => console.log('Playback started'));
|
|
101
|
+
player.addEventListener('player-timeupdate', (e) => console.log('Time:', e.detail.currentTime));
|
|
102
|
+
|
|
103
|
+
player.on('ended', () => console.log('Finished'));
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For advanced control, `player.controllerInstance` returns the underlying headless `PlayerController`.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 🛠️ Multi-Framework Integration Recipes
|
|
111
|
+
|
|
112
|
+
### 1. Plain HTML5 & Vanilla JavaScript
|
|
113
|
+
|
|
114
|
+
#### Modern ESM (no build step)
|
|
115
|
+
```html
|
|
116
|
+
<!DOCTYPE html>
|
|
117
|
+
<html lang="en">
|
|
118
|
+
<head>
|
|
119
|
+
<meta charset="UTF-8">
|
|
120
|
+
<title>Streamit Player - Plain HTML</title>
|
|
121
|
+
<style>
|
|
122
|
+
.player-wrapper {
|
|
123
|
+
max-width: 960px;
|
|
124
|
+
margin: 40px auto;
|
|
125
|
+
aspect-ratio: 16 / 9;
|
|
126
|
+
}
|
|
127
|
+
streamit-player {
|
|
128
|
+
width: 100%;
|
|
129
|
+
height: 100%;
|
|
130
|
+
display: block;
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
133
|
+
</head>
|
|
134
|
+
<body>
|
|
135
|
+
<div class="player-wrapper">
|
|
136
|
+
<streamit-player id="my-player"></streamit-player>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<script type="module">
|
|
140
|
+
import 'https://cdn.jsdelivr.net/npm/streamit-player@1/dist/streamit-player.esm.min.js';
|
|
141
|
+
|
|
142
|
+
const player = document.getElementById('my-player');
|
|
143
|
+
player.config = {
|
|
144
|
+
poster: 'https://images.unsplash.com/photo-1536240478700-b869070f9279?w=1200',
|
|
145
|
+
autoplay: false,
|
|
146
|
+
muted: false,
|
|
147
|
+
theme: { preset: 'glass-dark' }
|
|
148
|
+
};
|
|
149
|
+
player.loadSource({
|
|
150
|
+
type: 'hls',
|
|
151
|
+
src: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8'
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
player.addEventListener('player-play', () => console.log('Playback started'));
|
|
155
|
+
player.addEventListener('player-timeupdate', (e) => console.log('Current time:', e.detail.currentTime));
|
|
156
|
+
</script>
|
|
157
|
+
</body>
|
|
158
|
+
</html>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
With a bundler (Vite, webpack, Rollup, …) use the package name instead: `import 'streamit-player';`.
|
|
162
|
+
|
|
163
|
+
#### Classic Script (IIFE)
|
|
164
|
+
```html
|
|
165
|
+
<script src="https://cdn.jsdelivr.net/npm/streamit-player@1/dist/streamit-player.iife.min.js"></script>
|
|
166
|
+
<streamit-player id="classic-player" style="width: 100%; aspect-ratio: 16/9; display: block;"></streamit-player>
|
|
167
|
+
<script>
|
|
168
|
+
var player = document.getElementById('classic-player');
|
|
169
|
+
player.loadSource({
|
|
170
|
+
type: 'mp4',
|
|
171
|
+
src: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'
|
|
172
|
+
});
|
|
173
|
+
</script>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### 2. React (18 & 19)
|
|
179
|
+
|
|
180
|
+
Assign objects such as `config` through a `ref` (React 18 would otherwise stringify them into attributes), and listen for `player-*` events with `addEventListener`:
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
import { useEffect, useRef } from 'react';
|
|
184
|
+
import 'streamit-player';
|
|
185
|
+
import type { PlayerPlayer, PlayerConfiguration, PlayerSource } from 'streamit-player';
|
|
186
|
+
|
|
187
|
+
export interface StreamitVideoPlayerProps {
|
|
188
|
+
src: string;
|
|
189
|
+
type?: PlayerSource['type'];
|
|
190
|
+
config?: PlayerConfiguration;
|
|
191
|
+
onPlay?: () => void;
|
|
192
|
+
className?: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function StreamitVideoPlayer({ src, type, config, onPlay, className }: StreamitVideoPlayerProps) {
|
|
196
|
+
const playerRef = useRef<PlayerPlayer>(null);
|
|
197
|
+
|
|
198
|
+
useEffect(() => {
|
|
199
|
+
if (playerRef.current && config) playerRef.current.config = config;
|
|
200
|
+
}, [config]);
|
|
201
|
+
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
playerRef.current?.loadSource({ src, type });
|
|
204
|
+
}, [src, type]);
|
|
205
|
+
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
const el = playerRef.current;
|
|
208
|
+
if (!el || !onPlay) return;
|
|
209
|
+
el.addEventListener('player-play', onPlay);
|
|
210
|
+
return () => el.removeEventListener('player-play', onPlay);
|
|
211
|
+
}, [onPlay]);
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<streamit-player
|
|
215
|
+
ref={playerRef}
|
|
216
|
+
className={className}
|
|
217
|
+
style={{ display: 'block', width: '100%', aspectRatio: '16 / 9' }}
|
|
218
|
+
/>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
In React 19 you can also pass `config={config}` directly, because React 19 sets it as a property.
|
|
224
|
+
|
|
225
|
+
#### TypeScript: declaring the JSX element
|
|
226
|
+
|
|
227
|
+
TypeScript doesn't know about custom elements in JSX until you declare them. Add this file anywhere in your project (e.g. `src/streamit-player.d.ts`):
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
import type { DetailedHTMLProps, HTMLAttributes } from 'react';
|
|
231
|
+
import type { PlayerPlayer } from 'streamit-player';
|
|
232
|
+
|
|
233
|
+
declare module 'react' {
|
|
234
|
+
namespace JSX {
|
|
235
|
+
interface IntrinsicElements {
|
|
236
|
+
'streamit-player': DetailedHTMLProps<HTMLAttributes<PlayerPlayer>, PlayerPlayer> & {
|
|
237
|
+
src?: string;
|
|
238
|
+
poster?: string;
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### 3. Next.js (App Router & Pages Router)
|
|
248
|
+
|
|
249
|
+
The player registers custom elements when imported, so load it in the browser only, inside the `useEffect` of a client component:
|
|
250
|
+
|
|
251
|
+
#### Component (`components/StreamitPlayerClient.tsx`)
|
|
252
|
+
```tsx
|
|
253
|
+
'use client';
|
|
254
|
+
|
|
255
|
+
import { useEffect, useRef } from 'react';
|
|
256
|
+
import type { PlayerPlayer, PlayerConfiguration } from 'streamit-player';
|
|
257
|
+
|
|
258
|
+
export default function StreamitPlayerClient({ src, config }: { src: string; config?: PlayerConfiguration }) {
|
|
259
|
+
const playerRef = useRef<PlayerPlayer>(null);
|
|
260
|
+
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
let cancelled = false;
|
|
263
|
+
import('streamit-player').then(() => {
|
|
264
|
+
const el = playerRef.current;
|
|
265
|
+
if (cancelled || !el) return;
|
|
266
|
+
if (config) el.config = config;
|
|
267
|
+
el.loadSource({ src });
|
|
268
|
+
});
|
|
269
|
+
return () => {
|
|
270
|
+
cancelled = true;
|
|
271
|
+
};
|
|
272
|
+
}, [src, config]);
|
|
273
|
+
|
|
274
|
+
return (
|
|
275
|
+
<streamit-player
|
|
276
|
+
ref={playerRef}
|
|
277
|
+
style={{ display: 'block', width: '100%', aspectRatio: '16 / 9', borderRadius: '12px', overflow: 'hidden' }}
|
|
278
|
+
/>
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
#### App Router Page (`app/watch/page.tsx`)
|
|
284
|
+
```tsx
|
|
285
|
+
import StreamitPlayerClient from '@/components/StreamitPlayerClient';
|
|
286
|
+
|
|
287
|
+
export default function WatchPage() {
|
|
288
|
+
return (
|
|
289
|
+
<main style={{ maxWidth: '1100px', margin: '40px auto', padding: '0 20px' }}>
|
|
290
|
+
<h1>Now Watching</h1>
|
|
291
|
+
<StreamitPlayerClient
|
|
292
|
+
src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
|
293
|
+
config={{ autoplay: true, muted: true, theme: { preset: 'glass-dark' } }}
|
|
294
|
+
/>
|
|
295
|
+
</main>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
The same component works unchanged in the Pages Router. Add the JSX declaration from the React section for TypeScript.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
### 4. Laravel (Blade with Vite)
|
|
305
|
+
|
|
306
|
+
1. **Install and import in your Vite entry point (`resources/js/app.js`):**
|
|
307
|
+
```javascript
|
|
308
|
+
import './bootstrap';
|
|
309
|
+
import 'streamit-player';
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
2. **Render the custom element in your Blade view (`resources/views/watch.blade.php`):**
|
|
313
|
+
```html
|
|
314
|
+
@extends('layouts.app')
|
|
315
|
+
|
|
316
|
+
@section('content')
|
|
317
|
+
<div class="max-w-5xl mx-auto py-8">
|
|
318
|
+
<h1 class="text-2xl font-bold mb-4">{{ $video->title }}</h1>
|
|
319
|
+
|
|
320
|
+
<div class="rounded-xl overflow-hidden shadow-2xl aspect-video bg-black">
|
|
321
|
+
<streamit-player
|
|
322
|
+
src="{{ $video->stream_url }}"
|
|
323
|
+
poster="{{ $video->poster_url }}"
|
|
324
|
+
style="display:block;width:100%;height:100%"
|
|
325
|
+
></streamit-player>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
@endsection
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
To pass a full `config` object from a script, wait until the element is registered:
|
|
332
|
+
|
|
333
|
+
```javascript
|
|
334
|
+
customElements.whenDefined('streamit-player').then(() => {
|
|
335
|
+
document.querySelector('streamit-player').config = { volume: 0.8, theme: { preset: 'glass-dark' } };
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### 5. Vue 3 (incl. Laravel Inertia)
|
|
342
|
+
|
|
343
|
+
Tell Vue that `streamit-*` tags are custom elements (`vite.config.js`):
|
|
344
|
+
|
|
345
|
+
```javascript
|
|
346
|
+
import vue from '@vitejs/plugin-vue';
|
|
347
|
+
|
|
348
|
+
export default {
|
|
349
|
+
plugins: [
|
|
350
|
+
vue({
|
|
351
|
+
template: {
|
|
352
|
+
compilerOptions: { isCustomElement: (tag) => tag.startsWith('streamit-') },
|
|
353
|
+
},
|
|
354
|
+
}),
|
|
355
|
+
],
|
|
356
|
+
};
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Then use the element in a component (`resources/js/Pages/Watch.vue`):
|
|
360
|
+
|
|
361
|
+
```html
|
|
362
|
+
<template>
|
|
363
|
+
<div class="player-container aspect-video w-full rounded-2xl overflow-hidden">
|
|
364
|
+
<streamit-player
|
|
365
|
+
ref="playerRef"
|
|
366
|
+
:config.prop="config"
|
|
367
|
+
style="display:block;width:100%;height:100%"
|
|
368
|
+
@player-play="onPlay"
|
|
369
|
+
@player-timeupdate="onTimeUpdate"
|
|
370
|
+
/>
|
|
371
|
+
</div>
|
|
372
|
+
</template>
|
|
373
|
+
|
|
374
|
+
<script setup>
|
|
375
|
+
import { ref, onMounted, watch } from 'vue';
|
|
376
|
+
import 'streamit-player';
|
|
377
|
+
|
|
378
|
+
const props = defineProps({
|
|
379
|
+
video: Object
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const playerRef = ref(null);
|
|
383
|
+
const config = { autoplay: false, muted: false, theme: { preset: 'glass-dark' } };
|
|
384
|
+
|
|
385
|
+
const loadVideo = () => {
|
|
386
|
+
playerRef.value?.loadSource({ src: props.video.url, type: props.video.type });
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
onMounted(loadVideo);
|
|
390
|
+
watch(() => props.video, loadVideo, { deep: true });
|
|
391
|
+
|
|
392
|
+
const onPlay = () => console.log('Playback started');
|
|
393
|
+
const onTimeUpdate = (e) => console.log('Time:', e.detail.currentTime);
|
|
394
|
+
</script>
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
### 6. WordPress (Classic PHP & Gutenberg)
|
|
400
|
+
|
|
401
|
+
#### WordPress Classic Theme / Shortcode (`functions.php`)
|
|
402
|
+
```php
|
|
403
|
+
<?php
|
|
404
|
+
// Enqueue the Streamit Player IIFE bundle from the CDN
|
|
405
|
+
function streamit_player_register_assets() {
|
|
406
|
+
wp_register_script(
|
|
407
|
+
'streamit-player',
|
|
408
|
+
'https://cdn.jsdelivr.net/npm/streamit-player@1/dist/streamit-player.iife.min.js',
|
|
409
|
+
array(),
|
|
410
|
+
null,
|
|
411
|
+
true
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
add_action('wp_enqueue_scripts', 'streamit_player_register_assets');
|
|
415
|
+
|
|
416
|
+
// Register the [streamit_player src="..." poster="..." autoplay="true"] shortcode
|
|
417
|
+
function streamit_player_shortcode($atts) {
|
|
418
|
+
wp_enqueue_script('streamit-player');
|
|
419
|
+
|
|
420
|
+
$atts = shortcode_atts(array(
|
|
421
|
+
'src' => '',
|
|
422
|
+
'poster' => '',
|
|
423
|
+
'autoplay' => 'false',
|
|
424
|
+
), $atts, 'streamit_player');
|
|
425
|
+
|
|
426
|
+
// Browsers only allow autoplay when muted
|
|
427
|
+
$autoplay = $atts['autoplay'] === 'true' ? ' autoplay muted' : '';
|
|
428
|
+
|
|
429
|
+
return sprintf(
|
|
430
|
+
'<div style="width:100%%;max-width:960px;margin:20px auto;aspect-ratio:16/9;">'
|
|
431
|
+
. '<streamit-player src="%s" poster="%s"%s style="display:block;width:100%%;height:100%%;"></streamit-player>'
|
|
432
|
+
. '</div>',
|
|
433
|
+
esc_url($atts['src']),
|
|
434
|
+
esc_url($atts['poster']),
|
|
435
|
+
$autoplay
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
add_shortcode('streamit_player', 'streamit_player_shortcode');
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
#### WordPress Gutenberg Custom HTML Block
|
|
442
|
+
Paste directly into a Gutenberg **Custom HTML** block:
|
|
443
|
+
```html
|
|
444
|
+
<script src="https://cdn.jsdelivr.net/npm/streamit-player@1/dist/streamit-player.iife.min.js"></script>
|
|
445
|
+
|
|
446
|
+
<div style="width: 100%; aspect-ratio: 16/9; max-width: 900px; margin: 0 auto; border-radius: 12px; overflow: hidden;">
|
|
447
|
+
<streamit-player
|
|
448
|
+
src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
|
449
|
+
style="width: 100%; height: 100%; display: block;"
|
|
450
|
+
></streamit-player>
|
|
451
|
+
</div>
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
### 7. Headless & Core-Only TypeScript (Zero Lit / Custom UI)
|
|
457
|
+
|
|
458
|
+
Build your own bespoke UI around the headless engine without including any Lit or Web Component DOM overhead:
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
import { PlayerController } from 'streamit-player/core';
|
|
462
|
+
import type { PlayerConfiguration, PlayerState } from 'streamit-player/core';
|
|
463
|
+
|
|
464
|
+
// Reference your existing HTML5 <video> element
|
|
465
|
+
const videoElement = document.getElementById('my-video') as HTMLVideoElement;
|
|
466
|
+
|
|
467
|
+
const config: PlayerConfiguration = {
|
|
468
|
+
autoplay: false,
|
|
469
|
+
drm: {
|
|
470
|
+
widevine: {
|
|
471
|
+
licenseUrl: 'https://license.widevine.com/cenc/getlicense'
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
ads: {
|
|
475
|
+
enabled: true,
|
|
476
|
+
provider: 'VAST',
|
|
477
|
+
tagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?iu=...'
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// Initialize headless engine
|
|
482
|
+
const controller = new PlayerController(videoElement, config);
|
|
483
|
+
|
|
484
|
+
// Subscribe to state changes (returns an unsubscribe function)
|
|
485
|
+
const unsubscribe = controller.onStateChange((state: PlayerState) => {
|
|
486
|
+
console.log('Status:', state.status, '| playing:', state.isPlaying);
|
|
487
|
+
console.log('Position:', state.currentTime, '/', state.duration);
|
|
488
|
+
console.log('Quality levels:', state.qualities);
|
|
489
|
+
console.log('Audio tracks:', state.audioTracks);
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// Load a source and control playback
|
|
493
|
+
controller.loadSource({
|
|
494
|
+
type: 'hls',
|
|
495
|
+
src: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8'
|
|
496
|
+
});
|
|
497
|
+
controller.play();
|
|
498
|
+
controller.seek(45.5);
|
|
499
|
+
controller.setVolume(0.75);
|
|
500
|
+
|
|
501
|
+
// Teardown when done
|
|
502
|
+
// unsubscribe();
|
|
503
|
+
// controller.destroy();
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## 🎨 Theming & CSS Custom Properties
|
|
509
|
+
|
|
510
|
+
Streamit Player ships four theme presets (`glass-dark`, `glass-light`, `dark`, `light`). Pick one and override individual values through `config.theme`:
|
|
511
|
+
|
|
512
|
+
```js
|
|
513
|
+
player.config = {
|
|
514
|
+
theme: {
|
|
515
|
+
preset: 'glass-dark',
|
|
516
|
+
primaryColor: '#3b82f6',
|
|
517
|
+
accentColor: '#60a5fa',
|
|
518
|
+
borderRadius: '12px',
|
|
519
|
+
fontFamily: "'Inter', system-ui, sans-serif",
|
|
520
|
+
// Any CSS custom property can be set directly:
|
|
521
|
+
customVariables: { '--player-seekbar-played': '#3b82f6' }
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
Without a `theme` object you can style the player from your own CSS with its `--player-*` custom properties (more than 60 are available):
|
|
527
|
+
|
|
528
|
+
```css
|
|
529
|
+
streamit-player {
|
|
530
|
+
--player-primary-color: #3b82f6;
|
|
531
|
+
--player-accent-color: #60a5fa;
|
|
532
|
+
--player-seekbar-played: #3b82f6;
|
|
533
|
+
--player-seekbar-buffer: rgba(255, 255, 255, 0.4);
|
|
534
|
+
--player-glass-blur: 16px;
|
|
535
|
+
--player-border-radius: 12px;
|
|
536
|
+
--player-font-family: 'Inter', system-ui, sans-serif;
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
Values from `config.theme` are written inline on the element, so they take precedence over stylesheet rules.
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
## 🏷️ Tag Name Aliases
|
|
545
|
+
|
|
546
|
+
`<player-player>` and all `player-*` sub-component tag names (`<player-play-button>`, `<player-seekbar>`, `<player-volume-control>`, etc.) are registered as aliases of their `streamit-*` equivalents.
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
## 📄 License
|
|
551
|
+
|
|
552
|
+
[Apache-2.0](./LICENSE)
|