@touchcastllc/napster-companion-api-dev 1.5.0-alpha.0 → 1.6.0-alpha.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/README.md CHANGED
@@ -1,1171 +1,68 @@
1
- # Napster Companion API SDK
1
+ # Napster API Web SDK
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@touchcastllc/napster-companion-api.svg)](https://www.npmjs.com/package/@touchcastllc/napster-companion-api)
4
4
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
5
 
6
- > Real-time conversational video AI for web applications. Embed AI companions that users can talk to face-to-face via WebRTC. Attaches to any DOM element, handles video streaming and avatar rendering, connects to Azure OpenAI for conversation.
6
+ Put a video AI agent on your website one your visitors can see, hear and talk to, in real time.
7
7
 
8
- **Supported Environments:**
8
+ The SDK handles the hard parts: the live WebRTC connection, the agent's video and audio, the microphone, and the controls around it. You decide where it sits and what it can do.
9
9
 
10
- - Modern browsers (Chrome, Firefox, Safari, Edge)
11
- - React 16 and up
12
- - Vue 2 and up
13
- - Angular 12 and up
14
- - Vanilla JavaScript (no build tools required)
10
+ ## 📚 Documentation
15
11
 
16
- **Key Capabilities:**
12
+ **[developers.napster.com/docs/sdks/web-sdk/overview](https://developers.napster.com/docs/sdks/web-sdk/overview)**
17
13
 
18
- - **WebRTC Video Streaming:** Real-time video with AI avatars
19
- - **Framework Agnostic:** React, Vue, Angular, or vanilla JS
20
- - **Zero External Dependencies:** Drop in a script tag and go
21
- - **TypeScript Support:** Fully typed APIs
22
- - **Tree-Shakeable:** Import only what you need
23
- - **Production Ready:** Minified builds with type definitions
14
+ Everything lives there getting started, authentication, configuration, the full API reference, and guides for each framework. This file is only an introduction.
24
15
 
25
- ---
16
+ ## What you can build
26
17
 
27
- ## 1. Quick Start
18
+ - **An agent that greets and helps** — answers questions about your product, in your voice, on the page the visitor is already on.
19
+ - **A guide that stays with them** — the conversation survives navigation, so visitors can browse your whole site without dropping the session.
20
+ - **An assistant that can act** — expose what your app can do, and the agent can use those actions on the visitor's behalf rather than just describing them.
21
+ - **A face for your brand** — choose the avatar, where it sits on the page, and how it looks.
28
22
 
29
- Get up and running in minutes. Follow these four steps to integrate the SDK into your project.
23
+ ## What comes with it
30
24
 
31
- ### 1.1 Choose Your Setup
25
+ | | |
26
+ | ----------------------- | ------------------------------------------------------------ |
27
+ | **Live conversation** | Real-time voice and video both ways, over WebRTC |
28
+ | **Works anywhere** | React, Vue, Angular, or plain HTML with a script tag |
29
+ | **Yours to place** | Floating or inline, positioned and styled to match your site |
30
+ | **Screen sharing** | Show the agent what you are looking at |
31
+ | **Picture-in-picture** | The agent stays visible while the visitor keeps working |
32
+ | **Cross-page sessions** | One continuous conversation across page loads |
33
+ | **Typed throughout** | Full TypeScript definitions |
32
34
 
33
- Pick the integration method that matches your project:
34
-
35
- | Build Type | Best For | Import Path | Dependencies |
36
- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------------------- |
37
- | **ESM** | ✅ **Recommended for most projects**<br>✅ You use a bundler (Vite, Webpack, Rollup, etc.)<br>✅ You want optimal bundle size (dependencies not bundled)<br>✅ You're using TypeScript or modern JavaScript | `@touchcastllc/napster-companion-api` | Redux Toolkit (peer) |
38
- | **Standalone** | ✅ You want a `<script>` tag (no bundler, no external dependencies)<br>✅ You want zero external dependencies<br>✅ You don't want to manage dependencies separately<br>✅ You're okay with a slightly larger file (all dependencies included) | `lib/index.standalone.js` | All bundled |
39
-
40
- ---
41
-
42
- ### 1.2 Installation & Setup
43
-
44
- #### 1.2.1 For ESM Build Type (Recommended)
45
-
46
- **Step 1: Install the SDK**
47
-
48
- Install the package:
35
+ ## Installation
49
36
 
50
37
  ```bash
51
38
  npm install @touchcastllc/napster-companion-api
52
- # or
53
- yarn add @touchcastllc/napster-companion-api
54
- ```
55
-
56
- Install peer dependencies:
57
-
58
- ```bash
59
- npm install @reduxjs/toolkit
60
- ```
61
-
62
- **Step 2: Import the SDK**
63
-
64
- ```typescript
65
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
66
- ```
67
-
68
- **Also, import CSS Stylesheet (required):**
69
-
70
- The SDK comes with a complete stylesheet for all components. Import it in your application:
71
-
72
- **ESM/TypeScript:**
73
-
74
- ```typescript
75
- import "@touchcastllc/napster-companion-api/styles";
76
39
  ```
77
40
 
78
- **CommonJS:**
41
+ Import the SDK and its stylesheet:
79
42
 
80
43
  ```js
81
- require("@touchcastllc/napster-companion-api/styles");
82
- ```
83
-
84
- **HTML `<link>` Tag:**
85
-
86
- ```html
87
- <link
88
- rel="stylesheet"
89
- href="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css"
90
- />
91
- ```
92
-
93
- **CSS `@import`:**
94
-
95
- ```css
96
- @import url("https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css");
97
- ```
98
-
99
- The CSS file (`index.css`) is minified and contains all styles needed for the avatar widget, controls, tooltips, and more.
100
-
101
- #### 1.2.2 For Standalone Build Type
102
-
103
- **Step 1: Import the SDK**
104
-
105
- ```html
106
- <!-- All dependencies bundled (easier, larger file) -->
107
- <script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.js"></script>
108
- ```
109
-
110
- ---
111
-
112
- ### 1.3 Initialization
113
-
114
- #### 1.3.1 For ESM Build Type
115
-
116
- Initialize the SDK by calling `NapsterCompanionApiSdk.init()` with your auth token and configuration options.
117
-
118
- See the [1.4 Authentication](#14-authentication) section for details on generating auth tokens.
119
-
120
- **Basic Example:**
121
-
122
- ```typescript
123
- const widget = await NapsterCompanionApiSdk.init("YOUR_AUTH_TOKEN", {
124
- mountContainer: "#avatar-container",
125
- });
126
- ```
127
-
128
- #### 1.3.2 For Standalone Build Type
129
-
130
- Initialize the SDK by calling `window.napsterCompanionApiSDK.init()` with your auth token and configuration options.
131
-
132
- See the [1.4 Authentication](#14-authentication) section for details on generating auth tokens.
133
-
134
- **Step 1: Add container to your HTML**
135
-
136
- ```html
137
- <div id="sdk-container"></div>
138
- ```
139
-
140
- **Step 2: Initialize globally**
141
-
142
- ```html
143
- <script>
144
- window.napsterCompanionApiSDK.init("AUTH_TOKEN", {
145
- mountContainer: "#sdk-container",
146
- });
147
- </script>
148
- ```
149
-
150
- ---
151
-
152
- ### 1.4 Authentication
153
-
154
- The SDK requires an **auth token** to connect to the Napster Companion API.
155
-
156
- **Important:** **Do not generate tokens in client-side code** — use a backend service to keep your API key secure.
157
-
158
- #### Step 1: Generate Napster Companion API Key
159
-
160
- 1. Visit the [Napster Companion API Keys page](https://companion-api.napster.com/admin/organization/keys)
161
- 2. Click **Generate API key** and enter your details
162
- 3. Store your API key securely on your backend server
163
-
164
- #### Step 2: Create Connection & Get Token (Backend)
165
-
166
- Create a backend API call to the Napster Companion API to generate auth tokens:
167
-
168
- **Request URL:**
169
-
170
- ```
171
- POST https://companion-api.napster.com/public/connections
172
- ```
173
-
174
- **Request Headers:**
175
-
176
- | Header | Value |
177
- | -------------- | ------------------- |
178
- | `content-type` | `application/json` |
179
- | `x-api-key` | `YOUR_API_KEY_HERE` |
180
-
181
- **Request Body:**
182
-
183
- | Field | Type | Description |
184
- | ----------------------------------------------------------- | ------- | ------------------------------------ |
185
- | `companionId` | string | Your Napster Companion ID |
186
- | `providerConfig.type` | string | Provider type (e.g., `azureOpenAI`) |
187
- | `providerConfig.voiceId` | string | Voice identifier (e.g., `alloy`) |
188
- | `providerConfig.settings.instructions` | string | Custom instructions for the avatar |
189
- | `providerConfig.settings.turnDetection.threshold` | number | Voice detection threshold |
190
- | `providerConfig.settings.turnDetection.prefix_padding_ms` | number | Padding before speech detection (ms) |
191
- | `providerConfig.settings.turnDetection.silence_duration_ms` | number | Silence duration threshold (ms) |
192
- | `providerConfig.settings.temperature` | number | Response temperature (0-1) |
193
- | `providerConfig.useGreenVideo` | boolean | Enable green screen background |
194
- | `disableIdleTimeout` | boolean | Disable idle timeout |
195
-
196
- **Example Request:**
197
-
198
- ```bash
199
- curl 'https://companion-api.napster.com/public/connections' \
200
- -H 'content-type: application/json' \
201
- -H 'x-api-key: YOUR_API_KEY_HERE' \
202
- --data-raw '{
203
- "companionId": "YOUR_COMPANION_ID",
204
- "providerConfig": {
205
- "type": "azureOpenAI",
206
- "voiceId": "alloy",
207
- "settings": {
208
- "instructions": "Your custom instructions here...",
209
- "turnDetection": {
210
- "threshold": 0,
211
- "prefix_padding_ms": 0,
212
- "silence_duration_ms": 0
213
- },
214
- "temperature": 0
215
- },
216
- "useGreenVideo": true
217
- },
218
- "disableIdleTimeout": false
219
- }'
220
- ```
221
-
222
- #### Step 3: Use Token in Client
223
-
224
- Fetch the token from your backend and pass it to the SDK:
225
-
226
- ```typescript
227
- // Possible client-side code for token retrieval
228
- async function initializeAvatar() {
229
- // Fetch token from your backend
230
- const response = await fetch("/your-backend-endpoint", { method: "POST" });
231
- const { token } = await response.json();
232
- }
233
- ```
234
-
235
- ---
236
-
237
- ## 2. Examples
238
-
239
- We provide example implementations for popular frameworks and vanilla JavaScript:
240
-
241
- ### 2.1 React
242
-
243
- ```tsx
244
- import React, { useEffect, useRef, useState } from "react";
245
44
  import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
246
- import type { NapsterCompanionApiInstance } from "@touchcastllc/napster-companion-api";
247
-
248
- export function CompanionWidget() {
249
- const containerRef = useRef<HTMLDivElement>(null);
250
- const [instance, setInstance] = useState<NapsterCompanionApiInstance | null>(
251
- null
252
- );
253
-
254
- useEffect(() => {
255
- const initSDK = async () => {
256
- if (!containerRef.current) return;
257
-
258
- const result = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
259
- mountContainer: containerRef.current,
260
- position: "bottom-right",
261
- });
262
- setInstance(result);
263
- };
264
-
265
- initSDK();
266
-
267
- return () => {
268
- instance?.destroy();
269
- };
270
- }, []);
271
-
272
- return <div ref={containerRef} style={{ width: "100%", height: "100%" }} />;
273
- }
274
- ```
275
-
276
- ### 2.2 Vue 3
277
-
278
- ```html
279
- <template>
280
- <div ref="containerRef"></div>
281
- </template>
282
-
283
- <script setup lang="ts">
284
- import { onMounted, onUnmounted, ref } from "vue";
285
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
286
- import type { NapsterCompanionApiInstance } from "@touchcastllc/napster-companion-api";
287
-
288
- const containerRef = ref<HTMLElement>();
289
- let instance: NapsterCompanionApiInstance | null = null;
290
-
291
- onMounted(async () => {
292
- if (!containerRef.value) return;
293
-
294
- instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
295
- mountContainer: containerRef.value,
296
- position: "bottom-right",
297
- });
298
- });
299
-
300
- onUnmounted(() => {
301
- instance?.destroy();
302
- });
303
- </script>
304
- ```
305
-
306
- ### 2.3 Angular
307
-
308
- ```typescript
309
- import {
310
- Component,
311
- OnInit,
312
- OnDestroy,
313
- ElementRef,
314
- ViewChild,
315
- } from "@angular/core";
316
- import {
317
- NapsterCompanionApiSdk,
318
- NapsterCompanionApiInstance,
319
- } from "@touchcastllc/napster-companion-api";
320
-
321
- @Component({
322
- selector: "app-companion",
323
- template: "<div #containerRef></div>",
324
- })
325
- export class CompanionComponent implements OnInit, OnDestroy {
326
- @ViewChild("containerRef") containerRef!: ElementRef<HTMLDivElement>;
327
- private instance: NapsterCompanionApiInstance | null = null;
328
-
329
- async ngOnInit() {
330
- this.instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
331
- mountContainer: this.containerRef.nativeElement,
332
- position: "bottom-right",
333
- });
334
- }
335
-
336
- ngOnDestroy() {
337
- this.instance?.destroy();
338
- }
339
- }
45
+ import "@touchcastllc/napster-companion-api/styles";
340
46
  ```
341
47
 
342
- ### 2.4 Vanilla JavaScript/TypeScript
48
+ No bundler? Drop in the standalone build with a `<script>` tag — styles are included, and the SDK is available as `napsterCompanionApiSDK`:
343
49
 
344
50
  ```html
345
- <div id="sdk-container"></div>
346
- <script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.js"></script>
51
+ <script src="https://unpkg.com/@touchcastllc/napster-companion-api"></script>
347
52
  <script>
348
- const sdk = window.napsterCompanionApiSDK;
349
-
350
- sdk
351
- .init("YOUR_TOKEN", {
352
- mountContainer: "#sdk-container",
353
- position: "bottom-right",
354
- })
355
- .then(instance => {
356
- // Control the avatar
357
- instance.showAvatar();
358
-
359
- // Hide after 10 seconds
360
- setTimeout(() => instance.hideAvatar(), 10000);
361
- });
53
+ // Connect with a short-lived token minted by your backend.
54
+ napsterCompanionApiSDK.init(connectionToken);
362
55
  </script>
363
56
  ```
364
57
 
365
- ### 2.5 Advanced Configuration
366
-
367
- ```typescript
368
- async function initAdvancedAvatar() {
369
- const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
370
- mountContainer: "#avatar-container",
371
- position: "bottom-right",
372
-
373
- avatarStyle: {
374
- view: "round", // Options: "round" | "rectangle" | "silhouette"
375
- },
376
-
377
- features: {
378
- inactiveTimeout: { enabled: true, duration: 120000, countdown: 15 },
379
- showSDKLoader: { enabled: true, bgColor: "#f0f0f0" },
380
- },
381
-
382
- style: {
383
- borderRadius: "12px",
384
- boxShadow: "0 4px 20px rgba(0,0,0,0.3)",
385
- },
386
-
387
- onReady: () => console.log("Avatar ready!"),
388
- onError: error => console.error("Error:", error),
389
- onAvatarReady: ready => console.log("Avatar loaded:", ready),
390
- });
391
-
392
- return instance;
393
- }
394
- ```
395
-
396
- ### 2.6 Dynamic Feature Control
397
-
398
- ```typescript
399
- async function controlFeatures() {
400
- const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
401
- mountContainer: "#avatar-container",
402
- });
403
-
404
- // Change position dynamically
405
- document.getElementById("move-avatar")?.addEventListener("click", () => {
406
- instance.setPosition("top-left");
407
- });
408
-
409
- return instance;
410
- }
411
- ```
412
-
413
- ### 2.7 Custom Styling
414
-
415
- #### Inline Styles
416
-
417
- ```typescript
418
- const instance = await NapsterCompanionApiSdk.init(token, {
419
- style: {
420
- border: "2px solid #00ff00",
421
- borderRadius: "8px",
422
- boxShadow: "0 2px 10px rgba(0,0,0,0.2)",
423
- background: "rgba(255,255,255,0.95)",
424
- },
425
- });
426
- ```
427
-
428
- #### CSS Classes
429
-
430
- ```typescript
431
- const instance = await NapsterCompanionApiSdk.init(token, {
432
- className: "my-custom-avatar",
433
- });
434
- ```
435
-
436
- ```css
437
- .my-custom-avatar {
438
- border: 2px solid #007acc;
439
- border-radius: 12px;
440
- backdrop-filter: blur(10px);
441
- }
442
- ```
443
-
444
- #### Dynamic Style Updates
445
-
446
- ```typescript
447
- // Update styles after initialization
448
- instance.updateStyles({
449
- opacity: "0.9",
450
- transform: "scale(1.1)",
451
- transition: "all 0.3s ease",
452
- });
453
- ```
454
-
455
- ### 2.8 Avatar Style Configuration
456
-
457
- Customize the avatar's visual appearance using the `avatarStyle` configuration. Control the avatar's view mode, and other visual properties.
458
-
459
- #### Avatar View Modes
460
-
461
- ```typescript
462
- const instance = await NapsterCompanionApiSdk.init(token, {
463
- avatarStyle: {
464
- view: "round", // Options: "round" | "rectangle" | "silhouette"
465
- },
466
- });
467
- ```
468
-
469
- **Available View Modes:**
470
-
471
- - `"round"` (default) - Circular avatar with rounded appearance
472
- - `"rectangle"` - Rectangular container, ideal for custom styling
473
- - `"silhouette"` - Full view without background styling. (**Note: works only with green screen feature enabled in [Create Connection](#step-2-create-connection--get-token-backend) API**)
474
-
475
- #### Avatar Style Example
476
-
477
- ```typescript
478
- const instance = await NapsterCompanionApiSdk.init(token, {
479
- avatarStyle: {
480
- view: "rectangle",
481
- },
482
- style: {
483
- borderRadius: "16px", // Works well with rectangle
484
- boxShadow: "0 8px 32px rgba(0,0,0,0.2)",
485
- },
486
- });
487
- ```
488
-
489
- ---
490
-
491
- ## 3. Feature Configuration
492
-
493
- ### 3.1 Core Features
494
-
495
- #### Inactivity Timeout
496
-
497
- Automatically disconnect the avatar after a period of user inactivity. Users receive a countdown notification before disconnection.
498
-
499
- ```typescript
500
- const instance = await NapsterCompanionApiSdk.init(token, {
501
- features: {
502
- inactiveTimeout: {
503
- enabled: true,
504
- duration: 60000, // 60 seconds (max: 180000ms)
505
- countdown: 10, // 10 second countdown (max: 60s)
506
- },
507
- },
508
- });
509
- ```
510
-
511
- #### SDK Loading Screen
512
-
513
- Display a loading screen while the avatar assets are being loaded. Customize the appearance with background color, loader color, animation type, or apply custom styles via CSS class name.
514
-
515
- ```typescript
516
- const instance = await NapsterCompanionApiSdk.init(token, {
517
- features: {
518
- showSDKLoader: {
519
- enabled: true,
520
- bgColor: "#ffffff", // Optional: background color of loader overlay
521
- color: "#000000", // Optional: color of the loader animation
522
- type: "spinner", // Optional: "spinner" | "pulse"
523
- className: "custom-loader", // Optional: CSS class for custom loader styles
524
- },
525
- },
526
- });
527
- ```
528
-
529
- **Custom Loader Styling:**
530
-
531
- Use the `className` option to apply your own loader design:
532
-
533
- ```typescript
534
- const instance = await NapsterCompanionApiSdk.init(token, {
535
- features: {
536
- showSDKLoader: {
537
- enabled: true,
538
- className: "my-brand-loader",
539
- },
540
- },
541
- });
542
- ```
543
-
544
- ```css
545
- /* Override default loader with custom styles */
546
- .my-brand-loader {
547
- width: 60px !important;
548
- height: 60px !important;
549
- border-width: 5px !important;
550
- border-style: solid !important;
551
- border-color: rgba(99, 102, 241, 0.2) !important;
552
- border-top-color: #6366f1 !important;
553
- border-radius: 50% !important;
554
- animation: spin 0.8s linear infinite !important;
555
- }
556
-
557
- @keyframes spin {
558
- to { transform: rotate(360deg); }
559
- }
560
- ```
561
-
562
- #### Built-in Controls Block
563
-
564
- Toggle the built-in controls UI (mute / volume / screen-share / end buttons) rendered over the avatar. Disable this when your application provides its own UI using the public methods (`muteMic`, `unmuteMic`, `setAudioVolume`, `stopAvatarTalking`, `destroy`, etc.). Defaults to `enabled: true` — existing integrations see no change.
565
-
566
- ```typescript
567
- const instance = await NapsterCompanionApiSdk.init(token, {
568
- features: {
569
- controls: {
570
- enabled: false, // hide built-in buttons, render your own
571
- },
572
- },
573
- });
574
- ```
575
-
576
- You can also toggle it at runtime via `updateFeatureConfig` (or `enableFeature` / `disableFeature`):
577
-
578
- ```typescript
579
- instance.updateFeatureConfig("controls", { enabled: false });
580
- // later
581
- instance.enableFeature("controls");
582
- ```
583
-
584
- ### 3.2 Picture-in-Picture (PiP)
585
-
586
- Automatically pop the avatar into a Document Picture-in-Picture window when the user switches browser tabs, so the conversation stays visible while they work in another tab. The PiP window mirrors the live avatar video and renders the built-in controls (mute / volume / screen-share / end). Closing the PiP window or returning to the original tab restores the in-page avatar. Chrome / Edge 116+ on HTTPS.
587
-
588
- ```typescript
589
- const instance = await NapsterCompanionApiSdk.init(token, {
590
- features: {
591
- pictureInPicture: {
592
- enabled: true,
593
- width: 400, // optional, default 400
594
- height: 300, // optional, default 300
595
- },
596
- },
597
- });
598
- ```
599
-
600
- **Browser requirements for the auto-PiP trigger to fire:**
601
-
602
- - Secure context (HTTPS)
603
- - Active media playback with audio
604
- - The site has met the browser's Media Engagement Index threshold (user frequently consumes media on the site)
605
-
606
- If the requirements aren't met, the avatar simply stays in-page when the tab loses focus — no errors are thrown.
607
-
608
- ### 3.3 Screen Sharing
609
-
610
- Share the user's screen with the avatar in real time. The SDK captures the display at 1 FPS, renders each frame onto an internal canvas, and streams the canvas track over WebRTC so the avatar can "see" what the user sees. Fully browser-based — no plugins or extensions required.
611
-
612
- #### Enable & Configure
613
-
614
- ```typescript
615
- const instance = await NapsterCompanionApiSdk.init(token, {
616
- features: {
617
- screenShare: {
618
- enabled: true,
619
- },
620
- },
621
- });
622
- ```
623
-
624
- > **Note:** `features.screenShare.enabled` must be `true` for the screen share controls to appear and for `isScreenShareSupported` to return `true`.
625
-
626
- #### Start & Stop
627
-
628
- ```typescript
629
- // Start sharing (opens browser's screen picker)
630
- await instance.startScreenShare();
631
-
632
- // Stop sharing
633
- instance.stopScreenShare();
634
-
635
- // Or toggle on/off
636
- await instance.toggleScreenShare();
637
- ```
638
-
639
- The SDK sends `start_video` / `stop_video` commands to the avatar server automatically. If the user stops sharing via the browser's native "Stop sharing" button, the SDK detects this and cleans up.
58
+ For framework-specific setup, version pinning and the first working session, see
59
+ **[developers.napster.com/docs/sdks/web-sdk/installation](https://developers.napster.com/docs/sdks/web-sdk/installation)**.
640
60
 
641
- #### Checking State
642
-
643
- ```typescript
644
- // Whether screen sharing is currently active
645
- instance.isScreenSharing; // boolean
646
-
647
- // Whether the browser supports screen sharing AND the feature is enabled
648
- instance.isScreenShareSupported; // boolean
649
- ```
650
-
651
- #### Cleanup
652
-
653
- Screen sharing is automatically stopped when:
654
-
655
- - The user calls `instance.destroy()`
656
- - The WebRTC connection closes (network failure, session end)
657
- - The user clicks the browser's native "Stop sharing" button
658
-
659
- ### 3.4 Position & Layout
660
-
661
- Customize the avatar's position on the screen using predefined positions or custom styles. Also you can override the position using style properties.
662
-
663
- ```typescript
664
- const instance = await NapsterCompanionApiSdk.init(token, {
665
- mountContainer: "#my-container", // CSS selector or HTMLElement
666
- position: "bottom-right", // Predefined positions
667
- // Apply custom inline styles to override default SDK styles, will be added to root container
668
- style: {
669
- top: "20px",
670
- left: "20px",
671
- zIndex: "1000",
672
- },
673
- // Apply CSS class name to override default SDK styles, will be added to root container
674
- className: "my-custom-class",
675
- });
676
- ```
677
-
678
- **Available Positions:**
679
-
680
- - `"bottom-right"` (default)
681
- - `"bottom-left"`
682
- - `"bottom-center"`
683
- - `"top-right"`
684
- - `"top-left"`
685
- - `"top-center"`
686
- - `"center"`
687
-
688
- ### 3.5 Inline Layout
689
-
690
- By default the avatar is a floating corner widget (`layout: "fixed"`). Set
691
- `layout: "inline"` to render the avatar **inside your own container** and fill it —
692
- you control placement, size, and shape by styling that container. `position` is
693
- ignored in inline mode.
694
-
695
- ```typescript
696
- // <div id="avatar-box" style="width: 320px; height: 480px"></div>
697
- await NapsterCompanionApiSdk.init(token, {
698
- mountContainer: "#avatar-box",
699
- layout: "inline",
700
- avatarStyle: { view: "rectangle" },
701
- });
702
- ```
703
-
704
- Sizing rules in inline mode:
705
-
706
- - The avatar fills your container's width and height.
707
- - If your container has **no explicit height**, an internal **4:5** ratio is used
708
- (matching the floating widget's 400×500 proportions) so the avatar is never invisible.
709
- - `view: "round"` always renders a **circle that fits the smaller side** and centers,
710
- regardless of the container's aspect ratio.
711
- - Video is cropped to cover (never stretched/distorted).
712
-
713
- ```typescript
714
- // Width-only container → height comes from the internal 4:5 fallback
715
- // <div id="avatar-box" style="width: 300px"></div>
716
- await NapsterCompanionApiSdk.init(token, {
717
- mountContainer: "#avatar-box",
718
- layout: "inline",
719
- });
720
- ```
721
-
722
- ## 4. Event Handling
723
-
724
- The SDK provides several event callbacks for monitoring status and handling errors.
725
-
726
- ```typescript
727
- const instance = await NapsterCompanionApiSdk.init(token, {
728
- // Fires when the SDK is initialized and ready to use
729
- onReady: () => console.log("SDK ready!"),
730
- // Fires on any SDK error
731
- onError: error => console.error("SDK error:", error),
732
- // Fires when the avatar is fully loaded and ready
733
- onAvatarReady: isReady => console.log("Avatar ready:", isReady),
734
- // Fires when user inactivity status changes
735
- onInactivityStatusChange: isInactive => console.log("Inactive:", isInactive),
736
- // Fires when the SDK is destroyed
737
- onDestroy: () => console.log("SDK destroyed"),
738
- // Fires when data is received from the WEBRTC data channel
739
- onData: data => console.log("Data received:", data),
740
- });
741
- ```
742
-
743
- ---
744
-
745
- ## 5. API Reference
746
-
747
- ### 5.1 Core Methods
748
-
749
- #### `init(token: string, config?: NapsterCompanionApiConfig): Promise<NapsterCompanionApiInstance>`
750
-
751
- Initialize the SDK with authentication token and configuration.
752
-
753
- ```typescript
754
- const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
755
- mountContainer: "#avatar-container",
756
- position: "bottom-right",
757
- });
758
- ```
759
-
760
- #### `showAvatar(): void`
761
-
762
- Make the avatar visible on screen.
763
-
764
- ```typescript
765
- instance.showAvatar();
766
- ```
767
-
768
- #### `hideAvatar(): void`
769
-
770
- Hide the avatar from screen.
771
-
772
- ```typescript
773
- instance.hideAvatar();
774
- ```
775
-
776
- #### `avatarIsVisible(): boolean`
777
-
778
- Check if the avatar is currently visible.
779
-
780
- ```typescript
781
- if (instance.avatarIsVisible()) {
782
- console.log("Avatar is visible");
783
- }
784
- ```
785
-
786
- #### `destroy(): void`
787
-
788
- Cleanup and remove the SDK completely.
789
-
790
- ```typescript
791
- instance.destroy();
792
- ```
793
-
794
- ### 5.2 Styling & Position Methods
795
-
796
- #### `updateStyles(styles: StyleObject): void`
797
-
798
- Update container styles dynamically.
799
-
800
- ```typescript
801
- instance.updateStyles({
802
- top: "50px",
803
- left: "50px",
804
- opacity: "0.8",
805
- });
806
- ```
807
-
808
- #### `setPosition(position: Position): void`
809
-
810
- Change avatar position on screen.
811
-
812
- ```typescript
813
- instance.setPosition("top-left");
814
- // or using enum
815
- import { Position } from "@touchcastllc/napster-companion-api";
816
- instance.setPosition(Position.TOP_LEFT);
817
- ```
818
-
819
- #### `clearPosition(): void`
820
-
821
- Reset position to default/configured value.
822
-
823
- ```typescript
824
- instance.clearPosition();
825
- ```
826
-
827
- ### 5.3 Feature Control Methods
828
-
829
- #### `enableFeature(feature: string): void`
830
-
831
- Enable a specific feature.
832
-
833
- ```typescript
834
- instance.enableFeature("disclaimer");
835
- ```
836
-
837
- #### `disableFeature(feature: string): void`
838
-
839
- Disable a specific feature.
840
-
841
- ```typescript
842
- instance.disableFeature("disclaimer");
843
- ```
844
-
845
- #### `isFeatureEnabled(feature: string): boolean`
846
-
847
- Check if a feature is currently enabled.
848
-
849
- ```typescript
850
- if (instance.isFeatureEnabled("disclaimer")) {
851
- console.log("Disclaimer is enabled");
852
- }
853
- ```
854
-
855
- ### 5.4 Screen Sharing Methods
856
-
857
- #### `startScreenShare(): Promise<void>`
858
-
859
- Start screen sharing. Opens the browser's screen picker and begins streaming frames to the avatar.
860
-
861
- ```typescript
862
- await instance.startScreenShare();
863
- ```
864
-
865
- > **Note:** Requires `features.screenShare.enabled = true` in the init config. Does nothing if already sharing.
866
-
867
- #### `stopScreenShare(): void`
868
-
869
- Stop screen sharing. Releases the display stream and notifies the server.
870
-
871
- ```typescript
872
- instance.stopScreenShare();
873
- ```
874
-
875
- #### `toggleScreenShare(): Promise<void>`
876
-
877
- Toggle screen sharing on or off.
878
-
879
- ```typescript
880
- await instance.toggleScreenShare();
881
- ```
882
-
883
- #### `isScreenSharing: boolean` _(read-only)_
884
-
885
- Whether screen sharing is currently active.
886
-
887
- ```typescript
888
- if (instance.isScreenSharing) {
889
- console.log("User is sharing their screen");
890
- }
891
- ```
892
-
893
- #### `isScreenShareSupported: boolean` _(read-only)_
894
-
895
- Whether screen sharing is supported by the browser **and** enabled in the feature config.
896
-
897
- ```typescript
898
- if (instance.isScreenShareSupported) {
899
- showScreenShareButton();
900
- }
901
- ```
902
-
903
- ### 5.5 Communication Methods
904
-
905
- #### `sendCommand(command: { type: string; data?: object }): void`
906
-
907
- Send a command to the avatar via the data channel.
908
-
909
- ```typescript
910
- // Send a message to the avatar
911
- instance.sendCommand({ type: "send_message", data: { text: "Hello, how are you?" } });
912
-
913
- // Cancel the current response
914
- instance.sendCommand({ type: "cancel" });
915
- ```
916
-
917
- ### 5.6 Audio Control Methods
918
-
919
- Control the avatar's incoming WebRTC audio output (the avatar's voice the user hears). These methods operate on the underlying `<audio>` element and do not affect the user's microphone.
920
-
921
- #### `muteAudio(): void`
922
-
923
- Mute the avatar's audio output.
924
-
925
- ```typescript
926
- instance.muteAudio();
927
- ```
928
-
929
- #### `unmuteAudio(): void`
930
-
931
- Unmute the avatar's audio output.
932
-
933
- ```typescript
934
- instance.unmuteAudio();
935
- ```
936
-
937
- #### `isAudioMuted: boolean` (readonly)
938
-
939
- Whether the avatar's audio output is currently muted.
940
-
941
- ```typescript
942
- if (instance.isAudioMuted) {
943
- instance.unmuteAudio();
944
- }
945
- ```
946
-
947
- #### `setAudioVolume(volume: number): void`
948
-
949
- Set the avatar's audio output volume. Accepts a value in the range `0..1`; values outside the range are clamped.
950
-
951
- ```typescript
952
- instance.setAudioVolume(0.5); // 50% volume
953
- ```
954
-
955
- #### `getAudioVolume(): number`
956
-
957
- Get the current avatar audio output volume in the range `0..1`.
958
-
959
- ```typescript
960
- const volume = instance.getAudioVolume();
961
- ```
962
-
963
- ### 5.7 Microphone Control Methods
964
-
965
- Control the user's microphone input that is sent to the avatar.
966
-
967
- #### `muteMic(): void`
968
-
969
- Mute the user's microphone input.
970
-
971
- ```typescript
972
- instance.muteMic();
973
- ```
974
-
975
- #### `unmuteMic(): void`
976
-
977
- Unmute the user's microphone input.
978
-
979
- ```typescript
980
- instance.unmuteMic();
981
- ```
982
-
983
- #### `isMicMuted: boolean` (readonly)
984
-
985
- Whether the user's microphone is currently muted.
986
-
987
- ```typescript
988
- if (instance.isMicMuted) {
989
- instance.unmuteMic();
990
- }
991
- ```
992
-
993
- ### 5.8 Avatar Speech Control Methods
994
-
995
- Interrupt the avatar's response and inspect speaking state for both sides of the conversation.
996
-
997
- #### `stopAvatarTalking(): void`
998
-
999
- Interrupt the avatar's current response so it stops talking. Sends a `cancel` command over the data channel.
1000
-
1001
- ```typescript
1002
- instance.stopAvatarTalking();
1003
- ```
1004
-
1005
- #### `isAvatarSpeaking: boolean` (readonly)
1006
-
1007
- Whether the avatar is currently speaking.
1008
-
1009
- ```typescript
1010
- if (instance.isAvatarSpeaking) {
1011
- instance.stopAvatarTalking();
1012
- }
1013
- ```
1014
-
1015
- #### `isUserTalking: boolean` (readonly)
1016
-
1017
- Whether the user is currently talking (detected from the microphone input).
1018
-
1019
- ```typescript
1020
- if (instance.isUserTalking) {
1021
- // e.g. dim a "push to talk" indicator
1022
- }
1023
- ```
1024
-
1025
- ## 6. Configuration Interface
1026
-
1027
- ```typescript
1028
- interface NapsterCompanionApiConfig {
1029
- // Container mounting
1030
- mountContainer?: HTMLElement | string | null;
1031
-
1032
- // Layout mode:
1033
- // - "fixed" (default) floating corner widget, anchored via `position`
1034
- // - "inline" renders inside `mountContainer` and fills it (`position` ignored)
1035
- layout?: "fixed" | "inline";
1036
-
1037
- // Positioning (fixed layout only)
1038
- position?:
1039
- | "bottom-right"
1040
- | "bottom-left"
1041
- | "bottom-center"
1042
- | "top-right"
1043
- | "top-left"
1044
- | "top-center"
1045
- | "center";
1046
-
1047
- // Styling
1048
- style?: StyleObject;
1049
- className?: string;
1050
- avatarStyle?: {
1051
- view: "round" | "rectangle" | "silhouette";
1052
- borderWidth?: string;
1053
- borderColor?: string;
1054
- borderStyle?: string;
1055
- };
1056
-
1057
- // Features
1058
- features?: {
1059
- backgroundRemoval?: { enabled: boolean };
1060
- inactiveTimeout?: {
1061
- enabled: boolean;
1062
- duration?: number; // max: 180000ms
1063
- countdown?: number; // max: 60s
1064
- };
1065
- disclaimer?: { enabled: boolean; text?: string };
1066
- showSDKLoader?: {
1067
- enabled: boolean;
1068
- bgColor?: string; // background color of loader overlay
1069
- color?: string; // color of the loader animation
1070
- type?: "spinner" | "pulse"; // animation type
1071
- className?: string; // CSS class name for custom loader styles
1072
- };
1073
- pictureInPicture?: {
1074
- enabled: boolean;
1075
- width?: number; // default 400
1076
- height?: number; // default 300
1077
- };
1078
- screenShare?: { enabled: boolean };
1079
- controls?: { enabled: boolean };
1080
- };
1081
-
1082
- // Configuration
1083
- debug?: boolean;
1084
-
1085
- // Event callbacks
1086
- onReady?: () => void;
1087
- onError?: (error: Error) => void;
1088
- onData?: (data: EventMessage) => void;
1089
- onAvatarReady?: (isReady?: boolean) => void;
1090
- onInactivityStatusChange?: (isInactive: boolean) => void;
1091
- onDestroy?: () => void;
1092
- onFeaturesUpdate?: (features: FeatureConfig) => void;
1093
- }
1094
- ```
1095
-
1096
- ---
1097
-
1098
- ## 7. Troubleshooting
1099
-
1100
- ### 7.1 Common Issues
1101
-
1102
- **Problem: "Module not found" Error**
1103
- **Solution:**
1104
-
1105
- ```bash
1106
- # Ensure package is installed
1107
- npm install @touchcastllc/napster-companion-api
1108
-
1109
- # Install peer dependencies
1110
- npm install @reduxjs/toolkit
1111
- ```
1112
-
1113
- **Problem: Invalid or expired token**
1114
- **Solution:**
1115
-
1116
- - Generate new token from backend API
1117
- - Ensure token is passed correctly to `init()`
1118
-
1119
- **Problem: Avatar appears unstyled**
1120
- **Solution:**
1121
-
1122
- See the style import guide from [1.2.1 Installation & Setup](#121-for-esm-build-type-recommended)
1123
-
1124
- **Problem:** `mountContainer` element doesn't exist
1125
- **Solution:**
1126
-
1127
- ```typescript
1128
- // Wait for DOM to load
1129
- document.addEventListener("DOMContentLoaded", async () => {
1130
- const instance = await NapsterCompanionApiSdk.init(token, {
1131
- mountContainer: "#avatar-container", // Ensure element exists
1132
- });
1133
- });
1134
- ```
1135
-
1136
- ### 7.2 Debug Mode
1137
-
1138
- Enable debug logging:
1139
-
1140
- ```typescript
1141
- const instance = await NapsterCompanionApiSdk.init(token, {
1142
- debug: true, // Enable debug logs
1143
- onError: error => console.error("SDK Error:", error),
1144
- onData: data => console.log("SDK Data:", data),
1145
- });
1146
- ```
1147
-
1148
- ### 7.3 Performance Issues
1149
-
1150
- #### Large Bundle Size
1151
-
1152
- - Use ESM build instead of standalone
1153
- - Import only needed features
1154
- - Enable tree-shaking in bundler
1155
-
1156
- #### Memory Leaks
1157
-
1158
- ```typescript
1159
- // Always cleanup when done
1160
- useEffect(() => {
1161
- return () => {
1162
- instance?.destroy();
1163
- };
1164
- }, [instance]);
1165
- ```
61
+ ## Support
1166
62
 
1167
- ---
63
+ - **Documentation:** [developers.napster.com/docs/sdks/web-sdk/overview](https://developers.napster.com/docs/sdks/web-sdk/overview)
64
+ - **Package:** [npmjs.com/package/@touchcastllc/napster-companion-api](https://www.npmjs.com/package/@touchcastllc/napster-companion-api)
1168
65
 
1169
66
  ## License
1170
67
 
1171
- This project is licensed under the MIT License - see the [LICENSE](/LICENSE) file for details.
68
+ MIT see [LICENSE](LICENSE).