@viostream/viostream-player-svelte 0.1.2 → 0.2.1

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 CHANGED
@@ -1,456 +1,414 @@
1
- # viostream-player-svelte
2
-
3
- Svelte 5 SDK for the [Viostream](https://www.viostream.com) video player. Embed, control, and listen to player events with full TypeScript support.
4
-
5
- ## Requirements
6
-
7
- - Svelte 5
8
- - A Viostream account key (found on the **Settings > General** page in Viostream)
9
-
10
- ## Installation
11
-
12
- ```bash
13
- npm install viostream-player-svelte
14
- ```
15
-
16
- ## Quick Start
17
-
18
- ### Component
19
-
20
- Drop a `<ViostreamPlayer>` into any Svelte component. The SDK loads the Viostream script automatically.
21
-
22
- ```svelte
23
- <script lang="ts">
24
- import { ViostreamPlayer } from 'viostream-player-svelte';
25
- </script>
26
-
27
- <ViostreamPlayer
28
- accountKey="vc-100100100"
29
- publicKey="nhedxonrxsyfee"
30
- displayTitle={true}
31
- sharing={true}
32
- onplay={() => console.log('playing')}
33
- />
34
- ```
35
-
36
- ### Headless / Programmatic
37
-
38
- Use `createViostreamPlayer` when you need full control without a component:
39
-
40
- ```ts
41
- import { createViostreamPlayer } from 'viostream-player-svelte';
42
-
43
- const player = await createViostreamPlayer({
44
- accountKey: 'vc-100100100',
45
- publicKey: 'nhedxonrxsyfee',
46
- target: 'my-video-div', // element id or HTMLElement
47
- options: { displayTitle: true }
48
- });
49
-
50
- player.play();
51
- ```
52
-
53
- ---
54
-
55
- ## `<ViostreamPlayer>` Component
56
-
57
- ### Props
58
-
59
- #### Required
60
-
61
- | Prop | Type | Description |
62
- |---|---|---|
63
- | `accountKey` | `string` | Your Viostream account key (e.g. `'vc-100100100'`). |
64
- | `publicKey` | `string` | The public key of the media asset to embed. |
65
-
66
- #### Embed Options
67
-
68
- All embed options are optional and passed directly to the Viostream embed API.
69
-
70
- | Prop | Type | Description |
71
- |---|---|---|
72
- | `chapters` | `boolean` | Display chapter markers. |
73
- | `chapterDisplayType` | `'dropdown' \| 'progressbar' \| 'horizontal'` | Chapter display style. |
74
- | `chapterSlug` | `string` | Seek to a named chapter before playback. |
75
- | `displayTitle` | `boolean` | Show the video title overlay. |
76
- | `hlsQualitySelector` | `boolean` | Show the HLS quality selector. |
77
- | `playerKey` | `string` | Override the player theme to use. |
78
- | `sharing` | `boolean` | Show sharing controls. |
79
- | `speedSelector` | `boolean` | Show playback speed selector. |
80
- | `startEndTimespan` | `string` | Play a specific section (e.g. `'10,30'`). |
81
- | `startTime` | `string` | Seek to a time (seconds) before playback. |
82
- | `transcriptDownload` | `boolean` | Allow transcript download. |
83
-
84
- #### Event Callbacks
85
-
86
- | Prop | Signature | Fires when |
87
- |---|---|---|
88
- | `onplay` | `() => void` | Playback starts or resumes. |
89
- | `onpause` | `() => void` | Playback is paused. |
90
- | `onended` | `() => void` | Media finishes playing. |
91
- | `ontimeupdate` | `(data: ViostreamTimeUpdateData) => void` | Current time changes. `data.seconds`, `data.duration`. |
92
- | `onvolumechange` | `(data: ViostreamVolumeChangeData) => void` | Volume changes. `data.volume`. |
93
- | `onerror` | `(data: ViostreamErrorData) => void` | An error occurs. `data.code`, `data.message`. |
94
- | `onprogress` | `(data: ViostreamProgressData) => void` | Buffering progress. `data.percent`. |
95
- | `onready` | `() => void` | Player is ready. |
96
- | `onseeked` | `() => void` | Seek operation completes. |
97
- | `onloaded` | `() => void` | Metadata has loaded. |
98
-
99
- #### Other Props
100
-
101
- | Prop | Type | Description |
102
- |---|---|---|
103
- | `class` | `string` | CSS class applied to the outer wrapper `<div>`. |
104
- | `onplayerready` | `(player: ViostreamPlayerInstance) => void` | Callback providing the player instance for programmatic control. |
105
- | `loading` | `Snippet` | Optional Svelte 5 snippet rendered while the player is loading. |
106
- | `error` | `Snippet<[string]>` | Optional snippet rendered on error. Receives the error message as an argument. |
107
-
108
- ### Getting the Player Instance
109
-
110
- Use `onplayerready` to get a reference to the player for programmatic control:
111
-
112
- ```svelte
113
- <script lang="ts">
114
- import { ViostreamPlayer } from 'viostream-player-svelte';
115
- import type { ViostreamPlayerInstance } from 'viostream-player-svelte';
116
-
117
- let player: ViostreamPlayerInstance | undefined = $state();
118
- </script>
119
-
120
- <ViostreamPlayer
121
- accountKey="vc-100100100"
122
- publicKey="nhedxonrxsyfee"
123
- onplayerready={(p) => (player = p)}
124
- />
125
-
126
- <button onclick={() => player?.play()}>Play</button>
127
- <button onclick={() => player?.pause()}>Pause</button>
128
- ```
129
-
130
- ### Custom Loading and Error States
131
-
132
- Use Svelte 5 snippets to replace the default loading/error UI:
133
-
134
- ```svelte
135
- <ViostreamPlayer
136
- accountKey="vc-100100100"
137
- publicKey="nhedxonrxsyfee"
138
- >
139
- {#snippet loading()}
140
- <p>Loading video...</p>
141
- {/snippet}
142
-
143
- {#snippet error(message)}
144
- <div class="my-error">Something went wrong: {message}</div>
145
- {/snippet}
146
- </ViostreamPlayer>
147
- ```
148
-
149
- ### Cleanup
150
-
151
- The player is destroyed automatically when the component unmounts. All event listeners are cleaned up and the player iframe is removed from the DOM.
152
-
153
- ---
154
-
155
- ## `createViostreamPlayer()`
156
-
157
- For use outside of Svelte components or when you need full lifecycle control.
158
-
159
- ```ts
160
- import { createViostreamPlayer } from 'viostream-player-svelte';
161
- import type { CreateViostreamPlayerOptions } from 'viostream-player-svelte';
162
-
163
- const player = await createViostreamPlayer({
164
- accountKey: 'vc-100100100',
165
- publicKey: 'nhedxonrxsyfee',
166
- target: 'my-video-div', // element id (string) or HTMLElement
167
- options: {
168
- displayTitle: true,
169
- sharing: true,
170
- speedSelector: true
171
- }
172
- });
173
- ```
174
-
175
- ### Options
176
-
177
- | Property | Type | Description |
178
- |---|---|---|
179
- | `accountKey` | `string` | Your Viostream account key. |
180
- | `publicKey` | `string` | Public key of the media asset. |
181
- | `target` | `string \| HTMLElement` | Container element id or direct DOM reference. |
182
- | `options` | `ViostreamEmbedOptions` | Embed options (same as component props above). |
183
-
184
- ---
185
-
186
- ## Player Instance API
187
-
188
- Both the component (via `onplayerready`) and `createViostreamPlayer()` provide a `ViostreamPlayerInstance` with the following methods.
189
-
190
- ### Playback Controls
191
-
192
- ```ts
193
- player.play();
194
- player.pause();
195
- player.mute();
196
- player.unmute();
197
- player.setVolume(0.5); // 0 to 1
198
- player.setLoop(true);
199
- player.setCurrentTime(30); // seek to 30 seconds
200
- player.setCurrentTime(30, true); // seek and auto-play
201
- player.reload(); // reload the player
202
- player.reload({ key: 'value' }); // reload with new settings
203
- ```
204
-
205
- ### Getters (Promise-based)
206
-
207
- All getters return promises. The SDK converts the underlying callback-based API to `async`/`await`.
208
-
209
- ```ts
210
- const volume = await player.getVolume(); // number (0–1)
211
- const loop = await player.getLoop(); // boolean
212
- const time = await player.getCurrentTime(); // number (seconds)
213
- const paused = await player.getPaused(); // boolean
214
- const duration = await player.getDuration(); // number (seconds)
215
- const muted = await player.getMuted(); // boolean
216
- const ratio = await player.getAspectRatio(); // number
217
- const liveTime = await player.getLiveCurrentTime(); // number (seconds)
218
- const height = await player.getHeight(); // number (pixels)
219
- const tracks = await player.getTracks(); // ViostreamTrack[]
220
- ```
221
-
222
- ### Track Management
223
-
224
- ```ts
225
- const tracks = await player.getTracks();
226
- player.setTrack(tracks[0]); // pass a ViostreamTrack object
227
- player.setTrack('en'); // or a track id string
228
- ```
229
-
230
- ### Cue Management
231
-
232
- ```ts
233
- player.cueAdd({ startTime: 10, text: 'Introduction' });
234
-
235
- player.cueUpdate(
236
- { startTime: 10, text: 'Introduction' },
237
- { text: 'Updated Introduction' }
238
- );
239
-
240
- player.cueDelete('cue-id');
241
- ```
242
-
243
- ### Automatic Speech Recognition (ASR)
244
-
245
- ```ts
246
- player.asrAdd(cueArray, 'asr-track-id');
247
- ```
248
-
249
- ### Events
250
-
251
- Subscribe to player events with `on()`. It returns an unsubscribe function.
252
-
253
- ```ts
254
- // Subscribe
255
- const unsubscribe = player.on('timeupdate', (data) => {
256
- console.log(`${data.seconds}s / ${data.duration}s`);
257
- });
258
-
259
- // Unsubscribe later
260
- unsubscribe();
261
-
262
- // Or use off() directly
263
- const handler = () => console.log('paused');
264
- player.on('pause', handler);
265
- player.off('pause', handler);
266
- ```
267
-
268
- #### Available Events
269
-
270
- | Event | Callback Data | Description |
271
- |---|---|---|
272
- | `play` | `void` | Playback started or resumed. |
273
- | `pause` | `void` | Playback paused. |
274
- | `ended` | `void` | Media finished playing. |
275
- | `timeupdate` | `{ seconds: number, duration: number }` | Playback time changed. |
276
- | `volumechange` | `{ volume: number }` | Volume changed. |
277
- | `error` | `{ code?: number, message?: string }` | Error occurred. |
278
- | `progress` | `{ percent: number }` | Buffering progress. |
279
- | `ready` | `void` | Player is ready. |
280
- | `seeked` | `void` | Seek completed. |
281
- | `loaded` | `void` | Metadata loaded. |
282
-
283
- Custom event names are also accepted via the string index signature:
284
-
285
- ```ts
286
- player.on('my-custom-event', (data) => {
287
- console.log(data);
288
- });
289
- ```
290
-
291
- ### Destroy
292
-
293
- When using `createViostreamPlayer()`, you are responsible for cleanup:
294
-
295
- ```ts
296
- player.destroy();
297
- ```
298
-
299
- After calling `destroy()`:
300
- - All event listeners are removed.
301
- - The player iframe is removed from the DOM.
302
- - Getter calls will reject with `"Player has been destroyed"`.
303
- - `player.raw` returns `undefined`.
304
-
305
- ### Raw Escape Hatch
306
-
307
- If you need direct access to the underlying Viostream player instance:
308
-
309
- ```ts
310
- const raw = player.raw; // RawViostreamPlayerInstance | undefined
311
- if (raw) {
312
- raw.getVolume((vol) => console.log(vol)); // callback-based original API
313
- }
314
- ```
315
-
316
- ---
317
-
318
- ## Script Loader
319
-
320
- The SDK loads the Viostream API script automatically. If you need manual control over loading (e.g. preloading), you can use `loadViostream` directly:
321
-
322
- ```ts
323
- import { loadViostream } from 'viostream-player-svelte';
324
-
325
- const api = await loadViostream('vc-100100100');
326
- // api.embed(...) is now available
327
- ```
328
-
329
- The loader:
330
- - Injects `<script src="https://play.viostream.com/api/{accountKey}">` into `<head>`.
331
- - Deduplicates requests -- calling it multiple times with the same key returns the same promise.
332
- - Times out after 15 seconds if the script fails to load.
333
- - Detects if the script tag already exists in the DOM (e.g. added manually) and waits for it.
334
-
335
- ---
336
-
337
- ## TypeScript
338
-
339
- Every export is fully typed. Import types alongside runtime exports:
340
-
341
- ```ts
342
- import { ViostreamPlayer, createViostreamPlayer } from 'viostream-player-svelte';
343
- import type {
344
- ViostreamPlayerInstance,
345
- ViostreamPlayerProps,
346
- ViostreamEmbedOptions,
347
- ViostreamTimeUpdateData,
348
- ViostreamVolumeChangeData,
349
- ViostreamErrorData,
350
- ViostreamProgressData,
351
- ViostreamPlayerEventMap,
352
- ViostreamEventHandler,
353
- ViostreamCue,
354
- ViostreamCueFieldUpdate,
355
- ViostreamTrack,
356
- CreateViostreamPlayerOptions,
357
- RawViostreamPlayerInstance,
358
- ViostreamGlobal
359
- } from 'viostream-player-svelte';
360
- ```
361
-
362
- ---
363
-
364
- ## Full Example
365
-
366
- A complete example showing the component with custom controls, event logging, and async getters:
367
-
368
- ```svelte
369
- <script lang="ts">
370
- import { ViostreamPlayer } from 'viostream-player-svelte';
371
- import type { ViostreamPlayerInstance, ViostreamTimeUpdateData } from 'viostream-player-svelte';
372
-
373
- let player: ViostreamPlayerInstance | undefined = $state();
374
- let currentTime = $state(0);
375
- let duration = $state(0);
376
- let paused = $state(true);
377
- let log: string[] = $state([]);
378
-
379
- function handleReady(p: ViostreamPlayerInstance) {
380
- player = p;
381
- p.getDuration().then((d) => (duration = d));
382
- }
383
-
384
- function handleTimeUpdate(data: ViostreamTimeUpdateData) {
385
- currentTime = data.seconds;
386
- duration = data.duration;
387
- }
388
-
389
- function format(s: number): string {
390
- return `${Math.floor(s / 60)}:${Math.floor(s % 60).toString().padStart(2, '0')}`;
391
- }
392
- </script>
393
-
394
- <ViostreamPlayer
395
- accountKey="vc-100100100"
396
- publicKey="nhedxonrxsyfee"
397
- displayTitle={true}
398
- sharing={true}
399
- speedSelector={true}
400
- hlsQualitySelector={true}
401
- onplay={() => { paused = false; log = ['play', ...log]; }}
402
- onpause={() => { paused = true; log = ['pause', ...log]; }}
403
- onended={() => { log = ['ended', ...log]; }}
404
- ontimeupdate={handleTimeUpdate}
405
- onplayerready={handleReady}
406
- />
407
-
408
- <div>
409
- <button onclick={() => paused ? player?.play() : player?.pause()}>
410
- {paused ? 'Play' : 'Pause'}
411
- </button>
412
- <button onclick={() => player?.setCurrentTime(0)}>Restart</button>
413
- <span>{format(currentTime)} / {format(duration)}</span>
414
- </div>
415
-
416
- <div>
417
- <button onclick={async () => {
418
- const vol = await player?.getVolume();
419
- log = [`volume: ${vol}`, ...log];
420
- }}>Get Volume</button>
421
- <button onclick={async () => {
422
- const tracks = await player?.getTracks();
423
- log = [`tracks: ${JSON.stringify(tracks)}`, ...log];
424
- }}>Get Tracks</button>
425
- </div>
426
-
427
- <pre>{log.join('\n')}</pre>
428
- ```
429
-
430
- ---
431
-
432
- ## Development
433
-
434
- ```bash
435
- # Install dependencies
436
- npm install
437
-
438
- # Start the dev server (serves the demo page)
439
- npm run dev
440
-
441
- # Type-check
442
- npm run check
443
-
444
- # Run tests
445
- npm run test
446
-
447
- # Run tests in watch mode
448
- npm run test:watch
449
-
450
- # Build the library for publishing
451
- npm run package
452
- ```
453
-
454
- ## License
455
-
456
- MIT
1
+ # viostream-player-svelte
2
+
3
+ <a href="https://www.npmjs.com/package/@viostream/viostream-player-svelte"><img src="https://img.shields.io/npm/v/@viostream/viostream-player-svelte.svg?sanitize=true" alt="npm version"></a>
4
+ <a href="https://www.npmjs.com/package/@viostream/viostream-player-svelte"><img src="https://img.shields.io/npm/l/@viostream/viostream-player-svelte.svg?sanitize=true" alt="License"></a>
5
+ <a href="https://npmcharts.com/compare/@viostream/viostream-player-svelte?interval=30"><img src="https://img.shields.io/npm/dm/@viostream/viostream-player-svelte.svg?sanitize=true" alt="Downloads"></a>
6
+
7
+ Svelte 5 SDK for the [Viostream](https://www.viostream.com) video player. Embed, control, and listen to player events with full TypeScript support.
8
+
9
+ ## Requirements
10
+
11
+ - Svelte 5
12
+ - A Viostream account key (found on the **Settings > General** page in Viostream)
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install viostream-player-svelte
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ### Component
23
+
24
+ Drop a `<ViostreamPlayer>` into any Svelte component. The SDK loads the Viostream script automatically.
25
+
26
+ ```svelte
27
+ <script lang="ts">
28
+ import { ViostreamPlayer } from 'viostream-player-svelte';
29
+ </script>
30
+
31
+ <ViostreamPlayer
32
+ accountKey="vc-100100100"
33
+ publicKey="nhedxonrxsyfee"
34
+ displayTitle={true}
35
+ sharing={true}
36
+ onplay={() => console.log('playing')}
37
+ />
38
+ ```
39
+
40
+ ### Headless / Programmatic
41
+
42
+ Use `createViostreamPlayer` when you need full control without a component:
43
+
44
+ ```ts
45
+ import { createViostreamPlayer } from 'viostream-player-svelte';
46
+
47
+ const player = await createViostreamPlayer({
48
+ accountKey: 'vc-100100100',
49
+ publicKey: 'nhedxonrxsyfee',
50
+ target: 'my-video-div', // element id or HTMLElement
51
+ options: { displayTitle: true }
52
+ });
53
+
54
+ player.play();
55
+ ```
56
+
57
+ ---
58
+
59
+ ## `<ViostreamPlayer>` Component
60
+
61
+ ### Props
62
+
63
+ #### Required
64
+
65
+ | Prop | Type | Description |
66
+ |---|---|---|
67
+ | `accountKey` | `string` | Your Viostream account key (e.g. `'vc-100100100'`). |
68
+ | `publicKey` | `string` | The public key of the media asset to embed. |
69
+
70
+ #### Embed Options
71
+
72
+ All embed options are optional and passed directly to the Viostream embed API.
73
+
74
+ | Prop | Type | Description |
75
+ |---|---|---|
76
+ | `chapters` | `boolean` | Display chapter markers. |
77
+ | `chapterSlug` | `string` | Seek to a named chapter before playback. |
78
+ | `displayTitle` | `boolean` | Show the video title overlay. Default: `false`. |
79
+ | `hlsQualitySelector` | `boolean` | Show the HLS quality selector. Default: `true`. |
80
+ | `playerKey` | `string` | Override the player theme to use. |
81
+ | `playerStyle` | `'video' \| 'audio' \| 'audio-poster'` | The player rendering style. Default: `'video'`. |
82
+ | `sharing` | `boolean` | Show sharing controls. Default: `false`. |
83
+ | `skinActive` | `string` | Custom skin active colour (e.g. `'#ff0000'`). Requires `skinCustom: true`. |
84
+ | `skinBackground` | `string` | Custom skin background colour (e.g. `'#000000'`). Requires `skinCustom: true`. |
85
+ | `skinCustom` | `boolean` | Enable a custom skin via the API. Default: `false`. |
86
+ | `skinInactive` | `string` | Custom skin inactive colour (e.g. `'#cccccc'`). Requires `skinCustom: true`. |
87
+ | `speedSelector` | `boolean` | Show playback speed selector. Default: `true`. |
88
+ | `startEndTimespan` | `string` | Play a specific section (e.g. `'10,30'`). |
89
+ | `startTime` | `string` | Seek to a time (seconds) before playback. |
90
+ | `transcriptDownload` | `boolean` | Allow transcript download. Default: `false`. |
91
+ | `useSettingsMenu` | `boolean` | Enable the settings menu on the control bar. Default: `false`. |
92
+
93
+ #### Event Callbacks
94
+
95
+ | Prop | Signature | Fires when |
96
+ |---|---|---|
97
+ | `onplay` | `() => void` | Playback starts or resumes. |
98
+ | `onpause` | `() => void` | Playback is paused. |
99
+ | `onended` | `() => void` | Media finishes playing. |
100
+ | `ontimeupdate` | `(data: ViostreamTimeUpdateData) => void` | Current time changes. `data.seconds`, `data.duration`. |
101
+ | `onvolumechange` | `(data: ViostreamVolumeChangeData) => void` | Volume changes. `data.volume`. |
102
+ | `onerror` | `(data: ViostreamErrorData) => void` | An error occurs. `data.code`, `data.message`. |
103
+ | `onprogress` | `(data: ViostreamProgressData) => void` | Buffering progress. `data.percent`. |
104
+ | `onready` | `() => void` | Player is ready. |
105
+ | `onseeked` | `() => void` | Seek operation completes. |
106
+ | `onloaded` | `() => void` | Metadata has loaded. |
107
+
108
+ #### Other Props
109
+
110
+ | Prop | Type | Description |
111
+ |---|---|---|
112
+ | `class` | `string` | CSS class applied to the outer wrapper `<div>`. |
113
+ | `onplayerready` | `(player: ViostreamPlayerInstance) => void` | Callback providing the player instance for programmatic control. |
114
+ | `loading` | `Snippet` | Optional Svelte 5 snippet rendered while the player is loading. |
115
+ | `error` | `Snippet<[string]>` | Optional snippet rendered on error. Receives the error message as an argument. |
116
+
117
+ ### Getting the Player Instance
118
+
119
+ Use `onplayerready` to get a reference to the player for programmatic control:
120
+
121
+ ```svelte
122
+ <script lang="ts">
123
+ import { ViostreamPlayer } from 'viostream-player-svelte';
124
+ import type { ViostreamPlayerInstance } from 'viostream-player-svelte';
125
+
126
+ let player: ViostreamPlayerInstance | undefined = $state();
127
+ </script>
128
+
129
+ <ViostreamPlayer
130
+ accountKey="vc-100100100"
131
+ publicKey="nhedxonrxsyfee"
132
+ onplayerready={(p) => (player = p)}
133
+ />
134
+
135
+ <button onclick={() => player?.play()}>Play</button>
136
+ <button onclick={() => player?.pause()}>Pause</button>
137
+ ```
138
+
139
+ ### Custom Loading and Error States
140
+
141
+ Use Svelte 5 snippets to replace the default loading/error UI:
142
+
143
+ ```svelte
144
+ <ViostreamPlayer
145
+ accountKey="vc-100100100"
146
+ publicKey="nhedxonrxsyfee"
147
+ >
148
+ {#snippet loading()}
149
+ <p>Loading video...</p>
150
+ {/snippet}
151
+
152
+ {#snippet error(message)}
153
+ <div class="my-error">Something went wrong: {message}</div>
154
+ {/snippet}
155
+ </ViostreamPlayer>
156
+ ```
157
+
158
+ ### Cleanup
159
+
160
+ The player is destroyed automatically when the component unmounts. All event listeners are cleaned up and the player iframe is removed from the DOM.
161
+
162
+ ---
163
+
164
+ ## `createViostreamPlayer()`
165
+
166
+ For use outside of Svelte components or when you need full lifecycle control.
167
+
168
+ ```ts
169
+ import { createViostreamPlayer } from 'viostream-player-svelte';
170
+ import type { CreateViostreamPlayerOptions } from 'viostream-player-svelte';
171
+
172
+ const player = await createViostreamPlayer({
173
+ accountKey: 'vc-100100100',
174
+ publicKey: 'nhedxonrxsyfee',
175
+ target: 'my-video-div', // element id (string) or HTMLElement
176
+ options: {
177
+ displayTitle: true,
178
+ sharing: true,
179
+ speedSelector: true
180
+ }
181
+ });
182
+ ```
183
+
184
+ ### Options
185
+
186
+ | Property | Type | Description |
187
+ |---|---|---|
188
+ | `accountKey` | `string` | Your Viostream account key. |
189
+ | `publicKey` | `string` | Public key of the media asset. |
190
+ | `target` | `string \| HTMLElement` | Container element id or direct DOM reference. |
191
+ | `options` | `ViostreamEmbedOptions` | Embed options (same as component props above). |
192
+
193
+ ---
194
+
195
+ ## Player Instance API
196
+
197
+ Both the component (via `onplayerready`) and `createViostreamPlayer()` provide a `ViostreamPlayerInstance` with the following methods.
198
+
199
+ ### Playback Controls
200
+
201
+ ```ts
202
+ player.play();
203
+ player.pause();
204
+ player.mute();
205
+ player.unmute();
206
+ player.setVolume(0.5); // 0 to 1
207
+ player.setLoop(true);
208
+ player.setCurrentTime(30); // seek to 30 seconds
209
+ player.setCurrentTime(30, true); // seek and auto-play
210
+ player.reload(); // reload the player
211
+ player.reload({ key: 'value' }); // reload with new settings
212
+ ```
213
+
214
+ ### Getters (Promise-based)
215
+
216
+ All getters return promises. The SDK converts the underlying callback-based API to `async`/`await`.
217
+
218
+ ```ts
219
+ const volume = await player.getVolume(); // number (0–1)
220
+ const loop = await player.getLoop(); // boolean
221
+ const time = await player.getCurrentTime(); // number (seconds)
222
+ const paused = await player.getPaused(); // boolean
223
+ const duration = await player.getDuration(); // number (seconds)
224
+ const muted = await player.getMuted(); // boolean
225
+ const ratio = await player.getAspectRatio(); // number
226
+ const height = await player.getHeight(); // number (pixels)
227
+ ```
228
+
229
+ ### Events
230
+
231
+ Subscribe to player events with `on()`. It returns an unsubscribe function.
232
+
233
+ ```ts
234
+ // Subscribe
235
+ const unsubscribe = player.on('timeupdate', (data) => {
236
+ console.log(`${data.seconds}s / ${data.duration}s`);
237
+ });
238
+
239
+ // Unsubscribe later
240
+ unsubscribe();
241
+
242
+ // Or use off() directly
243
+ const handler = () => console.log('paused');
244
+ player.on('pause', handler);
245
+ player.off('pause', handler);
246
+ ```
247
+
248
+ #### Available Events
249
+
250
+ | Event | Callback Data | Description |
251
+ |---|---|---|
252
+ | `play` | `void` | Playback started or resumed. |
253
+ | `pause` | `void` | Playback paused. |
254
+ | `ended` | `void` | Media finished playing. |
255
+ | `timeupdate` | `{ seconds: number, duration: number }` | Playback time changed. |
256
+ | `volumechange` | `{ volume: number }` | Volume changed. |
257
+ | `error` | `{ code?: number, message?: string }` | Error occurred. |
258
+ | `progress` | `{ percent: number }` | Buffering progress. |
259
+ | `ready` | `void` | Player is ready. |
260
+ | `seeked` | `void` | Seek completed. |
261
+ | `loaded` | `void` | Metadata loaded. |
262
+
263
+ Custom event names are also accepted via the string index signature:
264
+
265
+ ```ts
266
+ player.on('my-custom-event', (data) => {
267
+ console.log(data);
268
+ });
269
+ ```
270
+
271
+ ### Destroy
272
+
273
+ When using `createViostreamPlayer()`, you are responsible for cleanup:
274
+
275
+ ```ts
276
+ player.destroy();
277
+ ```
278
+
279
+ After calling `destroy()`:
280
+ - All event listeners are removed.
281
+ - The player iframe is removed from the DOM.
282
+ - Getter calls will reject with `"Player has been destroyed"`.
283
+ ---
284
+
285
+ ## Script Loader
286
+
287
+ The SDK loads the Viostream API script automatically. If you need manual control over loading (e.g. preloading), you can use `loadViostream` directly:
288
+
289
+ ```ts
290
+ import { loadViostream } from 'viostream-player-svelte';
291
+
292
+ const api = await loadViostream('vc-100100100');
293
+ // api.embed(...) is now available
294
+ ```
295
+
296
+ The loader:
297
+ - Injects `<script src="https://play.viostream.com/api/{accountKey}">` into `<head>`.
298
+ - Deduplicates requests -- calling it multiple times with the same key returns the same promise.
299
+ - Times out after 15 seconds if the script fails to load.
300
+ - Detects if the script tag already exists in the DOM (e.g. added manually) and waits for it.
301
+
302
+ ---
303
+
304
+ ## TypeScript
305
+
306
+ Every export is fully typed. Import types alongside runtime exports:
307
+
308
+ ```ts
309
+ import { ViostreamPlayer, createViostreamPlayer } from 'viostream-player-svelte';
310
+ import type {
311
+ ViostreamPlayerInstance,
312
+ ViostreamPlayerProps,
313
+ ViostreamEmbedOptions,
314
+ ViostreamTimeUpdateData,
315
+ ViostreamVolumeChangeData,
316
+ ViostreamErrorData,
317
+ ViostreamProgressData,
318
+ ViostreamPlayerEventMap,
319
+ ViostreamEventHandler,
320
+ CreateViostreamPlayerOptions,
321
+ } from 'viostream-player-svelte';
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Full Example
327
+
328
+ A complete example showing the component with custom controls, event logging, and async getters:
329
+
330
+ ```svelte
331
+ <script lang="ts">
332
+ import { ViostreamPlayer } from 'viostream-player-svelte';
333
+ import type { ViostreamPlayerInstance, ViostreamTimeUpdateData } from 'viostream-player-svelte';
334
+
335
+ let player: ViostreamPlayerInstance | undefined = $state();
336
+ let currentTime = $state(0);
337
+ let duration = $state(0);
338
+ let paused = $state(true);
339
+ let log: string[] = $state([]);
340
+
341
+ function handleReady(p: ViostreamPlayerInstance) {
342
+ player = p;
343
+ p.getDuration().then((d) => (duration = d));
344
+ }
345
+
346
+ function handleTimeUpdate(data: ViostreamTimeUpdateData) {
347
+ currentTime = data.seconds;
348
+ duration = data.duration;
349
+ }
350
+
351
+ function format(s: number): string {
352
+ return `${Math.floor(s / 60)}:${Math.floor(s % 60).toString().padStart(2, '0')}`;
353
+ }
354
+ </script>
355
+
356
+ <ViostreamPlayer
357
+ accountKey="vc-100100100"
358
+ publicKey="nhedxonrxsyfee"
359
+ displayTitle={true}
360
+ sharing={true}
361
+ speedSelector={true}
362
+ hlsQualitySelector={true}
363
+ onplay={() => { paused = false; log = ['play', ...log]; }}
364
+ onpause={() => { paused = true; log = ['pause', ...log]; }}
365
+ onended={() => { log = ['ended', ...log]; }}
366
+ ontimeupdate={handleTimeUpdate}
367
+ onplayerready={handleReady}
368
+ />
369
+
370
+ <div>
371
+ <button onclick={() => paused ? player?.play() : player?.pause()}>
372
+ {paused ? 'Play' : 'Pause'}
373
+ </button>
374
+ <button onclick={() => player?.setCurrentTime(0)}>Restart</button>
375
+ <span>{format(currentTime)} / {format(duration)}</span>
376
+ </div>
377
+
378
+ <div>
379
+ <button onclick={async () => {
380
+ const vol = await player?.getVolume();
381
+ log = [`volume: ${vol}`, ...log];
382
+ }}>Get Volume</button>
383
+ </div>
384
+
385
+ <pre>{log.join('\n')}</pre>
386
+ ```
387
+
388
+ ---
389
+
390
+ ## Development
391
+
392
+ ```bash
393
+ # Install dependencies
394
+ npm install
395
+
396
+ # Start the dev server (serves the demo page)
397
+ npm run dev
398
+
399
+ # Type-check
400
+ npm run check
401
+
402
+ # Run tests
403
+ npm run test
404
+
405
+ # Run tests in watch mode
406
+ npm run test:watch
407
+
408
+ # Build the library for publishing
409
+ npm run package
410
+ ```
411
+
412
+ ## License
413
+
414
+ MIT