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.
@@ -1,2 +1,2 @@
1
- export declare const CLI_VERSION = "0.1.191";
1
+ export declare const CLI_VERSION = "0.1.192";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.191";
2
+ export const CLI_VERSION = "0.1.192";
3
3
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugly-app",
3
- "version": "0.1.191",
3
+ "version": "0.1.192",
4
4
  "type": "module",
5
5
  "main": "./dist/server/index.js",
6
6
  "exports": {
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.191";
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 recorderCtxRef = useRef<AudioContext | null>(null);
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 separate recording stream for STT
378
- const recStream = await navigator.mediaDevices.getUserMedia({
379
- audio: { sampleRate: 48000, channelCount: 1, echoCancellation: true, noiseSuppression: true },
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
- recorderStreamRef.current = recStream;
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
- stopRecording();
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
- stopRecording();
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