synxed-sdk 0.2.5 → 0.2.6
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 +109 -126
- package/dist/index.d.mts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,198 +1,181 @@
|
|
|
1
1
|
# Synxed SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Add Synxed music to your website or app in a few minutes — playlists, live radio, voice commands, and a ready-made player UI.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/synxed-sdk)
|
|
6
|
-
[](https://www.typescriptlang.org/)
|
|
7
6
|
|
|
8
|
-
##
|
|
7
|
+
## What you need
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- **Framework-agnostic core**: `SynxedPlayer` works in React, Vue, Angular, or vanilla JS.
|
|
14
|
-
- **Optional web UI**: Vanilla DOM overlay (`SynxedWebPlayer`) with **mini**, **wide**, and **large** layouts — works in any framework; **theme** and **placement** are fully configurable.
|
|
15
|
-
- **Type-safe**: Written in TypeScript with full definitions.
|
|
9
|
+
1. A **Synxed API key** (from your Synxed developer account `https://portal.synxed.com`).
|
|
10
|
+
2. Your **API URL** (Our api url: `https://api.synxed.com`).
|
|
11
|
+
3. A **playlist code**, **Single Song** or choose **live radio**.
|
|
16
12
|
|
|
17
|
-
##
|
|
13
|
+
## Install
|
|
18
14
|
|
|
19
15
|
```bash
|
|
20
16
|
npm install synxed-sdk
|
|
21
17
|
```
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
## Easiest setup — built-in player
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
npm install hls.js
|
|
27
|
-
```
|
|
21
|
+
This adds a floating music bar to your page. No React or special framework required.
|
|
28
22
|
|
|
29
|
-
|
|
23
|
+
### Play a playlist
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
```html
|
|
26
|
+
<script type="module">
|
|
27
|
+
import { SynxedWebPlayer } from "synxed-sdk";
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
SynxedWebPlayer.mount({
|
|
30
|
+
apiKey: "YOUR_SYNXED_API_KEY",
|
|
31
|
+
serverUrl: "https://api.synxed.com",
|
|
32
|
+
source: { type: "playlist", playlistCode: "sxpl_YOUR_CODE" },
|
|
33
|
+
});
|
|
34
|
+
</script>
|
|
35
|
+
```
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
### Play live radio
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
SynxedWebPlayer.mount({
|
|
37
41
|
apiKey: "YOUR_SYNXED_API_KEY",
|
|
38
42
|
serverUrl: "https://api.synxed.com",
|
|
39
|
-
|
|
43
|
+
source: { type: "radio" },
|
|
40
44
|
});
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
###
|
|
47
|
+
### Put the player inside your own box
|
|
44
48
|
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
```javascript
|
|
50
|
+
SynxedWebPlayer.mount({
|
|
51
|
+
container: document.getElementById("my-player"),
|
|
52
|
+
apiKey: "YOUR_SYNXED_API_KEY",
|
|
53
|
+
serverUrl: "https://api.synxed.com",
|
|
54
|
+
source: { type: "playlist", playlistCode: "sxpl_YOUR_CODE" },
|
|
48
55
|
});
|
|
49
56
|
```
|
|
50
57
|
|
|
51
|
-
|
|
58
|
+
## Player sizes
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
| Mode | What it looks like |
|
|
61
|
+
| ------- | ------------------------------- |
|
|
62
|
+
| `wide` | Bar across the bottom (default) |
|
|
63
|
+
| `mini` | Small round DJ button |
|
|
64
|
+
| `large` | Bigger card with visualizer |
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
```javascript
|
|
67
|
+
SynxedWebPlayer.mount({
|
|
68
|
+
apiKey: "...",
|
|
69
|
+
serverUrl: "...",
|
|
70
|
+
source: { type: "playlist", playlistCode: "sxpl_..." },
|
|
71
|
+
mode: "mini",
|
|
60
72
|
});
|
|
61
73
|
```
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Continuous **non-HLS** stream (not seekable). The SDK sends `CONTENT_KIND_RADIO` (`4`) over the same native `/sdk` WebSocket; the server returns a direct `playbackUrl` (e.g. MPEG stream).
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
await player.playRadio({ listenerId: "optional-stable-id" });
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
- **`skip` / `previous` / `skipTo` / `seek`**: no-ops for radio (the live edge keeps moving on the server).
|
|
72
|
-
- **`pause` / `resume`**: local audio only; when the user resumes, they rejoin the live stream.
|
|
73
|
-
- **Metadata**: poll the REST endpoint (unauthenticated on most deployments):
|
|
75
|
+
## Move the player on screen
|
|
74
76
|
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
// { title, station?, isLive? } — poll every 10–15s for “now playing” UI
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Optional web player UI (vanilla — no React required)
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
import { SynxedWebPlayer } from "synxed-sdk";
|
|
86
|
-
|
|
87
|
-
const ui = SynxedWebPlayer.mount({
|
|
88
|
-
apiKey: "YOUR_SYNXED_API_KEY",
|
|
89
|
-
serverUrl: "https://api.synxed.com",
|
|
77
|
+
```javascript
|
|
78
|
+
SynxedWebPlayer.mount({
|
|
79
|
+
apiKey: "...",
|
|
80
|
+
serverUrl: "...",
|
|
90
81
|
source: { type: "radio" },
|
|
91
|
-
mode: "wide",
|
|
92
|
-
attribution: "DJ Jesse · Synxed × Your Brand",
|
|
93
|
-
theme: {
|
|
94
|
-
accent: "#ef4444",
|
|
95
|
-
glow: "rgba(239, 68, 68, 0.35)",
|
|
96
|
-
background: "#0a0707",
|
|
97
|
-
},
|
|
98
82
|
position: { placement: "top-left", offsetX: 16, offsetY: 16 },
|
|
99
83
|
draggable: true,
|
|
100
84
|
});
|
|
101
|
-
|
|
102
|
-
// Later: ui.destroy();
|
|
103
85
|
```
|
|
104
86
|
|
|
105
|
-
|
|
87
|
+
## Match your brand colors
|
|
106
88
|
|
|
107
|
-
```
|
|
89
|
+
```javascript
|
|
108
90
|
SynxedWebPlayer.mount({
|
|
109
|
-
container: document.getElementById("player-slot")!,
|
|
110
91
|
apiKey: "...",
|
|
111
92
|
serverUrl: "...",
|
|
112
93
|
source: { type: "playlist", playlistCode: "sxpl_..." },
|
|
94
|
+
theme: {
|
|
95
|
+
accent: "#22c55e",
|
|
96
|
+
background: "#0a0a0a",
|
|
97
|
+
glow: "rgba(34, 197, 94, 0.35)",
|
|
98
|
+
},
|
|
113
99
|
});
|
|
114
100
|
```
|
|
115
101
|
|
|
116
|
-
|
|
117
|
-
|
|
102
|
+
## Talk to the DJ (voice playlists)
|
|
103
|
+
|
|
104
|
+
**Hold** the Synxed DJ avatar (the spinning circle) and say what you want to hear — for example _“play upbeat workout songs”_.
|
|
118
105
|
|
|
119
|
-
|
|
106
|
+
- **Tap** the DJ → play or pause the music.
|
|
107
|
+
- **Hold** the DJ → speak your request; release when done (or stop talking and it sends automatically).
|
|
108
|
+
- While you speak, the DJ icon switches to the AI listening view.
|
|
109
|
+
- Music pauses while you talk and can resume when you tap again.
|
|
120
110
|
|
|
121
|
-
|
|
111
|
+
To turn voice off:
|
|
122
112
|
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
player.setVolume(0.8);
|
|
129
|
-
player.skip();
|
|
130
|
-
player.previous();
|
|
131
|
-
player.skipTo(2);
|
|
113
|
+
```javascript
|
|
114
|
+
SynxedWebPlayer.mount({
|
|
115
|
+
enableVoice: false,
|
|
116
|
+
// ...other options
|
|
117
|
+
});
|
|
132
118
|
```
|
|
133
119
|
|
|
134
|
-
##
|
|
120
|
+
## Skip button and ads
|
|
135
121
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
});
|
|
122
|
+
- During normal playback, the **skip** button jumps to the next song.
|
|
123
|
+
- During an ad, the same button shows a **short countdown** (about 5 seconds), then you can skip the ad.
|
|
124
|
+
- After the ad, the skip button works again for the next song.
|
|
140
125
|
|
|
141
|
-
|
|
142
|
-
const progress = (currentTime / duration) * 100;
|
|
143
|
-
console.log(`Progress: ${progress.toFixed(2)}%`);
|
|
144
|
-
});
|
|
126
|
+
## Build your own UI (optional)
|
|
145
127
|
|
|
146
|
-
|
|
147
|
-
console.error("Playback Error:", err.message);
|
|
148
|
-
});
|
|
149
|
-
```
|
|
128
|
+
If you want full control over buttons and layout, use `SynxedPlayer` instead of `SynxedWebPlayer`:
|
|
150
129
|
|
|
151
|
-
|
|
130
|
+
```javascript
|
|
131
|
+
import { SynxedPlayer } from "synxed-sdk";
|
|
152
132
|
|
|
153
|
-
|
|
133
|
+
const player = new SynxedPlayer({
|
|
134
|
+
apiKey: "YOUR_SYNXED_API_KEY",
|
|
135
|
+
serverUrl: "https://api.synxed.com",
|
|
136
|
+
autoConnect: true,
|
|
137
|
+
});
|
|
154
138
|
|
|
155
|
-
|
|
156
|
-
- `serverUrl`: `string` (required)
|
|
157
|
-
- `autoConnect`: `boolean` (default `true`)
|
|
139
|
+
await player.playPlaylist({ playlistCode: "sxpl_YOUR_CODE" });
|
|
158
140
|
|
|
159
|
-
|
|
141
|
+
document.getElementById("play").onclick = () => player.resume();
|
|
142
|
+
document.getElementById("pause").onclick = () => player.pause();
|
|
143
|
+
document.getElementById("skip").onclick = () => player.skip();
|
|
144
|
+
```
|
|
160
145
|
|
|
161
|
-
|
|
162
|
-
- `playPlaylist(options)`: `Promise<void>`
|
|
163
|
-
- `playRadio(options?)`: `Promise<void>` — live radio (`listenerId` optional)
|
|
164
|
-
- `pause()` / `resume()` / `stop()`
|
|
165
|
-
- `skip()` / `previous()` / `skipTo(index)` — playlist / on-demand only
|
|
166
|
-
- `seek(ms)` — on-demand only (no-op for radio)
|
|
167
|
-
- `setVolume(0–1)`
|
|
168
|
-
- `destroy()`
|
|
146
|
+
### Voice with your own buttons
|
|
169
147
|
|
|
170
|
-
|
|
148
|
+
```javascript
|
|
149
|
+
const dj = document.getElementById("dj-avatar");
|
|
171
150
|
|
|
172
|
-
|
|
173
|
-
|
|
151
|
+
dj.addEventListener("pointerdown", () => player.beginVoiceHold());
|
|
152
|
+
dj.addEventListener("pointerup", () => player.endVoiceHold());
|
|
153
|
+
```
|
|
174
154
|
|
|
175
|
-
|
|
155
|
+
## Clean up when leaving the page
|
|
176
156
|
|
|
177
|
-
|
|
157
|
+
```javascript
|
|
158
|
+
const ui = SynxedWebPlayer.mount({
|
|
159
|
+
/* ... */
|
|
160
|
+
});
|
|
178
161
|
|
|
179
|
-
|
|
162
|
+
// When your app unmounts or navigates away:
|
|
163
|
+
ui.destroy();
|
|
164
|
+
```
|
|
180
165
|
|
|
181
|
-
|
|
166
|
+
## Radio “now playing” title
|
|
182
167
|
|
|
183
|
-
|
|
168
|
+
For radio, you can show the current song name on your own label:
|
|
184
169
|
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
artist?: string;
|
|
191
|
-
duration?: number;
|
|
192
|
-
albumArt?: string;
|
|
193
|
-
}
|
|
170
|
+
```javascript
|
|
171
|
+
import { fetchRadioNowPlaying } from "synxed-sdk";
|
|
172
|
+
|
|
173
|
+
const info = await fetchRadioNowPlaying("https://api.synxed.com");
|
|
174
|
+
if (info) console.log(info.title);
|
|
194
175
|
```
|
|
195
176
|
|
|
177
|
+
Poll every 10–15 seconds to keep the title fresh.
|
|
178
|
+
|
|
196
179
|
## License
|
|
197
180
|
|
|
198
181
|
Copyright © [Synxed.com](https://synxed.com)
|
package/dist/index.d.mts
CHANGED
|
@@ -344,8 +344,6 @@ interface SynxedWebPlayerOptions {
|
|
|
344
344
|
mode?: SynxedWebPlayerMode;
|
|
345
345
|
theme?: SynxedWebPlayerTheme;
|
|
346
346
|
position?: SynxedWebPlayerPosition;
|
|
347
|
-
avatarUrl?: string;
|
|
348
|
-
voiceAvatarUrl?: string;
|
|
349
347
|
attribution?: string;
|
|
350
348
|
nowPlayingPollMs?: number;
|
|
351
349
|
powerByLabel?: string;
|
|
@@ -393,6 +391,8 @@ declare class SynxedWebPlayer {
|
|
|
393
391
|
private voiceUiDismissed;
|
|
394
392
|
private voiceHoldTimer;
|
|
395
393
|
private readonly defaultVoiceHoldMs;
|
|
394
|
+
/** Avatar to restore after an ad (DJ / album art — not ad or voice AI). */
|
|
395
|
+
private avatarImageBeforeAd;
|
|
396
396
|
constructor(options: SynxedWebPlayerOptions);
|
|
397
397
|
/** Convenience factory — same as `new SynxedWebPlayer(options)`. */
|
|
398
398
|
static mount(options: SynxedWebPlayerOptions): SynxedWebPlayer;
|
|
@@ -422,14 +422,17 @@ declare class SynxedWebPlayer {
|
|
|
422
422
|
private resetVoiceHoldState;
|
|
423
423
|
private applyVoiceVisual;
|
|
424
424
|
private isVoiceAvatarActive;
|
|
425
|
+
private getContentAvatarUrl;
|
|
425
426
|
private getAvatarImageUrl;
|
|
426
427
|
private refreshAvatarImage;
|
|
427
428
|
private startNowPlayingPoll;
|
|
428
429
|
private stopNowPlayingPoll;
|
|
429
430
|
private handleSkipClick;
|
|
430
|
-
/**
|
|
431
|
+
/**
|
|
432
|
+
* During ads: swap skip icon for countdown text in the same control (no style changes).
|
|
433
|
+
* After ads: restore skip icon for the next track.
|
|
434
|
+
*/
|
|
431
435
|
private applyAdSkipUi;
|
|
432
|
-
private clearAdSkipStyleOverrides;
|
|
433
436
|
private restoreTrackSkipButton;
|
|
434
437
|
private displayLine;
|
|
435
438
|
private refreshLabels;
|
package/dist/index.d.ts
CHANGED
|
@@ -344,8 +344,6 @@ interface SynxedWebPlayerOptions {
|
|
|
344
344
|
mode?: SynxedWebPlayerMode;
|
|
345
345
|
theme?: SynxedWebPlayerTheme;
|
|
346
346
|
position?: SynxedWebPlayerPosition;
|
|
347
|
-
avatarUrl?: string;
|
|
348
|
-
voiceAvatarUrl?: string;
|
|
349
347
|
attribution?: string;
|
|
350
348
|
nowPlayingPollMs?: number;
|
|
351
349
|
powerByLabel?: string;
|
|
@@ -393,6 +391,8 @@ declare class SynxedWebPlayer {
|
|
|
393
391
|
private voiceUiDismissed;
|
|
394
392
|
private voiceHoldTimer;
|
|
395
393
|
private readonly defaultVoiceHoldMs;
|
|
394
|
+
/** Avatar to restore after an ad (DJ / album art — not ad or voice AI). */
|
|
395
|
+
private avatarImageBeforeAd;
|
|
396
396
|
constructor(options: SynxedWebPlayerOptions);
|
|
397
397
|
/** Convenience factory — same as `new SynxedWebPlayer(options)`. */
|
|
398
398
|
static mount(options: SynxedWebPlayerOptions): SynxedWebPlayer;
|
|
@@ -422,14 +422,17 @@ declare class SynxedWebPlayer {
|
|
|
422
422
|
private resetVoiceHoldState;
|
|
423
423
|
private applyVoiceVisual;
|
|
424
424
|
private isVoiceAvatarActive;
|
|
425
|
+
private getContentAvatarUrl;
|
|
425
426
|
private getAvatarImageUrl;
|
|
426
427
|
private refreshAvatarImage;
|
|
427
428
|
private startNowPlayingPoll;
|
|
428
429
|
private stopNowPlayingPoll;
|
|
429
430
|
private handleSkipClick;
|
|
430
|
-
/**
|
|
431
|
+
/**
|
|
432
|
+
* During ads: swap skip icon for countdown text in the same control (no style changes).
|
|
433
|
+
* After ads: restore skip icon for the next track.
|
|
434
|
+
*/
|
|
431
435
|
private applyAdSkipUi;
|
|
432
|
-
private clearAdSkipStyleOverrides;
|
|
433
436
|
private restoreTrackSkipButton;
|
|
434
437
|
private displayLine;
|
|
435
438
|
private refreshLabels;
|