@lokutor/sdk 1.2.1 → 1.2.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/dist/index.d.mts +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.js +6 -26
- package/dist/index.mjs +6 -26
- package/package.json +1 -1
- package/src/client.ts +4 -4
- package/src/conversational-panel.ts +4 -23
package/dist/index.d.mts
CHANGED
|
@@ -827,7 +827,6 @@ declare class ConversationalPanel {
|
|
|
827
827
|
private startBtn;
|
|
828
828
|
private errorEl;
|
|
829
829
|
private errorText;
|
|
830
|
-
private timerEl;
|
|
831
830
|
private canvas;
|
|
832
831
|
private muteBtn;
|
|
833
832
|
private muteSvg;
|
|
@@ -863,7 +862,6 @@ declare class ConversationalPanel {
|
|
|
863
862
|
showError(text: string): void;
|
|
864
863
|
/** Destroy the component, removing all DOM and stopping any active session */
|
|
865
864
|
destroy(): void;
|
|
866
|
-
private fmt;
|
|
867
865
|
private startTimer;
|
|
868
866
|
private toggleMute;
|
|
869
867
|
private playConnectingSound;
|
package/dist/index.d.ts
CHANGED
|
@@ -827,7 +827,6 @@ declare class ConversationalPanel {
|
|
|
827
827
|
private startBtn;
|
|
828
828
|
private errorEl;
|
|
829
829
|
private errorText;
|
|
830
|
-
private timerEl;
|
|
831
830
|
private canvas;
|
|
832
831
|
private muteBtn;
|
|
833
832
|
private muteSvg;
|
|
@@ -863,7 +862,6 @@ declare class ConversationalPanel {
|
|
|
863
862
|
showError(text: string): void;
|
|
864
863
|
/** Destroy the component, removing all DOM and stopping any active session */
|
|
865
864
|
destroy(): void;
|
|
866
|
-
private fmt;
|
|
867
865
|
private startTimer;
|
|
868
866
|
private toggleMute;
|
|
869
867
|
private playConnectingSound;
|
package/dist/index.js
CHANGED
|
@@ -1318,7 +1318,7 @@ var TTSClient = class {
|
|
|
1318
1318
|
const req = {
|
|
1319
1319
|
text: options.text,
|
|
1320
1320
|
voice: options.voice || "F1" /* F1 */,
|
|
1321
|
-
|
|
1321
|
+
language: options.language || "en" /* ENGLISH */,
|
|
1322
1322
|
speed: options.speed || 1.05,
|
|
1323
1323
|
steps: options.steps || 24,
|
|
1324
1324
|
visemes: options.visemes || false
|
|
@@ -1407,7 +1407,7 @@ var STTClient = class {
|
|
|
1407
1407
|
if (typeof Blob !== "undefined" && options.audio instanceof Blob) {
|
|
1408
1408
|
const form = new FormData();
|
|
1409
1409
|
form.append("audio", options.audio, "audio.wav");
|
|
1410
|
-
if (options.language) form.append("
|
|
1410
|
+
if (options.language) form.append("language", options.language);
|
|
1411
1411
|
if (options.sampleRate) form.append("sample_rate", String(options.sampleRate));
|
|
1412
1412
|
res = await fetch(url, {
|
|
1413
1413
|
method: "POST",
|
|
@@ -1423,7 +1423,7 @@ var STTClient = class {
|
|
|
1423
1423
|
audio: uint8ArrayToBase64(bytes),
|
|
1424
1424
|
format: options.format || "pcm16",
|
|
1425
1425
|
sample_rate: options.sampleRate,
|
|
1426
|
-
|
|
1426
|
+
language: options.language
|
|
1427
1427
|
})
|
|
1428
1428
|
});
|
|
1429
1429
|
}
|
|
@@ -1495,7 +1495,7 @@ var SpeechToTextClient = class {
|
|
|
1495
1495
|
this.ws.onopen = async () => {
|
|
1496
1496
|
this.isConnected = true;
|
|
1497
1497
|
this.onStatusChange?.("connected");
|
|
1498
|
-
this.ws.send(JSON.stringify({
|
|
1498
|
+
this.ws.send(JSON.stringify({ language: this.language || "en" /* ENGLISH */, vad: this.vad }));
|
|
1499
1499
|
await this.audioManager.startMicrophone((data) => {
|
|
1500
1500
|
if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {
|
|
1501
1501
|
this.ws.send(data);
|
|
@@ -1765,12 +1765,6 @@ var PANEL_CSS = (
|
|
|
1765
1765
|
gap: 1rem;
|
|
1766
1766
|
letter-spacing: -0.02em;
|
|
1767
1767
|
}
|
|
1768
|
-
.cv-title .cv-timer {
|
|
1769
|
-
font-variant-numeric: tabular-nums;
|
|
1770
|
-
color: var(--cv-accent);
|
|
1771
|
-
font-weight: 400;
|
|
1772
|
-
opacity: 0.8;
|
|
1773
|
-
}
|
|
1774
1768
|
.cv-visualizer-wrap {
|
|
1775
1769
|
position: absolute;
|
|
1776
1770
|
top: 50%;
|
|
@@ -1919,7 +1913,6 @@ var PANEL_CSS = (
|
|
|
1919
1913
|
.cv-visualizer-wrap { width: 60px; height: 60px; }
|
|
1920
1914
|
.cv-header { padding-top: 0.75rem; }
|
|
1921
1915
|
.cv-title { font-size: 0.7rem; gap: 0.3rem; }
|
|
1922
|
-
.cv-title .cv-timer { display: none; }
|
|
1923
1916
|
.cv-controls { gap: 0.6rem; padding-bottom: 0.6rem; }
|
|
1924
1917
|
.cv-pill { padding: 0.15rem 0.4rem; gap: 0.3rem; }
|
|
1925
1918
|
.cv-btn { padding: 0.2rem 0.4rem; font-size: 0.6rem; gap: 0; }
|
|
@@ -1937,7 +1930,6 @@ var PANEL_CSS = (
|
|
|
1937
1930
|
.cv-visualizer-wrap { width: clamp(80px, 35cqw, 140px); height: clamp(80px, 35cqw, 140px); }
|
|
1938
1931
|
.cv-header { padding-top: 0.8rem; }
|
|
1939
1932
|
.cv-title { font-size: clamp(0.7rem, 2.5cqw, 1rem); gap: 0.4rem; }
|
|
1940
|
-
.cv-title .cv-timer { font-size: 0.65em; }
|
|
1941
1933
|
.cv-controls { gap: clamp(0.6rem, 1.5cqw, 1rem); padding-bottom: clamp(0.6rem, 1.5cqw, 1rem); }
|
|
1942
1934
|
.cv-pill { padding: clamp(0.15rem, 0.5cqw, 0.25rem) clamp(0.35rem, 1cqw, 0.6rem); font-size: 0.65rem; gap: 0.3rem; }
|
|
1943
1935
|
.cv-btn { padding: clamp(0.2rem, 0.5cqw, 0.3rem) clamp(0.35rem, 1cqw, 0.6rem); font-size: clamp(0.6rem, 1.2cqw, 0.7rem); }
|
|
@@ -1955,7 +1947,6 @@ var PANEL_CSS = (
|
|
|
1955
1947
|
.cv-visualizer-wrap { width: clamp(100px, 40cqw, 200px); height: clamp(100px, 40cqw, 200px); }
|
|
1956
1948
|
.cv-header { padding-top: clamp(1rem, 1.5cqw, 1.5rem); }
|
|
1957
1949
|
.cv-title { font-size: clamp(0.9rem, 3cqw, 1.3rem); gap: clamp(0.4rem, 1cqw, 0.75rem); }
|
|
1958
|
-
.cv-title .cv-timer { font-size: 0.85em; }
|
|
1959
1950
|
.cv-controls { gap: clamp(0.8rem, 1.5cqw, 1.2rem); padding-bottom: clamp(0.8rem, 1.5cqw, 1.2rem); }
|
|
1960
1951
|
.cv-pill { padding: clamp(0.2rem, 0.75cqw, 0.3rem) clamp(0.5rem, 1.2cqw, 0.75rem); font-size: 0.7rem; }
|
|
1961
1952
|
.cv-btn { padding: clamp(0.25rem, 0.75cqw, 0.35rem) clamp(0.5rem, 1.2cqw, 0.75rem); font-size: clamp(0.65rem, 1.2cqw, 0.8rem); }
|
|
@@ -1971,7 +1962,6 @@ var PANEL_CSS = (
|
|
|
1971
1962
|
.cv-visualizer-wrap { width: clamp(140px, 45cqw, 300px); height: clamp(140px, 45cqw, 300px); }
|
|
1972
1963
|
.cv-header { padding-top: clamp(1.5rem, 2cqw, 2rem); }
|
|
1973
1964
|
.cv-title { font-size: clamp(1rem, 3cqw, 1.8rem); gap: clamp(0.75rem, 1.5cqw, 1.2rem); }
|
|
1974
|
-
.cv-title .cv-timer { font-size: 0.9em; }
|
|
1975
1965
|
.cv-controls { gap: clamp(1.2rem, 2cqw, 1.8rem); padding-bottom: clamp(1.2rem, 2cqw, 1.8rem); }
|
|
1976
1966
|
.cv-pill { padding: clamp(0.3rem, 0.8cqw, 0.4rem) clamp(0.75rem, 1.2cqw, 1rem); font-size: 0.85rem; gap: 0.75rem; }
|
|
1977
1967
|
.cv-btn { padding: clamp(0.35rem, 0.8cqw, 0.4rem) clamp(0.75rem, 1.2cqw, 1rem); font-size: clamp(0.75rem, 1.2cqw, 0.9rem); }
|
|
@@ -2008,7 +1998,6 @@ var ConversationalPanel = class {
|
|
|
2008
1998
|
startBtn;
|
|
2009
1999
|
errorEl;
|
|
2010
2000
|
errorText;
|
|
2011
|
-
timerEl;
|
|
2012
2001
|
canvas;
|
|
2013
2002
|
muteBtn;
|
|
2014
2003
|
muteSvg;
|
|
@@ -2060,7 +2049,7 @@ var ConversationalPanel = class {
|
|
|
2060
2049
|
</div>
|
|
2061
2050
|
</div>
|
|
2062
2051
|
<div class="cv-header">
|
|
2063
|
-
<h2 class="cv-title">${this.esc(this.cfg.title || "Voice Chat")}
|
|
2052
|
+
<h2 class="cv-title">${this.esc(this.cfg.title || "Voice Chat")}</h2>
|
|
2064
2053
|
</div>
|
|
2065
2054
|
<div class="cv-visualizer-wrap">
|
|
2066
2055
|
<canvas class="cv-canvas"></canvas>
|
|
@@ -2091,7 +2080,6 @@ var ConversationalPanel = class {
|
|
|
2091
2080
|
this.startBtn = this.el.querySelector(".cv-curtain-btn");
|
|
2092
2081
|
this.errorEl = this.el.querySelector(".cv-error");
|
|
2093
2082
|
this.errorText = this.el.querySelector(".cv-error-text");
|
|
2094
|
-
this.timerEl = this.el.querySelector(".cv-timer");
|
|
2095
2083
|
this.canvas = this.el.querySelector(".cv-canvas");
|
|
2096
2084
|
this.muteBtn = this.el.querySelector(".cv-btn--mute");
|
|
2097
2085
|
this.muteSvg = this.muteBtn.querySelector("svg");
|
|
@@ -2269,7 +2257,7 @@ var ConversationalPanel = class {
|
|
|
2269
2257
|
this.cfg.title = title;
|
|
2270
2258
|
this.curtainTitle.textContent = title;
|
|
2271
2259
|
const h2 = this.el.querySelector(".cv-title");
|
|
2272
|
-
if (h2) h2.
|
|
2260
|
+
if (h2) h2.textContent = title;
|
|
2273
2261
|
}
|
|
2274
2262
|
/** Select a voice from the picker */
|
|
2275
2263
|
/** Update description text */
|
|
@@ -2299,21 +2287,13 @@ var ConversationalPanel = class {
|
|
|
2299
2287
|
this.el.remove();
|
|
2300
2288
|
}
|
|
2301
2289
|
// ─── internal helpers ────────────────────────────────────
|
|
2302
|
-
fmt(s) {
|
|
2303
|
-
const m = Math.floor(s / 60).toString().padStart(2, "0");
|
|
2304
|
-
const sec = (s % 60).toString().padStart(2, "0");
|
|
2305
|
-
return `${m}:${sec}`;
|
|
2306
|
-
}
|
|
2307
2290
|
startTimer() {
|
|
2308
2291
|
let elapsed = 0;
|
|
2309
2292
|
const maxDur = this.cfg.maxDuration || 300;
|
|
2310
2293
|
const silentMax = this.cfg.silenceTimeout || 60;
|
|
2311
2294
|
this._lastSpeechTime = Date.now();
|
|
2312
|
-
this.timerEl.textContent = this.fmt(maxDur);
|
|
2313
2295
|
this.timerTicker = window.setInterval(() => {
|
|
2314
2296
|
elapsed++;
|
|
2315
|
-
const remaining = Math.max(0, maxDur - elapsed);
|
|
2316
|
-
this.timerEl.textContent = this.fmt(remaining);
|
|
2317
2297
|
if (elapsed >= maxDur) {
|
|
2318
2298
|
this._locked = true;
|
|
2319
2299
|
this.stop();
|
package/dist/index.mjs
CHANGED
|
@@ -1267,7 +1267,7 @@ var TTSClient = class {
|
|
|
1267
1267
|
const req = {
|
|
1268
1268
|
text: options.text,
|
|
1269
1269
|
voice: options.voice || "F1" /* F1 */,
|
|
1270
|
-
|
|
1270
|
+
language: options.language || "en" /* ENGLISH */,
|
|
1271
1271
|
speed: options.speed || 1.05,
|
|
1272
1272
|
steps: options.steps || 24,
|
|
1273
1273
|
visemes: options.visemes || false
|
|
@@ -1356,7 +1356,7 @@ var STTClient = class {
|
|
|
1356
1356
|
if (typeof Blob !== "undefined" && options.audio instanceof Blob) {
|
|
1357
1357
|
const form = new FormData();
|
|
1358
1358
|
form.append("audio", options.audio, "audio.wav");
|
|
1359
|
-
if (options.language) form.append("
|
|
1359
|
+
if (options.language) form.append("language", options.language);
|
|
1360
1360
|
if (options.sampleRate) form.append("sample_rate", String(options.sampleRate));
|
|
1361
1361
|
res = await fetch(url, {
|
|
1362
1362
|
method: "POST",
|
|
@@ -1372,7 +1372,7 @@ var STTClient = class {
|
|
|
1372
1372
|
audio: uint8ArrayToBase64(bytes),
|
|
1373
1373
|
format: options.format || "pcm16",
|
|
1374
1374
|
sample_rate: options.sampleRate,
|
|
1375
|
-
|
|
1375
|
+
language: options.language
|
|
1376
1376
|
})
|
|
1377
1377
|
});
|
|
1378
1378
|
}
|
|
@@ -1444,7 +1444,7 @@ var SpeechToTextClient = class {
|
|
|
1444
1444
|
this.ws.onopen = async () => {
|
|
1445
1445
|
this.isConnected = true;
|
|
1446
1446
|
this.onStatusChange?.("connected");
|
|
1447
|
-
this.ws.send(JSON.stringify({
|
|
1447
|
+
this.ws.send(JSON.stringify({ language: this.language || "en" /* ENGLISH */, vad: this.vad }));
|
|
1448
1448
|
await this.audioManager.startMicrophone((data) => {
|
|
1449
1449
|
if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {
|
|
1450
1450
|
this.ws.send(data);
|
|
@@ -1714,12 +1714,6 @@ var PANEL_CSS = (
|
|
|
1714
1714
|
gap: 1rem;
|
|
1715
1715
|
letter-spacing: -0.02em;
|
|
1716
1716
|
}
|
|
1717
|
-
.cv-title .cv-timer {
|
|
1718
|
-
font-variant-numeric: tabular-nums;
|
|
1719
|
-
color: var(--cv-accent);
|
|
1720
|
-
font-weight: 400;
|
|
1721
|
-
opacity: 0.8;
|
|
1722
|
-
}
|
|
1723
1717
|
.cv-visualizer-wrap {
|
|
1724
1718
|
position: absolute;
|
|
1725
1719
|
top: 50%;
|
|
@@ -1868,7 +1862,6 @@ var PANEL_CSS = (
|
|
|
1868
1862
|
.cv-visualizer-wrap { width: 60px; height: 60px; }
|
|
1869
1863
|
.cv-header { padding-top: 0.75rem; }
|
|
1870
1864
|
.cv-title { font-size: 0.7rem; gap: 0.3rem; }
|
|
1871
|
-
.cv-title .cv-timer { display: none; }
|
|
1872
1865
|
.cv-controls { gap: 0.6rem; padding-bottom: 0.6rem; }
|
|
1873
1866
|
.cv-pill { padding: 0.15rem 0.4rem; gap: 0.3rem; }
|
|
1874
1867
|
.cv-btn { padding: 0.2rem 0.4rem; font-size: 0.6rem; gap: 0; }
|
|
@@ -1886,7 +1879,6 @@ var PANEL_CSS = (
|
|
|
1886
1879
|
.cv-visualizer-wrap { width: clamp(80px, 35cqw, 140px); height: clamp(80px, 35cqw, 140px); }
|
|
1887
1880
|
.cv-header { padding-top: 0.8rem; }
|
|
1888
1881
|
.cv-title { font-size: clamp(0.7rem, 2.5cqw, 1rem); gap: 0.4rem; }
|
|
1889
|
-
.cv-title .cv-timer { font-size: 0.65em; }
|
|
1890
1882
|
.cv-controls { gap: clamp(0.6rem, 1.5cqw, 1rem); padding-bottom: clamp(0.6rem, 1.5cqw, 1rem); }
|
|
1891
1883
|
.cv-pill { padding: clamp(0.15rem, 0.5cqw, 0.25rem) clamp(0.35rem, 1cqw, 0.6rem); font-size: 0.65rem; gap: 0.3rem; }
|
|
1892
1884
|
.cv-btn { padding: clamp(0.2rem, 0.5cqw, 0.3rem) clamp(0.35rem, 1cqw, 0.6rem); font-size: clamp(0.6rem, 1.2cqw, 0.7rem); }
|
|
@@ -1904,7 +1896,6 @@ var PANEL_CSS = (
|
|
|
1904
1896
|
.cv-visualizer-wrap { width: clamp(100px, 40cqw, 200px); height: clamp(100px, 40cqw, 200px); }
|
|
1905
1897
|
.cv-header { padding-top: clamp(1rem, 1.5cqw, 1.5rem); }
|
|
1906
1898
|
.cv-title { font-size: clamp(0.9rem, 3cqw, 1.3rem); gap: clamp(0.4rem, 1cqw, 0.75rem); }
|
|
1907
|
-
.cv-title .cv-timer { font-size: 0.85em; }
|
|
1908
1899
|
.cv-controls { gap: clamp(0.8rem, 1.5cqw, 1.2rem); padding-bottom: clamp(0.8rem, 1.5cqw, 1.2rem); }
|
|
1909
1900
|
.cv-pill { padding: clamp(0.2rem, 0.75cqw, 0.3rem) clamp(0.5rem, 1.2cqw, 0.75rem); font-size: 0.7rem; }
|
|
1910
1901
|
.cv-btn { padding: clamp(0.25rem, 0.75cqw, 0.35rem) clamp(0.5rem, 1.2cqw, 0.75rem); font-size: clamp(0.65rem, 1.2cqw, 0.8rem); }
|
|
@@ -1920,7 +1911,6 @@ var PANEL_CSS = (
|
|
|
1920
1911
|
.cv-visualizer-wrap { width: clamp(140px, 45cqw, 300px); height: clamp(140px, 45cqw, 300px); }
|
|
1921
1912
|
.cv-header { padding-top: clamp(1.5rem, 2cqw, 2rem); }
|
|
1922
1913
|
.cv-title { font-size: clamp(1rem, 3cqw, 1.8rem); gap: clamp(0.75rem, 1.5cqw, 1.2rem); }
|
|
1923
|
-
.cv-title .cv-timer { font-size: 0.9em; }
|
|
1924
1914
|
.cv-controls { gap: clamp(1.2rem, 2cqw, 1.8rem); padding-bottom: clamp(1.2rem, 2cqw, 1.8rem); }
|
|
1925
1915
|
.cv-pill { padding: clamp(0.3rem, 0.8cqw, 0.4rem) clamp(0.75rem, 1.2cqw, 1rem); font-size: 0.85rem; gap: 0.75rem; }
|
|
1926
1916
|
.cv-btn { padding: clamp(0.35rem, 0.8cqw, 0.4rem) clamp(0.75rem, 1.2cqw, 1rem); font-size: clamp(0.75rem, 1.2cqw, 0.9rem); }
|
|
@@ -1957,7 +1947,6 @@ var ConversationalPanel = class {
|
|
|
1957
1947
|
startBtn;
|
|
1958
1948
|
errorEl;
|
|
1959
1949
|
errorText;
|
|
1960
|
-
timerEl;
|
|
1961
1950
|
canvas;
|
|
1962
1951
|
muteBtn;
|
|
1963
1952
|
muteSvg;
|
|
@@ -2009,7 +1998,7 @@ var ConversationalPanel = class {
|
|
|
2009
1998
|
</div>
|
|
2010
1999
|
</div>
|
|
2011
2000
|
<div class="cv-header">
|
|
2012
|
-
<h2 class="cv-title">${this.esc(this.cfg.title || "Voice Chat")}
|
|
2001
|
+
<h2 class="cv-title">${this.esc(this.cfg.title || "Voice Chat")}</h2>
|
|
2013
2002
|
</div>
|
|
2014
2003
|
<div class="cv-visualizer-wrap">
|
|
2015
2004
|
<canvas class="cv-canvas"></canvas>
|
|
@@ -2040,7 +2029,6 @@ var ConversationalPanel = class {
|
|
|
2040
2029
|
this.startBtn = this.el.querySelector(".cv-curtain-btn");
|
|
2041
2030
|
this.errorEl = this.el.querySelector(".cv-error");
|
|
2042
2031
|
this.errorText = this.el.querySelector(".cv-error-text");
|
|
2043
|
-
this.timerEl = this.el.querySelector(".cv-timer");
|
|
2044
2032
|
this.canvas = this.el.querySelector(".cv-canvas");
|
|
2045
2033
|
this.muteBtn = this.el.querySelector(".cv-btn--mute");
|
|
2046
2034
|
this.muteSvg = this.muteBtn.querySelector("svg");
|
|
@@ -2218,7 +2206,7 @@ var ConversationalPanel = class {
|
|
|
2218
2206
|
this.cfg.title = title;
|
|
2219
2207
|
this.curtainTitle.textContent = title;
|
|
2220
2208
|
const h2 = this.el.querySelector(".cv-title");
|
|
2221
|
-
if (h2) h2.
|
|
2209
|
+
if (h2) h2.textContent = title;
|
|
2222
2210
|
}
|
|
2223
2211
|
/** Select a voice from the picker */
|
|
2224
2212
|
/** Update description text */
|
|
@@ -2248,21 +2236,13 @@ var ConversationalPanel = class {
|
|
|
2248
2236
|
this.el.remove();
|
|
2249
2237
|
}
|
|
2250
2238
|
// ─── internal helpers ────────────────────────────────────
|
|
2251
|
-
fmt(s) {
|
|
2252
|
-
const m = Math.floor(s / 60).toString().padStart(2, "0");
|
|
2253
|
-
const sec = (s % 60).toString().padStart(2, "0");
|
|
2254
|
-
return `${m}:${sec}`;
|
|
2255
|
-
}
|
|
2256
2239
|
startTimer() {
|
|
2257
2240
|
let elapsed = 0;
|
|
2258
2241
|
const maxDur = this.cfg.maxDuration || 300;
|
|
2259
2242
|
const silentMax = this.cfg.silenceTimeout || 60;
|
|
2260
2243
|
this._lastSpeechTime = Date.now();
|
|
2261
|
-
this.timerEl.textContent = this.fmt(maxDur);
|
|
2262
2244
|
this.timerTicker = window.setInterval(() => {
|
|
2263
2245
|
elapsed++;
|
|
2264
|
-
const remaining = Math.max(0, maxDur - elapsed);
|
|
2265
|
-
this.timerEl.textContent = this.fmt(remaining);
|
|
2266
2246
|
if (elapsed >= maxDur) {
|
|
2267
2247
|
this._locked = true;
|
|
2268
2248
|
this.stop();
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -893,7 +893,7 @@ export class TTSClient {
|
|
|
893
893
|
const req = {
|
|
894
894
|
text: options.text,
|
|
895
895
|
voice: options.voice || VoiceStyle.F1,
|
|
896
|
-
|
|
896
|
+
language: options.language || Language.ENGLISH,
|
|
897
897
|
speed: options.speed || 1.05,
|
|
898
898
|
steps: options.steps || 24,
|
|
899
899
|
visemes: options.visemes || false
|
|
@@ -1001,7 +1001,7 @@ export class STTClient {
|
|
|
1001
1001
|
if (typeof Blob !== 'undefined' && options.audio instanceof Blob) {
|
|
1002
1002
|
const form = new FormData();
|
|
1003
1003
|
form.append('audio', options.audio, 'audio.wav');
|
|
1004
|
-
if (options.language) form.append('
|
|
1004
|
+
if (options.language) form.append('language', options.language);
|
|
1005
1005
|
if (options.sampleRate) form.append('sample_rate', String(options.sampleRate));
|
|
1006
1006
|
res = await fetch(url, {
|
|
1007
1007
|
method: 'POST',
|
|
@@ -1019,7 +1019,7 @@ export class STTClient {
|
|
|
1019
1019
|
audio: uint8ArrayToBase64(bytes),
|
|
1020
1020
|
format: options.format || 'pcm16',
|
|
1021
1021
|
sample_rate: options.sampleRate,
|
|
1022
|
-
|
|
1022
|
+
language: options.language,
|
|
1023
1023
|
}),
|
|
1024
1024
|
});
|
|
1025
1025
|
}
|
|
@@ -1105,7 +1105,7 @@ export class SpeechToTextClient {
|
|
|
1105
1105
|
this.ws.onopen = async () => {
|
|
1106
1106
|
this.isConnected = true;
|
|
1107
1107
|
this.onStatusChange?.('connected');
|
|
1108
|
-
this.ws!.send(JSON.stringify({
|
|
1108
|
+
this.ws!.send(JSON.stringify({ language: this.language || Language.ENGLISH, vad: this.vad }));
|
|
1109
1109
|
|
|
1110
1110
|
await this.audioManager!.startMicrophone((data) => {
|
|
1111
1111
|
if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {
|
|
@@ -107,12 +107,6 @@ const PANEL_CSS = /*css*/ `
|
|
|
107
107
|
gap: 1rem;
|
|
108
108
|
letter-spacing: -0.02em;
|
|
109
109
|
}
|
|
110
|
-
.cv-title .cv-timer {
|
|
111
|
-
font-variant-numeric: tabular-nums;
|
|
112
|
-
color: var(--cv-accent);
|
|
113
|
-
font-weight: 400;
|
|
114
|
-
opacity: 0.8;
|
|
115
|
-
}
|
|
116
110
|
.cv-visualizer-wrap {
|
|
117
111
|
position: absolute;
|
|
118
112
|
top: 50%;
|
|
@@ -261,7 +255,6 @@ const PANEL_CSS = /*css*/ `
|
|
|
261
255
|
.cv-visualizer-wrap { width: 60px; height: 60px; }
|
|
262
256
|
.cv-header { padding-top: 0.75rem; }
|
|
263
257
|
.cv-title { font-size: 0.7rem; gap: 0.3rem; }
|
|
264
|
-
.cv-title .cv-timer { display: none; }
|
|
265
258
|
.cv-controls { gap: 0.6rem; padding-bottom: 0.6rem; }
|
|
266
259
|
.cv-pill { padding: 0.15rem 0.4rem; gap: 0.3rem; }
|
|
267
260
|
.cv-btn { padding: 0.2rem 0.4rem; font-size: 0.6rem; gap: 0; }
|
|
@@ -279,7 +272,6 @@ const PANEL_CSS = /*css*/ `
|
|
|
279
272
|
.cv-visualizer-wrap { width: clamp(80px, 35cqw, 140px); height: clamp(80px, 35cqw, 140px); }
|
|
280
273
|
.cv-header { padding-top: 0.8rem; }
|
|
281
274
|
.cv-title { font-size: clamp(0.7rem, 2.5cqw, 1rem); gap: 0.4rem; }
|
|
282
|
-
.cv-title .cv-timer { font-size: 0.65em; }
|
|
283
275
|
.cv-controls { gap: clamp(0.6rem, 1.5cqw, 1rem); padding-bottom: clamp(0.6rem, 1.5cqw, 1rem); }
|
|
284
276
|
.cv-pill { padding: clamp(0.15rem, 0.5cqw, 0.25rem) clamp(0.35rem, 1cqw, 0.6rem); font-size: 0.65rem; gap: 0.3rem; }
|
|
285
277
|
.cv-btn { padding: clamp(0.2rem, 0.5cqw, 0.3rem) clamp(0.35rem, 1cqw, 0.6rem); font-size: clamp(0.6rem, 1.2cqw, 0.7rem); }
|
|
@@ -297,7 +289,6 @@ const PANEL_CSS = /*css*/ `
|
|
|
297
289
|
.cv-visualizer-wrap { width: clamp(100px, 40cqw, 200px); height: clamp(100px, 40cqw, 200px); }
|
|
298
290
|
.cv-header { padding-top: clamp(1rem, 1.5cqw, 1.5rem); }
|
|
299
291
|
.cv-title { font-size: clamp(0.9rem, 3cqw, 1.3rem); gap: clamp(0.4rem, 1cqw, 0.75rem); }
|
|
300
|
-
.cv-title .cv-timer { font-size: 0.85em; }
|
|
301
292
|
.cv-controls { gap: clamp(0.8rem, 1.5cqw, 1.2rem); padding-bottom: clamp(0.8rem, 1.5cqw, 1.2rem); }
|
|
302
293
|
.cv-pill { padding: clamp(0.2rem, 0.75cqw, 0.3rem) clamp(0.5rem, 1.2cqw, 0.75rem); font-size: 0.7rem; }
|
|
303
294
|
.cv-btn { padding: clamp(0.25rem, 0.75cqw, 0.35rem) clamp(0.5rem, 1.2cqw, 0.75rem); font-size: clamp(0.65rem, 1.2cqw, 0.8rem); }
|
|
@@ -313,7 +304,6 @@ const PANEL_CSS = /*css*/ `
|
|
|
313
304
|
.cv-visualizer-wrap { width: clamp(140px, 45cqw, 300px); height: clamp(140px, 45cqw, 300px); }
|
|
314
305
|
.cv-header { padding-top: clamp(1.5rem, 2cqw, 2rem); }
|
|
315
306
|
.cv-title { font-size: clamp(1rem, 3cqw, 1.8rem); gap: clamp(0.75rem, 1.5cqw, 1.2rem); }
|
|
316
|
-
.cv-title .cv-timer { font-size: 0.9em; }
|
|
317
307
|
.cv-controls { gap: clamp(1.2rem, 2cqw, 1.8rem); padding-bottom: clamp(1.2rem, 2cqw, 1.8rem); }
|
|
318
308
|
.cv-pill { padding: clamp(0.3rem, 0.8cqw, 0.4rem) clamp(0.75rem, 1.2cqw, 1rem); font-size: 0.85rem; gap: 0.75rem; }
|
|
319
309
|
.cv-btn { padding: clamp(0.35rem, 0.8cqw, 0.4rem) clamp(0.75rem, 1.2cqw, 1rem); font-size: clamp(0.75rem, 1.2cqw, 0.9rem); }
|
|
@@ -387,7 +377,6 @@ export class ConversationalPanel {
|
|
|
387
377
|
private startBtn!: HTMLButtonElement;
|
|
388
378
|
private errorEl!: HTMLElement;
|
|
389
379
|
private errorText!: HTMLElement;
|
|
390
|
-
private timerEl!: HTMLElement;
|
|
391
380
|
private canvas!: HTMLCanvasElement;
|
|
392
381
|
private muteBtn!: HTMLElement;
|
|
393
382
|
private muteSvg!: SVGElement;
|
|
@@ -444,7 +433,7 @@ export class ConversationalPanel {
|
|
|
444
433
|
</div>
|
|
445
434
|
</div>
|
|
446
435
|
<div class="cv-header">
|
|
447
|
-
<h2 class="cv-title">${this.esc(this.cfg.title || "Voice Chat")}
|
|
436
|
+
<h2 class="cv-title">${this.esc(this.cfg.title || "Voice Chat")}</h2>
|
|
448
437
|
</div>
|
|
449
438
|
<div class="cv-visualizer-wrap">
|
|
450
439
|
<canvas class="cv-canvas"></canvas>
|
|
@@ -478,7 +467,6 @@ export class ConversationalPanel {
|
|
|
478
467
|
this.startBtn = this.el.querySelector('.cv-curtain-btn')!;
|
|
479
468
|
this.errorEl = this.el.querySelector('.cv-error')!;
|
|
480
469
|
this.errorText = this.el.querySelector('.cv-error-text')!;
|
|
481
|
-
this.timerEl = this.el.querySelector('.cv-timer')!;
|
|
482
470
|
this.canvas = this.el.querySelector('.cv-canvas')!;
|
|
483
471
|
this.muteBtn = this.el.querySelector('.cv-btn--mute')!;
|
|
484
472
|
this.muteSvg = this.muteBtn.querySelector('svg')!;
|
|
@@ -673,7 +661,7 @@ export class ConversationalPanel {
|
|
|
673
661
|
this.cfg.title = title;
|
|
674
662
|
this.curtainTitle.textContent = title;
|
|
675
663
|
const h2 = this.el.querySelector('.cv-title');
|
|
676
|
-
if (h2) h2.
|
|
664
|
+
if (h2) h2.textContent = title;
|
|
677
665
|
}
|
|
678
666
|
|
|
679
667
|
/** Select a voice from the picker */
|
|
@@ -710,22 +698,15 @@ export class ConversationalPanel {
|
|
|
710
698
|
|
|
711
699
|
// ─── internal helpers ────────────────────────────────────
|
|
712
700
|
|
|
713
|
-
private fmt(s: number): string {
|
|
714
|
-
const m = Math.floor(s / 60).toString().padStart(2, '0');
|
|
715
|
-
const sec = (s % 60).toString().padStart(2, '0');
|
|
716
|
-
return `${m}:${sec}`;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
701
|
private startTimer() {
|
|
702
|
+
// No visible countdown — this interval only enforces maxDuration and
|
|
703
|
+
// the silence timeout, both real safety/cost-control cutoffs, not UI.
|
|
720
704
|
let elapsed = 0;
|
|
721
705
|
const maxDur = this.cfg.maxDuration || 300;
|
|
722
706
|
const silentMax = this.cfg.silenceTimeout || 60;
|
|
723
707
|
this._lastSpeechTime = Date.now();
|
|
724
|
-
this.timerEl.textContent = this.fmt(maxDur);
|
|
725
708
|
this.timerTicker = window.setInterval(() => {
|
|
726
709
|
elapsed++;
|
|
727
|
-
const remaining = Math.max(0, maxDur - elapsed);
|
|
728
|
-
this.timerEl.textContent = this.fmt(remaining);
|
|
729
710
|
|
|
730
711
|
if (elapsed >= maxDur) {
|
|
731
712
|
this._locked = true;
|