@viostream/viostream-player-svelte 0.1.2 → 0.1.3

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