ugly-app 0.1.191 → 0.1.192
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/cli/version.d.ts +1 -1
- package/dist/cli/version.js +1 -1
- package/package.json +1 -1
- package/src/cli/version.ts +1 -1
- package/templates/client/pages/AITestPage.tsx +3 -0
- package/templates/client/pages/AudioTestPage.tsx +17 -49
- package/templates/client/pages/EmailTestPage.tsx +3 -0
- package/templates/client/pages/KagiTestPage.tsx +3 -0
- package/templates/client/pages/PushTestPage.tsx +3 -0
- package/templates/client/pages/UploadTestPage.tsx +3 -0
package/dist/cli/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "0.1.
|
|
1
|
+
export declare const CLI_VERSION = "0.1.192";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/cli/version.js
CHANGED
package/package.json
CHANGED
package/src/cli/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by prebuild — do not edit manually
|
|
2
|
-
export const CLI_VERSION = "0.1.
|
|
2
|
+
export const CLI_VERSION = "0.1.192";
|
|
@@ -34,6 +34,9 @@ export default function AITestPage(): React.ReactElement {
|
|
|
34
34
|
const [logs, setLogs] = useState<LogEntry[]>([]);
|
|
35
35
|
|
|
36
36
|
function addLog(msg: string, kind: LogEntry['kind'] = 'info'): void {
|
|
37
|
+
const prefix = '[AITest]';
|
|
38
|
+
if (kind === 'err') console.error(prefix, msg);
|
|
39
|
+
else console.log(prefix, msg);
|
|
37
40
|
setLogs((prev) => [...prev, { ts: Date.now(), msg, kind }]);
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
|
+
AudioRecorder,
|
|
3
4
|
BarsVisualizer,
|
|
4
5
|
BlobVisualizer,
|
|
5
6
|
Button,
|
|
@@ -265,12 +266,13 @@ function STTSection({ socket }: { socket: RawSocket }) {
|
|
|
265
266
|
|
|
266
267
|
const mic = useMicAnalyzer();
|
|
267
268
|
const streamIdRef = useRef<string | null>(null);
|
|
268
|
-
const
|
|
269
|
-
const workletRef = useRef<AudioWorkletNode | null>(null);
|
|
270
|
-
const recorderStreamRef = useRef<MediaStream | null>(null);
|
|
269
|
+
const recorderRef = useRef<AudioRecorder | null>(null);
|
|
271
270
|
const chunkCountRef = useRef(0);
|
|
272
271
|
|
|
273
272
|
function addLog(msg: string, kind: LogEntry['kind'] = 'info') {
|
|
273
|
+
const prefix = '[STT]';
|
|
274
|
+
if (kind === 'err') console.error(prefix, msg);
|
|
275
|
+
else console.log(prefix, msg);
|
|
274
276
|
setLogs((prev) => [...prev, { ts: Date.now(), msg, kind }]);
|
|
275
277
|
}
|
|
276
278
|
|
|
@@ -295,50 +297,12 @@ function STTSection({ socket }: { socket: RawSocket }) {
|
|
|
295
297
|
[],
|
|
296
298
|
);
|
|
297
299
|
|
|
298
|
-
async function startRecording(stream: MediaStream) {
|
|
299
|
-
const ctx = new AudioContext({ sampleRate: 48000 });
|
|
300
|
-
const source = ctx.createMediaStreamSource(stream);
|
|
301
|
-
const workletUrl = new URL('ugly-app/client/audioRecorder.worklet.js', import.meta.url).href;
|
|
302
|
-
await ctx.audioWorklet.addModule(workletUrl);
|
|
303
|
-
const worklet = new AudioWorkletNode(ctx, 'audio-recorder');
|
|
304
|
-
chunkCountRef.current = 0;
|
|
305
|
-
worklet.port.onmessage = (event: MessageEvent) => {
|
|
306
|
-
if (event.data?.type === 'chunk') {
|
|
307
|
-
const floatData = event.data.samples as Float32Array;
|
|
308
|
-
const int16 = new Int16Array(floatData.length);
|
|
309
|
-
for (let i = 0; i < floatData.length; i++) {
|
|
310
|
-
const clamped = Math.max(-1, Math.min(1, floatData[i] ?? 0));
|
|
311
|
-
int16[i] = clamped < 0 ? clamped * 32768 : clamped * 32767;
|
|
312
|
-
}
|
|
313
|
-
const bytes = new Uint8Array(int16.buffer);
|
|
314
|
-
let binary = '';
|
|
315
|
-
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
316
|
-
const audio = btoa(binary);
|
|
317
|
-
chunkCountRef.current++;
|
|
318
|
-
socket.send({ type: 'stt:audio', streamId: streamIdRef.current, audio });
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
source.connect(worklet);
|
|
322
|
-
worklet.connect(ctx.destination);
|
|
323
|
-
recorderCtxRef.current = ctx;
|
|
324
|
-
workletRef.current = worklet;
|
|
325
|
-
addLog('AudioWorklet recorder started', 'ok');
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
function stopRecording() {
|
|
329
|
-
workletRef.current?.disconnect();
|
|
330
|
-
void recorderCtxRef.current?.close().catch(() => { /* noop */ });
|
|
331
|
-
recorderStreamRef.current?.getTracks().forEach((t) => { t.stop(); });
|
|
332
|
-
workletRef.current = null;
|
|
333
|
-
recorderCtxRef.current = null;
|
|
334
|
-
recorderStreamRef.current = null;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
300
|
async function startListening() {
|
|
338
301
|
const streamId = `stt-${++sttCounter}`;
|
|
339
302
|
streamIdRef.current = streamId;
|
|
340
303
|
setTranscript('');
|
|
341
304
|
setLogs([]);
|
|
305
|
+
chunkCountRef.current = 0;
|
|
342
306
|
|
|
343
307
|
const started = Date.now();
|
|
344
308
|
addLog(`Mode: ${sttMode}${sttMode === 'continuous' ? ' (VAD enabled)' : ''}`);
|
|
@@ -374,19 +338,20 @@ function STTSection({ socket }: { socket: RawSocket }) {
|
|
|
374
338
|
// Start mic for visualization
|
|
375
339
|
await mic.start();
|
|
376
340
|
|
|
377
|
-
// Start
|
|
378
|
-
|
|
379
|
-
|
|
341
|
+
// Start recording with AudioRecorder (uses AudioWorkletNode)
|
|
342
|
+
if (!recorderRef.current) recorderRef.current = new AudioRecorder();
|
|
343
|
+
await recorderRef.current.start((audio) => {
|
|
344
|
+
chunkCountRef.current++;
|
|
345
|
+
socket.send({ type: 'stt:audio', streamId: streamIdRef.current, audio });
|
|
380
346
|
});
|
|
381
|
-
|
|
382
|
-
await startRecording(recStream);
|
|
347
|
+
addLog('Recording started', 'ok');
|
|
383
348
|
|
|
384
349
|
setListening(true);
|
|
385
350
|
addLog('Listening…');
|
|
386
351
|
}
|
|
387
352
|
|
|
388
353
|
function stopListening() {
|
|
389
|
-
|
|
354
|
+
recorderRef.current?.stop();
|
|
390
355
|
mic.stop();
|
|
391
356
|
if (streamIdRef.current) {
|
|
392
357
|
socket.send({ type: 'stt:stop', streamId: streamIdRef.current });
|
|
@@ -406,7 +371,7 @@ function STTSection({ socket }: { socket: RawSocket }) {
|
|
|
406
371
|
// Cleanup on unmount
|
|
407
372
|
useEffect(() => { // eslint-disable-line react-hooks/exhaustive-deps
|
|
408
373
|
return () => {
|
|
409
|
-
|
|
374
|
+
recorderRef.current?.stop();
|
|
410
375
|
mic.stop();
|
|
411
376
|
if (streamIdRef.current) {
|
|
412
377
|
socket.send({ type: 'stt:stop', streamId: streamIdRef.current });
|
|
@@ -526,6 +491,9 @@ function TTSSection({ socket }: { socket: RawSocket }) {
|
|
|
526
491
|
const activeWordIdxRef = useRef(-1);
|
|
527
492
|
|
|
528
493
|
function addLog(msg: string, kind: LogEntry['kind'] = 'info') {
|
|
494
|
+
const prefix = '[TTS]';
|
|
495
|
+
if (kind === 'err') console.error(prefix, msg);
|
|
496
|
+
else console.log(prefix, msg);
|
|
529
497
|
setLogs((prev) => [...prev, { ts: Date.now(), msg, kind }]);
|
|
530
498
|
}
|
|
531
499
|
|
|
@@ -29,6 +29,9 @@ export default function EmailTestPage(): React.ReactElement {
|
|
|
29
29
|
const [logs, setLogs] = useState<LogEntry[]>([]);
|
|
30
30
|
|
|
31
31
|
function addLog(msg: string, kind: LogEntry['kind'] = 'info') {
|
|
32
|
+
const prefix = '[EmailTest]';
|
|
33
|
+
if (kind === 'err') console.error(prefix, msg);
|
|
34
|
+
else console.log(prefix, msg);
|
|
32
35
|
setLogs((prev) => [...prev, { ts: Date.now(), msg, kind }]);
|
|
33
36
|
}
|
|
34
37
|
|
|
@@ -50,6 +50,9 @@ export default function KagiTestPage(): React.ReactElement {
|
|
|
50
50
|
const [summaryResult, setSummaryResult] = useState('');
|
|
51
51
|
|
|
52
52
|
function addLog(msg: string, kind: LogEntry['kind'] = 'info'): void {
|
|
53
|
+
const prefix = '[KagiTest]';
|
|
54
|
+
if (kind === 'err') console.error(prefix, msg);
|
|
55
|
+
else console.log(prefix, msg);
|
|
53
56
|
setLogs((prev) => [...prev, { ts: Date.now(), msg, kind }]);
|
|
54
57
|
}
|
|
55
58
|
|
|
@@ -18,6 +18,9 @@ export default function PushTestPage(): React.ReactElement {
|
|
|
18
18
|
const [loading, setLoading] = useState(false);
|
|
19
19
|
|
|
20
20
|
function addLog(msg: string, kind: LogEntry['kind'] = 'info') {
|
|
21
|
+
const prefix = '[PushTest]';
|
|
22
|
+
if (kind === 'err') console.error(prefix, msg);
|
|
23
|
+
else console.log(prefix, msg);
|
|
21
24
|
setLogs((prev) => [...prev, { ts: Date.now(), msg, kind }]);
|
|
22
25
|
}
|
|
23
26
|
|
|
@@ -32,6 +32,9 @@ export default function UploadTestPage(): React.ReactElement {
|
|
|
32
32
|
const [dragOver, setDragOver] = useState(false);
|
|
33
33
|
|
|
34
34
|
function addLog(msg: string, kind: LogEntry['kind'] = 'info') {
|
|
35
|
+
const prefix = '[UploadTest]';
|
|
36
|
+
if (kind === 'err') console.error(prefix, msg);
|
|
37
|
+
else console.log(prefix, msg);
|
|
35
38
|
setLogs((prev) => [...prev, { ts: Date.now(), msg, kind }]);
|
|
36
39
|
}
|
|
37
40
|
|