@pie-players/pie-section-player-tools-tts-settings 0.3.20
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 +220 -0
- package/TtsSettingsPanel.svelte +1813 -0
- package/dist/TtsSettingsPanel.svelte.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/pie-section-player-tools-tts-settings.css +2 -0
- package/dist/section-player-tools-tts-settings.js +3802 -0
- package/dist/vite.config.d.ts +3 -0
- package/dist/vite.config.d.ts.map +1 -0
- package/index.ts +10 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# @pie-players/pie-section-player-tools-tts-settings
|
|
2
|
+
|
|
3
|
+
Reusable TTS settings development panel for section-player consumers.
|
|
4
|
+
|
|
5
|
+
This package follows the same integration model as the other `section-player-tools-*` panels:
|
|
6
|
+
|
|
7
|
+
- side-effect import to register a custom element
|
|
8
|
+
- render the element tag where your app manages debug overlays
|
|
9
|
+
|
|
10
|
+
## Install and register
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import "@pie-players/pie-section-player-tools-tts-settings";
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Render
|
|
17
|
+
|
|
18
|
+
```svelte
|
|
19
|
+
<pie-section-player-tools-tts-settings
|
|
20
|
+
toolkitCoordinator={toolkitCoordinator}
|
|
21
|
+
onclose={() => (showTtsPanel = false)}
|
|
22
|
+
/>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Default behavior
|
|
26
|
+
|
|
27
|
+
Without adapters, the panel uses the existing route contract:
|
|
28
|
+
|
|
29
|
+
- base endpoint: `/api/tts`
|
|
30
|
+
- voices routes:
|
|
31
|
+
- `GET {base}/polly/voices`
|
|
32
|
+
- `GET {base}/google/voices`
|
|
33
|
+
- synthesize route:
|
|
34
|
+
- `POST {base}/synthesize`
|
|
35
|
+
|
|
36
|
+
and applies settings via toolkit coordinator:
|
|
37
|
+
|
|
38
|
+
- `getToolConfig("tts")`
|
|
39
|
+
- `updateToolConfig("tts", ...)`
|
|
40
|
+
- optional `ensureTTSReady(...)`
|
|
41
|
+
|
|
42
|
+
## Custom element API
|
|
43
|
+
|
|
44
|
+
### Attributes / props
|
|
45
|
+
|
|
46
|
+
- `toolkitCoordinator` (`Object`): assessment toolkit coordinator instance
|
|
47
|
+
- `apiEndpoint` (`String`, default `/api/tts`): base endpoint for voice/synthesis routes
|
|
48
|
+
- `storageKey` (`String`, default `pie:section-player-tools:tts-settings`): localStorage key
|
|
49
|
+
- `adapters` (`Object`, optional): override fetching/synthesis behavior
|
|
50
|
+
- `customProviders` (`Array`, optional): register additional provider tabs (JS adapters and/or custom elements)
|
|
51
|
+
|
|
52
|
+
### Events
|
|
53
|
+
|
|
54
|
+
- `close`: emitted when the panel requests to close
|
|
55
|
+
|
|
56
|
+
Example:
|
|
57
|
+
|
|
58
|
+
```svelte
|
|
59
|
+
<pie-section-player-tools-tts-settings
|
|
60
|
+
toolkitCoordinator={toolkitCoordinator}
|
|
61
|
+
apiEndpoint="/internal/tts"
|
|
62
|
+
storageKey="my-app:dev-panels:tts"
|
|
63
|
+
onclose={handleClose}
|
|
64
|
+
/>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Adapter overrides
|
|
68
|
+
|
|
69
|
+
Use adapters when your host app cannot or should not expose the default route contract.
|
|
70
|
+
|
|
71
|
+
## Custom provider tabs
|
|
72
|
+
|
|
73
|
+
You can add provider tabs beyond Browser/Polly/Google through `customProviders`.
|
|
74
|
+
|
|
75
|
+
- Keep provider `id` unique and avoid reserved ids: `browser`, `polly`, `google`.
|
|
76
|
+
- The panel still owns persistence and `updateToolConfig("tts", ...)`.
|
|
77
|
+
- Provider apply returns normalized output: `{ config, message? }`.
|
|
78
|
+
|
|
79
|
+
### JS adapter mode
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const customProviders = [
|
|
83
|
+
{
|
|
84
|
+
id: "acme-tts",
|
|
85
|
+
label: "Acme TTS",
|
|
86
|
+
mode: "adapter",
|
|
87
|
+
initialState: { voice: "acme-default", quality: "high" },
|
|
88
|
+
async checkAvailability({ apiEndpoint }) {
|
|
89
|
+
const response = await fetch(`${apiEndpoint}/acme/health`);
|
|
90
|
+
return {
|
|
91
|
+
available: response.ok,
|
|
92
|
+
message: response.ok ? "Acme provider available." : "Acme provider unavailable."
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
async buildApplyConfig({ state, apiEndpoint }) {
|
|
96
|
+
return {
|
|
97
|
+
config: {
|
|
98
|
+
backend: "acme-tts",
|
|
99
|
+
transportMode: "custom",
|
|
100
|
+
apiEndpoint,
|
|
101
|
+
defaultVoice: state.voice,
|
|
102
|
+
providerOptions: { quality: state.quality }
|
|
103
|
+
},
|
|
104
|
+
message: "Applied Acme TTS settings."
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
];
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Custom element mode (CE bridge)
|
|
112
|
+
|
|
113
|
+
`mode: "component"` providers can emit normalized events that the panel consumes:
|
|
114
|
+
|
|
115
|
+
- `change` with `detail: { state: Record<string, unknown> }`
|
|
116
|
+
- `availability` with `detail: { available: boolean, message?: string, detail?: string }`
|
|
117
|
+
- `apply-request` with `detail: { config: Record<string, unknown>, message?: string }`
|
|
118
|
+
- `preview-request` (panel triggers provider `preview` hook if supplied)
|
|
119
|
+
|
|
120
|
+
Example descriptor:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
const customProviders = [
|
|
124
|
+
{
|
|
125
|
+
id: "vendor-x",
|
|
126
|
+
label: "Vendor X",
|
|
127
|
+
mode: "component",
|
|
128
|
+
tagName: "my-vendor-tts-provider-tab",
|
|
129
|
+
componentProps: { tenant: "district-a" },
|
|
130
|
+
async buildApplyConfig({ state, apiEndpoint }) {
|
|
131
|
+
return {
|
|
132
|
+
config: {
|
|
133
|
+
backend: "vendor-x",
|
|
134
|
+
transportMode: "custom",
|
|
135
|
+
apiEndpoint,
|
|
136
|
+
providerOptions: state
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
];
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Adapter shape
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
type TtsSettingsAdapters = {
|
|
148
|
+
fetchPollyVoices?: (args: {
|
|
149
|
+
endpoint: string;
|
|
150
|
+
language: string;
|
|
151
|
+
gender: string;
|
|
152
|
+
engine: "standard" | "neural";
|
|
153
|
+
url: URL;
|
|
154
|
+
}) => Promise<Array<{ id?: string; name?: string; languageCode?: string; gender?: string }>>;
|
|
155
|
+
fetchGoogleVoices?: (args: {
|
|
156
|
+
endpoint: string;
|
|
157
|
+
language: string;
|
|
158
|
+
gender: string;
|
|
159
|
+
voiceType: string;
|
|
160
|
+
url: URL;
|
|
161
|
+
}) => Promise<Array<{ id?: string; name?: string; languageCode?: string; gender?: string }>>;
|
|
162
|
+
synthesizeProbe?: (args: {
|
|
163
|
+
endpoint: string;
|
|
164
|
+
provider: "polly" | "google";
|
|
165
|
+
body: Record<string, unknown>;
|
|
166
|
+
}) => Promise<{
|
|
167
|
+
audio: string;
|
|
168
|
+
contentType?: string;
|
|
169
|
+
speechMarks?: Array<{ time: number; start: number; end: number }>;
|
|
170
|
+
}>;
|
|
171
|
+
};
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Example with custom adapters
|
|
175
|
+
|
|
176
|
+
```svelte
|
|
177
|
+
<script lang="ts">
|
|
178
|
+
import "@pie-players/pie-section-player-tools-tts-settings";
|
|
179
|
+
|
|
180
|
+
const adapters = {
|
|
181
|
+
async fetchPollyVoices({ endpoint, language, gender, engine }) {
|
|
182
|
+
const response = await fetch(`${endpoint}/providers/polly/voices`, {
|
|
183
|
+
method: "POST",
|
|
184
|
+
headers: { "Content-Type": "application/json" },
|
|
185
|
+
body: JSON.stringify({ language, gender, engine })
|
|
186
|
+
});
|
|
187
|
+
const payload = await response.json();
|
|
188
|
+
return Array.isArray(payload?.voices) ? payload.voices : [];
|
|
189
|
+
},
|
|
190
|
+
async fetchGoogleVoices({ endpoint, language, gender, voiceType }) {
|
|
191
|
+
const response = await fetch(`${endpoint}/providers/google/voices`, {
|
|
192
|
+
method: "POST",
|
|
193
|
+
headers: { "Content-Type": "application/json" },
|
|
194
|
+
body: JSON.stringify({ language, gender, voiceType })
|
|
195
|
+
});
|
|
196
|
+
const payload = await response.json();
|
|
197
|
+
return Array.isArray(payload?.voices) ? payload.voices : [];
|
|
198
|
+
},
|
|
199
|
+
async synthesizeProbe({ endpoint, provider, body }) {
|
|
200
|
+
const response = await fetch(`${endpoint}/providers/${provider}/preview`, {
|
|
201
|
+
method: "POST",
|
|
202
|
+
headers: { "Content-Type": "application/json" },
|
|
203
|
+
body: JSON.stringify(body)
|
|
204
|
+
});
|
|
205
|
+
if (!response.ok) {
|
|
206
|
+
const payload = await response.json().catch(() => ({}));
|
|
207
|
+
throw new Error(payload?.message || `Preview failed (${response.status})`);
|
|
208
|
+
}
|
|
209
|
+
return response.json();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
</script>
|
|
213
|
+
|
|
214
|
+
<pie-section-player-tools-tts-settings
|
|
215
|
+
toolkitCoordinator={toolkitCoordinator}
|
|
216
|
+
apiEndpoint="/tts-gateway"
|
|
217
|
+
{adapters}
|
|
218
|
+
onclose={() => (showTtsPanel = false)}
|
|
219
|
+
/>
|
|
220
|
+
```
|