@gnani.ai/web-voice-hook 0.0.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/README.md ADDED
@@ -0,0 +1,187 @@
1
+ # GnaniWebVoiceHook
2
+
3
+ A **React hook** for real-time bidirectional WebSocket voice: capture microphone → server (STT), play TTS ← server. Published as `@gnani/web-voice-hook`.
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ - **SSH key** — You need an SSH key added to your GitLab account to install from the private GitLab repo. See [GitLab: Add an SSH key](https://docs.gitlab.com/ee/user/ssh.html).
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ In your application project:
16
+
17
+ ```bash
18
+ pnpm add git+ssh://git@gitlab.com:gnani.ai/demo_platform/gnani-web-voice-hook.git#v1.0.4
19
+ ```
20
+
21
+ Or with npm:
22
+
23
+ ```bash
24
+ npm install git+ssh://git@gitlab.com:gnani.ai/demo_platform/gnani-web-voice-hook.git#v1.0.4
25
+ ```
26
+
27
+ Replace `#v1.0.4` with the tag/version you need (e.g. `#v1.0.2`, `#main`).
28
+
29
+ **Peer dependencies** (install in your app if not already present):
30
+
31
+ ```bash
32
+ pnpm add react audiomotion-analyzer
33
+ ```
34
+
35
+ - **react** — required.
36
+ - **audiomotion-analyzer** — optional; only needed if you use the visualizer.
37
+
38
+ ---
39
+
40
+ ## Quick start
41
+
42
+ ### 1. Serve the Audio Worklet
43
+
44
+ Copy `audio-processor.js` from this package into your app’s **public** folder, e.g. `public/worklet/audio-processor.js`, so the URL `/worklet/audio-processor.js` serves that file. Or use a custom path and set `workletPath` in the hook options.
45
+
46
+ ### 2. Use the hook
47
+
48
+ **Option A — Direct use** (you build the WebSocket URL yourself):
49
+
50
+ ```tsx
51
+ import { useWebSocketAudio as useWebSocketAudioHook } from '@gnani/web-voice-hook';
52
+ import type { IUseWebVoiceOptions } from '@gnani/web-voice-hook';
53
+
54
+ const {
55
+ isConnected,
56
+ isPlaying,
57
+ connect,
58
+ disconnect,
59
+ reconnect,
60
+ startRecording,
61
+ stopRecording,
62
+ isRecording,
63
+ } = useWebSocketAudioHook({
64
+ websocketUrl: 'wss://your-api/voice',
65
+ workletPath: '/worklet/audio-processor.js',
66
+ visualizerOptions: { elementId: 'visualizer-canvas', color: '#9E77ED' },
67
+ events: {
68
+ onOpen: () => console.log('Connected'),
69
+ onClose: (source) => console.log('Closed', source),
70
+ onException: (err) => console.error(err),
71
+ },
72
+ logger: { info: console.log, error: console.error },
73
+ } as IUseWebVoiceOptions);
74
+ ```
75
+
76
+ **Option B — Wrapper hook** (build URL from app config/auth and pass through):
77
+
78
+ ```tsx
79
+ import { useWebSocketAudio as useWebSocketAudioHook } from '@gnani/web-voice-hook';
80
+ import type { IUseWebVoiceOptions } from '@gnani/web-voice-hook';
81
+ import { useMemo } from 'react';
82
+ import { v4 } from 'uuid';
83
+
84
+ // Example: your app builds websocketUrl from agentId, auth, etc.
85
+ export const useWebSocketAudio = ({
86
+ variant,
87
+ agentId,
88
+ onClose,
89
+ isDemoMode = false,
90
+ testerName,
91
+ onConversationIdGenerated,
92
+ visualizerColor,
93
+ }) => {
94
+ const callId = useMemo(() => v4(), []);
95
+ const authToken = useGnaniAuth()?.authToken; // your auth hook
96
+
97
+ const websocketUrl = useMemo(() => {
98
+ if (!agentId) return undefined;
99
+ return buildVoiceWebSocketUrl(variant, agentId, callId, authToken, isDemoMode, testerName);
100
+ }, [variant, agentId, callId, authToken, isDemoMode, testerName]);
101
+
102
+ onConversationIdGenerated?.(callId);
103
+
104
+ const hook = useWebSocketAudioHook({
105
+ websocketUrl,
106
+ conversationId: callId,
107
+ visualizerOptions: { elementId: 'visualizer-canvas', color: visualizerColor },
108
+ events: {
109
+ onOpen: () => console.log('WebSocket connected'),
110
+ onClose: (source) => {
111
+ console.log('WebSocket closed', source);
112
+ onClose?.(source);
113
+ },
114
+ onException: (error) => {
115
+ console.error('WebSocket error', error);
116
+ Sentry.captureException(error); // optional
117
+ },
118
+ },
119
+ logger: { info: console.log, error: console.error },
120
+ } as IUseWebVoiceOptions);
121
+
122
+ return {
123
+ ...hook,
124
+ conversationId: callId,
125
+ };
126
+ };
127
+ ```
128
+
129
+ Then in your UI, call your wrapper (e.g. `useWebSocketAudio({ variant, agentId, onClose, ... })`) and use `connect`, `disconnect`, `startRecording`, `stopRecording`, etc.
130
+
131
+ ---
132
+
133
+ ## API
134
+
135
+ ### Hook: `useWebSocketAudio(options)`
136
+
137
+ **Options** (`IUseWebVoiceOptions`):
138
+
139
+ | Option | Type | Required | Description |
140
+ |--------|------|----------|-------------|
141
+ | `websocketUrl` | `string` | ✅ | WebSocket URL (e.g. `wss://api.example.com/voice`). |
142
+ | `workletPath` | `string` | No | URL for the Audio Worklet. Default: `'/worklet/audio-processor.js'`. |
143
+ | `conversationId` | `string` | No | For your app; not sent by the hook. |
144
+ | `visualizerOptions` | `object` | No | `elementId`, `color`, `options`. |
145
+ | `events` | `object` | No | `onOpen`, `onClose`, `onException`. |
146
+ | `logger` | `{ info, error }` | No | Logging; defaults to console. |
147
+
148
+ **Returns:** `isConnected`, `isPlaying`, `connect`, `disconnect`, `reconnect`, `startRecording`, `stopRecording`, `isRecording`.
149
+
150
+ ---
151
+
152
+ ## WebSocket protocol (reference)
153
+
154
+ **Client → server:** `start`, `media` (base64 µ-law), `TTS_PLAYING`, `EOC`.
155
+ **Server → client:** `media` (base64 TTS), `barge`/`BARGE`, `EOC`, `stop`.
156
+
157
+ ---
158
+
159
+ ## Pushing changes (release steps)
160
+
161
+ When publishing a new patch version of this package, from the repo root run:
162
+
163
+ ```bash
164
+ pnpm run release:patch
165
+ ```
166
+
167
+ This script: builds the package, stages all changes, commits with message `build: v<current-version>` (or skips commit if nothing to commit), bumps the patch version, then pushes commits and tags.
168
+
169
+ For a **minor** or **major** bump, run the steps manually and use `pnpm version minor` or `pnpm version major` instead of `pnpm version patch` before pushing.
170
+
171
+ Consumers can then install the new tag, e.g. `#v1.0.2`.
172
+
173
+ ---
174
+
175
+ ## Troubleshooting
176
+
177
+ - **“Failed to load worklet”** — Serve `audio-processor.js` at `workletPath` (e.g. under `public/worklet/`).
178
+ - **No sound / no mic** — Check mic permissions; use `events.onException` and `logger`.
179
+ - **Visualizer not showing** — Set `visualizerOptions.elementId` to a mounted element id; install `audiomotion-analyzer`.
180
+
181
+ ---
182
+
183
+ ## TypeScript
184
+
185
+ ```ts
186
+ import type { IUseWebVoiceOptions, IWebVoiceLogger, ISocketEventData, ISocketMessage } from '@gnani/web-voice-hook';
187
+ ```
@@ -0,0 +1,9 @@
1
+ /**
2
+ * GnaniWebVoiceHook — Public API
3
+ *
4
+ * Use this file as the single entry point when consuming this package
5
+ * in another project (e.g. `import { useWebSocketAudio } from './GnaniWebVoiceHook'`).
6
+ */
7
+ export { useWebSocketAudio, CHANNELS, BITS_PER_SAMPLE } from './useWebVoice';
8
+ export type { IUseWebVoiceOptions, IWebVoiceLogger, ISocketEventData, ISocketMessage, } from './webVoice';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE7E,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,GACf,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export{useWebSocketAudio,CHANNELS,BITS_PER_SAMPLE}from"./useWebVoice";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["useWebSocketAudio","CHANNELS","BITS_PER_SAMPLE"],"sources":["../src/index.ts"],"mappings":"OAOSA,kBAAmBC,SAAUC,oBAAuB","ignoreList":[]}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * useWebVoice — React hook for real-time WebSocket voice (STT/TTS)
3
+ *
4
+ * Handles: mic capture → WebSocket, TTS playback ← WebSocket, optional visualizer,
5
+ * connect / disconnect / reconnect with full cleanup.
6
+ *
7
+ * @see README.md for setup (worklet path, peer deps) and usage examples.
8
+ */
9
+ import type { IUseWebVoiceOptions } from './webVoice';
10
+ export declare const CHANNELS = 1;
11
+ export declare const BITS_PER_SAMPLE = 16;
12
+ /**
13
+ * React hook for bidirectional WebSocket voice: mic → server, TTS ← server.
14
+ *
15
+ * @param options - websocketUrl, optional workletPath, visualizerOptions, events, logger.
16
+ * @returns { isConnected, isPlaying, connect, disconnect, reconnect, startRecording, stopRecording, isRecording }
17
+ */
18
+ export declare const useWebSocketAudio: ({ websocketUrl, workletPath, visualizerOptions: { elementId: visualizerElementId, color: visualizerColor, options: visualizerOptions, }, events: eventsOption, logger: loggerOption, }: IUseWebVoiceOptions) => {
19
+ isConnected: boolean;
20
+ isPlaying: boolean;
21
+ startRecording: () => Promise<void>;
22
+ stopRecording: () => void;
23
+ isRecording: boolean;
24
+ connect: () => void;
25
+ disconnect: () => void;
26
+ reconnect: (onConnectionSuccess?: () => void) => void;
27
+ };
28
+ //# sourceMappingURL=useWebVoice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWebVoice.d.ts","sourceRoot":"","sources":["../src/useWebVoice.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAoB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAaxE,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,eAAe,KAAK,CAAC;AAclC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,2LAU3B,mBAAmB;;;;;;;;sCAkgBK,MAAM,IAAI;CAyIpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import AudioMotionAnalyzer from"audiomotion-analyzer";import{useCallback,useMemo,useRef,useState}from"react";import{applyCustomColor,base64ToPCM16Data,convertPCMDataToFloat32,getBase64Audio,getVisualizerOptions,resampleAudio,resetAudioInput}from"./webVoiceUtils";const SAMPLE_RATE=44100;export const CHANNELS=1;export const BITS_PER_SAMPLE=16;const defaultLogger={info:(e,...r)=>console.log("[GnaniWebVoice]",e,...r),error:(e,...r)=>console.error("[GnaniWebVoice]",e,...r)},DEFAULT_WORKLET_PATH="/worklet/audio-processor.js";export const useWebSocketAudio=({websocketUrl:e,workletPath:r=DEFAULT_WORKLET_PATH,visualizerOptions:{elementId:t,color:n,options:c}={},events:o,logger:u})=>{const{onOpen:s,onClose:a,onException:i}=o??{},l=u??defaultLogger,[d,p]=useState(!1),f=useRef(null),g=useRef(null),m=useRef(null),y=useRef(!1),k=useRef(!0),S=useRef(),b=useRef(!1),C=useRef(!1),v=useRef(44100),h=useRef(!1),E=useRef(!1),R=useRef(0),A=useRef(null),[w,O]=useState(!1),P=useRef(!1),N=useRef([]),T=useCallback(()=>(g.current&&"closed"!==g.current.state||(g.current=new(window.AudioContext||window.webkitAudioContext)({sampleRate:44100,latencyHint:"playback"})),g.current),[]),L=useCallback(e=>{if(!t||A.current||C.current)A.current?.connectInput(e);else{const r=new AudioMotionAnalyzer(document.getElementById(t),{...c??getVisualizerOptions(e)});r.start(),n&&applyCustomColor(r,n),A.current=r}},[]),_=useCallback(async()=>{if(!b.current){resetAudioInput(S.current);try{S.current=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:44100,channelCount:1,echoCancellation:{ideal:!0},noiseSuppression:{ideal:!0},autoGainControl:{ideal:!0}}});const e=T(),r=e.createMediaStreamSource(S.current),t=e.createDynamicsCompressor();t.threshold.value=-30,t.knee.value=40,t.ratio.value=8,t.attack.value=.002,t.release.value=.1;const n=e.createGain();n.gain.value=1.2,r.connect(t).connect(n),L(r),b.current=!0}catch(e){throw l.error("Error setting up audio stream:",e),i?.(e),e}}},[T,L]),{startProcessing:I,stopProcessing:M,isProcessing:W}=useMemo(()=>{let e=null,t=null;return{startProcessing:async()=>{if(S.current)try{const n=T();await n.audioWorklet.addModule(r),t=n.createMediaStreamSource(S.current),e=new AudioWorkletNode(n,"audio-processor",{numberOfInputs:1,numberOfOutputs:1,channelCount:1,processorOptions:{sampleRate:n.sampleRate}}),e.port.onmessage=e=>{if(f.current?.readyState===WebSocket.OPEN){const{data:r,timestamp:t}=e.data,n=getBase64Audio(r);f.current.send(JSON.stringify({event:"media",media:{payload:n,timestamp:t}}))}},t.connect(e)}catch(e){l.error("Failed to start audio processing:",e),i?.(e)}},stopProcessing:()=>{e&&(e.disconnect(),e=null),t&&(t.disconnect(),t=null)},isProcessing:!!e}},[T,r]),D=useCallback(e=>{T();try{const r=base64ToPCM16Data(e),t=convertPCMDataToFloat32(r),n=44100===v.current?t:resampleAudio(t,v.current,44100);N.current.push(n),N.current.reduce((e,r)=>e+r.length,0)>=44100&&G()}catch(e){l.error("Error processing audio chunk:",e)}},[T]),G=useCallback(()=>{const e=T();if(!e||P.current)return;let r;if(0===N.current.length){P.current=!1,p(!1),f.current?.send(JSON.stringify({event:"TTS_PLAYING",media:{tts_playing:!1}})),E.current=!1;const e=Math.floor(1*v.current*2);r=new Float32Array(e).fill(0)}else{E.current||(f.current?.send(JSON.stringify({event:"TTS_PLAYING",media:{tts_playing:!0}})),E.current=!0),P.current=!0,p(!0);let e=0;const t=[];for(;N.current.length>0&&e<44100;){const r=N.current.shift();t.push(r),e+=r.length}r=new Float32Array(e);let n=0;for(const e of t)r.set(e,n),n+=e.length}const t=e.createBuffer(1,r.length,44100);t.getChannelData(0).set(r);const n=e.createBufferSource();n.buffer=t,n.connect(e.destination),L(n),n.onended=()=>{P.current=!1,N.current.length>0?G():(p(!1),f.current?.send(JSON.stringify({event:"TTS_PLAYING",media:{tts_playing:!1}})),E.current=!1,h.current&&f.current?.close())},n.start(),m.current=n,y.current=!0},[T,L]),J=useCallback(async e=>{try{"media"===e.event&&e.media?.payload?(0===R.current&&(R.current=Date.now(),l.info("Chunk received at:",R.current)),v.current=e.sample_rate??44100,D(e.media.payload)):["barge","BARGE"].includes(e.event)?(l.info("Barged"),N.current=[]):"EOC"===e.event?(l.info("EOC event occurred"),f.current?.send(JSON.stringify({event:"EOC"}))):"stop"===e.event?(l.info("Stop event occurred"),f.current?.readyState===WebSocket.OPEN&&(h.current=!0)):l.info("Unhandled message type:",e)}catch(e){l.error("Error processing audio message:",e)}},[]),x=useCallback(e=>{if(!C.current){if(C.current=!0,M(),f.current&&(f.current.readyState!==WebSocket.OPEN&&f.current.readyState!==WebSocket.CONNECTING||f.current.close(),f.current=null),A.current?.stop(),A.current?.destroy(),g.current&&(g.current.close(),g.current=null),m.current&&(m.current.stop(),m.current.disconnect(),m.current=null),S.current){S.current.getTracks().forEach(e=>{e.stop(),e.enabled=!1,S.current?.removeTrack(e)}),S.current=void 0}N.current=[],y.current=!1,b.current=!1,k.current=!0,P.current=!1,h.current=!1,p(!1),O(!1),a?.(e)}},[M,a]),B=useCallback(()=>{if(!e||f.current||C.current||w)return;C.current=!1,k.current=!0;const r=new WebSocket(e);f.current=r,r.onopen=async()=>{C.current?r.close():(O(!0),await _(),await I(),r.send(JSON.stringify({event:"start"})))},r.onmessage=e=>{if(!C.current)try{const r=JSON.parse(e.data);r&&J(r)}catch(e){l.error("Error parsing websocket message:",e)}},r.onclose=e=>{"LINK_EXPIRED"===e.reason&&(l.info("Link expired"),location.reload()),C.current||x("server"),M()},r.onerror=e=>{l.error("WebSocket error:",e),i?.(e),C.current||x("server")}},[e,s,a,i,_,I,w]),F=useCallback(()=>{x("client")},[x]),U=useCallback(r=>{if(f.current&&(f.current.close(),f.current=null),C.current=!1,k.current=!0,y.current=!1,b.current=!1,P.current=!1,h.current=!1,O(!1),p(!1),N.current=[],g.current&&(g.current.close(),g.current=null),m.current&&(m.current.stop(),m.current.disconnect(),m.current=null),A.current&&(A.current.stop(),A.current.destroy(),A.current=null),S.current){S.current.getTracks().forEach(e=>{e.stop(),e.enabled=!1,S.current?.removeTrack(e)}),S.current=void 0}if(M(),!e)return void l.error("Cannot reconnect: websocketUrl is required");const t=new WebSocket(e);f.current=t,t.onopen=async()=>{C.current?t.close():(O(!0),await _(),await I(),t.send(JSON.stringify({event:"start"})),r?.())},t.onmessage=e=>{if(!C.current)try{const r=JSON.parse(e.data);r&&J(r)}catch(e){l.error("Error parsing websocket message:",e),i?.(e)}},t.onclose=e=>{"LINK_EXPIRED"===e.reason&&(l.info("Link expired"),location.reload()),C.current||x("server"),M()},t.onerror=e=>{l.error("WebSocket error:",e),i?.(e),C.current||x("server")}},[e,s,a,i,_,I,M,x]);return{isConnected:w,isPlaying:d,startRecording:I,stopRecording:M,isRecording:W,connect:B,disconnect:F,reconnect:U}};
2
+ //# sourceMappingURL=useWebVoice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWebVoice.js","names":["AudioMotionAnalyzer","useCallback","useMemo","useRef","useState","applyCustomColor","base64ToPCM16Data","convertPCMDataToFloat32","getBase64Audio","getVisualizerOptions","resampleAudio","resetAudioInput","SAMPLE_RATE","CHANNELS","BITS_PER_SAMPLE","defaultLogger","info","arg","args","console","log","error","DEFAULT_WORKLET_PATH","useWebSocketAudio","websocketUrl","workletPath","visualizerOptions","elementId","visualizerElementId","color","visualizerColor","options","events","eventsOption","logger","loggerOption","onOpen","onClose","onException","isPlaying","setIsPlaying","websocketRef","audioContextRef","sourceNodeRef","isPlayingRef","isFirstChunk","streamRef","isAudioNodesConnected","isCleanedUp","backendSampleRate","isStopReceived","lastSentTTSEvent","chunkReceivedAt","analyzerRef","isConnected","setIsConnected","isPlayingAudio","audioBufferRef","getOrCreateAudioContext","current","state","window","AudioContext","webkitAudioContext","sampleRate","latencyHint","initializeVisualizer","source","connectInput","analyzer","document","getElementById","start","setupAudioStream","async","navigator","mediaDevices","getUserMedia","audio","channelCount","echoCancellation","ideal","noiseSuppression","autoGainControl","audioContext","createMediaStreamSource","compressor","createDynamicsCompressor","threshold","value","knee","ratio","attack","release","gainNode","createGain","gain","connect","e","startProcessing","stopProcessing","isProcessing","audioWorkletNode","sourceNode","audioWorklet","addModule","AudioWorkletNode","numberOfInputs","numberOfOutputs","processorOptions","port","onmessage","event","readyState","WebSocket","OPEN","data","timestamp","base64Data","send","JSON","stringify","media","payload","disconnect","processAudioChunk","pcm16Data","float32Data","rightSampled","push","reduce","acc","chunk","length","playNextChunk","audioData","tts_playing","silenceLength","Math","floor","Float32Array","fill","totalLength","chunks","shift","offset","set","audioBuffer","createBuffer","getChannelData","createBufferSource","buffer","destination","onended","close","processAudioMessage","message","Date","now","sample_rate","includes","cleanup","CONNECTING","stop","destroy","getTracks","forEach","track","enabled","removeTrack","undefined","ws","onopen","parse","onclose","reason","location","reload","onerror","reconnect","onConnectionSuccess","startRecording","stopRecording","isRecording"],"sources":["../src/useWebVoice.ts"],"mappings":"OASOA,wBAAyB,8BACvBC,YAAaC,QAASC,OAAQC,aAAgB,eAIrDC,iBACAC,kBACAC,wBACAC,eACAC,qBACAC,cACAC,oBACK,kBAGP,MAAMC,YAAc,aACb,MAAMC,SAAW,SACjB,MAAMC,gBAAkB,GAG/B,MAAMC,cAAgB,CACpBC,KAAM,CAACC,KAAiBC,IAEtBC,QAAQC,IAAI,kBAAmBH,KAAQC,GACzCG,MAAO,CAACJ,KAAiBC,IAEvBC,QAAQE,MAAM,kBAAmBJ,KAAQC,IAGvCI,qBAAuB,qCAQtB,MAAMC,kBAAoB,EAC/BC,eACAC,cAAcH,qBACdI,mBACEC,UAAWC,EACXC,MAAOC,EACPC,QAASL,GACP,GACJM,OAAQC,EACRC,OAAQC,MAER,MAAMC,OAAEA,EAAMC,QAAEA,EAAOC,YAAEA,GAAgBL,GAAgB,GACnDC,EAASC,GAAgBpB,eAExBwB,EAAWC,GAAgBpC,UAAS,GAErCqC,EAAetC,OAAyB,MACxCuC,EAAkBvC,OAA4B,MAC9CwC,EAAgBxC,OAAqC,MACrDyC,EAAezC,QAAO,GACtB0C,EAAe1C,QAAO,GACtB2C,EAAY3C,SACZ4C,EAAwB5C,QAAO,GAC/B6C,EAAc7C,QAAO,GACrB8C,EAAoB9C,OA9CR,OA+CZ+C,EAAiB/C,QAAO,GACxBgD,EAAmBhD,QAAO,GAC1BiD,EAAkBjD,OAAO,GAEzBkD,EAAclD,OAAmC,OAEhDmD,EAAaC,GAAkBnD,UAAS,GACzCoD,EAAiBrD,QAAO,GAKxBsD,EAAiBtD,OAAuB,IAGxCuD,EAA0BzD,YAAY,KAEvCyC,EAAgBiB,SACiB,WAAlCjB,EAAgBiB,QAAQC,QAExBlB,EAAgBiB,QAAU,IAAKE,OAAOC,cACnCD,OAAeE,oBAAoB,CACpCC,WArEY,MAsEZC,YAAa,cAGVvB,EAAgBiB,SACtB,IAEGO,EAAuBjE,YAC1BkE,IACC,IAAIvC,GAAwByB,EAAYM,SAAYX,EAAYW,QAiB9DN,EAAYM,SAASS,aAAaD,OAjBqC,CACvE,MAAME,EAAW,IAAIrE,oBACnBsE,SAASC,eAAe3C,GACxB,IACMF,GAAqBjB,qBAAqB0D,KAKlDE,EAASG,QAEL1C,GACFzB,iBAAiBgE,EAAUvC,GAG7BuB,EAAYM,QAAUU,CACxB,GAIF,IAGII,EAAmBxE,YAAYyE,UACnC,IAAI3B,EAAsBY,QAA1B,CAEAhD,gBAAgBmC,EAAUa,SAE1B,IAEEb,EAAUa,cAAgBgB,UAAUC,aAAaC,aAAa,CAC5DC,MAAO,CACLd,WA9GU,MA+GVe,aA9Gc,EA+GdC,iBAAkB,CAChBC,OAAO,GAETC,iBAAkB,CAChBD,OAAO,GAETE,gBAAiB,CACfF,OAAO,MAKb,MAAMG,EAAe1B,IAEfS,EAASiB,EAAaC,wBAAwBvC,EAAUa,SAGxD2B,EAAaF,EAAaG,2BAChCD,EAAWE,UAAUC,OAAS,GAC9BH,EAAWI,KAAKD,MAAQ,GACxBH,EAAWK,MAAMF,MAAQ,EACzBH,EAAWM,OAAOH,MAAQ,KAC1BH,EAAWO,QAAQJ,MAAQ,GAG3B,MAAMK,EAAWV,EAAaW,aAC9BD,EAASE,KAAKP,MAAQ,IAGtBtB,EAAO8B,QAAQX,GAAYW,QAAQH,GAEnC5B,EAAqBC,GAErBpB,EAAsBY,SAAU,CAClC,CAAE,MAAOuC,GAGP,MAFAhE,EAAOb,MAAM,iCAAkC6E,GAC/C5D,IAAc4D,GACRA,CACR,CAhDmC,GAiDlC,CAACxC,EAAyBQ,KAEvBiC,gBAAEA,EAAeC,eAAEA,EAAcC,aAAEA,GAAiBnG,QAAQ,KAChE,IAAIoG,EAA4C,KAC5CC,EAAgD,KA8DpD,MAAO,CACLJ,gBA7DYzB,UACZ,GAAK5B,EAAUa,QAEf,IACE,MAAMyB,EAAe1B,UAGf0B,EAAaoB,aAAaC,UAAUhF,GAE1C8E,EAAanB,EAAaC,wBAAwBvC,EAAUa,SAE5D2C,EAAmB,IAAII,iBACrBtB,EACA,kBACA,CACEuB,eAAgB,EAChBC,gBAAiB,EACjB7B,aAAc,EACd8B,iBAAkB,CAChB7C,WAAYoB,EAAapB,cAM/BsC,EAAiBQ,KAAKC,UAAaC,IACjC,GAAIvE,EAAakB,SAASsD,aAAeC,UAAUC,KAAM,CACvD,MAAMC,KAAEA,EAAIC,UAAEA,GAAcL,EAAMI,KAC5BE,EAAa9G,eAAe4G,GAElC3E,EAAakB,QAAQ4D,KACnBC,KAAKC,UAAU,CACbT,MAAO,QACPU,MAAO,CACLC,QAASL,EACTD,eAIR,GAGFd,EAAWN,QAAQK,EACrB,CAAE,MAAOjF,GACPa,EAAOb,MAAM,oCAAqCA,GAClDiB,IAAcjB,EAChB,GAgBA+E,eAbW,KACPE,IACFA,EAAiBsB,aACjBtB,EAAmB,MAEjBC,IACFA,EAAWqB,aACXrB,EAAa,OAOfF,eAAgBC,IAEjB,CAAC5C,EAAyBjC,IAEvBoG,EAAoB5H,YACvB0H,IAECjE,IAEA,IAEE,MAAMoE,EAAYxH,kBAAkBqH,GAC9BI,EAAcxH,wBAAwBuH,GAGtCE,EA3OM,QA4OV/E,EAAkBU,QACdoE,EACArH,cACEqH,EACA9E,EAAkBU,QAhPd,OAoPZF,EAAeE,QAAQsE,KAAKD,GAI1BvE,EAAeE,QAAQuE,OACrB,CAACC,EAAKC,IAAUD,EAAMC,EAAMC,OAC5B,IAjMSzH,OAoMX0H,GAEJ,CAAE,MAAOjH,GACPa,EAAOb,MAAM,gCAAiCA,EAChD,GAEF,CAACqC,IAGG4E,EAAgBrI,YAAY,KAEhC,MAAMmF,EAAe1B,IACrB,IAAK0B,GAAgB5B,EAAeG,QAAS,OAG7C,IAAI4E,EAEJ,GAAsC,IAAlC9E,EAAeE,QAAQ0E,OAAc,CACvC7E,EAAeG,SAAU,EACzBnB,GAAa,GAEbC,EAAakB,SAAS4D,KACpBC,KAAKC,UAAU,CACbT,MAAO,cACPU,MAAO,CACLc,aAAa,MAKnBrF,EAAiBQ,SAAU,EAG3B,MAAM8E,EAAgBC,KAAKC,MAtOP,EAuOlB1F,EAAkBU,QAA4B,GAEhD4E,EAAY,IAAIK,aAAaH,GAAeI,KAAK,EACnD,KAAO,CACA1F,EAAiBQ,UACpBlB,EAAakB,SAAS4D,KACpBC,KAAKC,UAAU,CACbT,MAAO,cACPU,MAAO,CACLc,aAAa,MAInBrF,EAAiBQ,SAAU,GAG7BH,EAAeG,SAAU,EACzBnB,GAAa,GAEb,IAAIsG,EAAc,EAClB,MAAMC,EAAyB,GAE/B,KAAOtF,EAAeE,QAAQ0E,OAAS,GAAKS,EA5P7BlI,OA4PuD,CACpE,MAAMwH,EAAQ3E,EAAeE,QAAQqF,QACrCD,EAAOd,KAAKG,GACZU,GAAeV,EAAMC,MACvB,CAGAE,EAAY,IAAIK,aAAaE,GAC7B,IAAIG,EAAS,EACb,IAAK,MAAMb,KAASW,EAClBR,EAAUW,IAAId,EAAOa,GACrBA,GAAUb,EAAMC,MAEpB,CAGA,MAAMc,EAAc/D,EAAagE,aAC/B,EACAb,EAAUF,OAvUI,OA4UhBc,EAAYE,eAAe,GAAGH,IAAIX,GAGlC,MAAMpE,EAASiB,EAAakE,qBAC5BnF,EAAOoF,OAASJ,EAEhBhF,EAAO8B,QAAQb,EAAaoE,aAG5BtF,EAAqBC,GAGrBA,EAAOsF,QAAU,KACfjG,EAAeG,SAAU,EAErBF,EAAeE,QAAQ0E,OAAS,EAClCC,KAEA9F,GAAa,GACbC,EAAakB,SAAS4D,KACpBC,KAAKC,UAAU,CACbT,MAAO,cACPU,MAAO,CACLc,aAAa,MAInBrF,EAAiBQ,SAAU,EAEvBT,EAAeS,SACjBlB,EAAakB,SAAS+F,UAM5BvF,EAAOK,QAEP7B,EAAcgB,QAAUQ,EAExBvB,EAAae,SAAU,GACtB,CAACD,EAAyBQ,IAEvByF,EAAsB1J,YAAYyE,MAAOkF,IAC7C,IACwB,UAAlBA,EAAQ5C,OAAqB4C,EAAQlC,OAAOC,SACd,IAA5BvE,EAAgBO,UAClBP,EAAgBO,QAAUkG,KAAKC,MAC/B5H,EAAOlB,KAAK,qBAAsBoC,EAAgBO,UAEpDV,EAAkBU,QAAUiG,EAAQG,aA9XxB,MA+XZlC,EAAkB+B,EAAQlC,MAAMC,UACvB,CAAC,QAAS,SAASqC,SAASJ,EAAQ5C,QAC7C9E,EAAOlB,KAAK,UACZyC,EAAeE,QAAU,IACE,QAAlBiG,EAAQ5C,OACjB9E,EAAOlB,KAAK,sBACZyB,EAAakB,SAAS4D,KAAKC,KAAKC,UAAU,CAAET,MAAO,UACxB,SAAlB4C,EAAQ5C,OACjB9E,EAAOlB,KAAK,uBACRyB,EAAakB,SAASsD,aAAeC,UAAUC,OACjDjE,EAAeS,SAAU,IAG3BzB,EAAOlB,KAAK,0BAA2B4I,EAE3C,CAAE,MAAOvI,GACPa,EAAOb,MAAM,kCAAmCA,EAClD,GACC,IAEG4I,EAAUhK,YACbkE,IACC,IAAInB,EAAYW,QAAhB,CAkCA,GAjCAX,EAAYW,SAAU,EAGtByC,IAGI3D,EAAakB,UAEblB,EAAakB,QAAQsD,aAAeC,UAAUC,MAC9C1E,EAAakB,QAAQsD,aAAeC,UAAUgD,YAE9CzH,EAAakB,QAAQ+F,QAEvBjH,EAAakB,QAAU,MAGzBN,EAAYM,SAASwG,OACrB9G,EAAYM,SAASyG,UAGjB1H,EAAgBiB,UAClBjB,EAAgBiB,QAAQ+F,QACxBhH,EAAgBiB,QAAU,MAIxBhB,EAAcgB,UAChBhB,EAAcgB,QAAQwG,OACtBxH,EAAcgB,QAAQiE,aACtBjF,EAAcgB,QAAU,MAItBb,EAAUa,QAAS,CACNb,EAAUa,QAAQ0G,YAC1BC,QAASC,IACdA,EAAMJ,OACNI,EAAMC,SAAU,EAChB1H,EAAUa,SAAS8G,YAAYF,KAEjCzH,EAAUa,aAAU+G,CACtB,CAGAjH,EAAeE,QAAU,GACzBf,EAAae,SAAU,EACvBZ,EAAsBY,SAAU,EAChCd,EAAac,SAAU,EACvBH,EAAeG,SAAU,EACzBT,EAAeS,SAAU,EACzBnB,GAAa,GAGbe,GAAe,GAGflB,IAAU8B,EAzDe,GA2D3B,CAACiC,EAAgB/D,IAGb4D,EAAUhG,YAAY,KAE1B,IACGuB,GACDiB,EAAakB,SACbX,EAAYW,SACZL,EAEA,OAGFN,EAAYW,SAAU,EACtBd,EAAac,SAAU,EAEvB,MAAMgH,EAAK,IAAIzD,UAAU1F,GAEzBiB,EAAakB,QAAUgH,EAEvBA,EAAGC,OAASlG,UACN1B,EAAYW,QACdgH,EAAGjB,SAGLnG,GAAe,SAETkB,UACA0B,IACNwE,EAAGpD,KAAKC,KAAKC,UAAU,CAAET,MAAO,aAGlC2D,EAAG5D,UAAaC,IACd,IAAIhE,EAAYW,QAChB,IACE,MAAMyD,EAAOI,KAAKqD,MAAM7D,EAAMI,MAC1BA,GACFuC,EAAoBvC,EAExB,CAAE,MAAO/F,GACPa,EAAOb,MAAM,mCAAoCA,EACnD,GAGFsJ,EAAGG,QAAW5E,IAEG,iBADAA,EAAE6E,SAEf7I,EAAOlB,KAAK,gBACZgK,SAASC,UAGNjI,EAAYW,SACfsG,EAAQ,UAGV7D,KAGFuE,EAAGO,QAAW7J,IACZa,EAAOb,MAAM,mBAAoBA,GACjCiB,IAAcjB,GAET2B,EAAYW,SACfsG,EAAQ,YAGX,CACDzI,EACAY,EACAC,EACAC,EACAmC,EACA0B,EACA7C,IAGIsE,EAAa3H,YAAY,KAC7BgK,EAAQ,WACP,CAACA,IAEEkB,EAAYlL,YACfmL,IA2CC,GAzCI3I,EAAakB,UACflB,EAAakB,QAAQ+F,QACrBjH,EAAakB,QAAU,MAIzBX,EAAYW,SAAU,EACtBd,EAAac,SAAU,EACvBf,EAAae,SAAU,EACvBZ,EAAsBY,SAAU,EAChCH,EAAeG,SAAU,EACzBT,EAAeS,SAAU,EAGzBJ,GAAe,GACff,GAAa,GAGbiB,EAAeE,QAAU,GAGrBjB,EAAgBiB,UAClBjB,EAAgBiB,QAAQ+F,QACxBhH,EAAgBiB,QAAU,MAIxBhB,EAAcgB,UAChBhB,EAAcgB,QAAQwG,OACtBxH,EAAcgB,QAAQiE,aACtBjF,EAAcgB,QAAU,MAItBN,EAAYM,UACdN,EAAYM,QAAQwG,OACpB9G,EAAYM,QAAQyG,UACpB/G,EAAYM,QAAU,MAIpBb,EAAUa,QAAS,CACNb,EAAUa,QAAQ0G,YAC1BC,QAASC,IACdA,EAAMJ,OACNI,EAAMC,SAAU,EAChB1H,EAAUa,SAAS8G,YAAYF,KAEjCzH,EAAUa,aAAU+G,CACtB,CAMA,GAHAtE,KAGK5E,EAEH,YADAU,EAAOb,MAAM,8CAIf,MAAMsJ,EAAK,IAAIzD,UAAU1F,GAEzBiB,EAAakB,QAAUgH,EAEvBA,EAAGC,OAASlG,UACN1B,EAAYW,QACdgH,EAAGjB,SAGLnG,GAAe,SAETkB,UACA0B,IACNwE,EAAGpD,KAAKC,KAAKC,UAAU,CAAET,MAAO,WAChCoE,QAGFT,EAAG5D,UAAaC,IACd,IAAIhE,EAAYW,QAChB,IACE,MAAMyD,EAAOI,KAAKqD,MAAM7D,EAAMI,MAC1BA,GACFuC,EAAoBvC,EAExB,CAAE,MAAO/F,GACPa,EAAOb,MAAM,mCAAoCA,GACjDiB,IAAcjB,EAChB,GAGFsJ,EAAGG,QAAW5E,IAEG,iBADAA,EAAE6E,SAEf7I,EAAOlB,KAAK,gBACZgK,SAASC,UAGNjI,EAAYW,SACfsG,EAAQ,UAGV7D,KAGFuE,EAAGO,QAAW7J,IACZa,EAAOb,MAAM,mBAAoBA,GACjCiB,IAAcjB,GAET2B,EAAYW,SACfsG,EAAQ,YAId,CACEzI,EACAY,EACAC,EACAC,EACAmC,EACA0B,EACAC,EACA6D,IAIJ,MAAO,CACL3G,cACAf,YACA8I,eAAgBlF,EAChBmF,cAAelF,EACfmF,YAAalF,EACbJ,UACA2B,aACAuD","ignoreList":[]}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * webVoiceUtils — Audio encoding/decoding and visualizer helpers
3
+ *
4
+ * Used by useWebVoice for: Float32 → PCM → µ-law → base64 (outbound),
5
+ * base64 → PCM16 → Float32 (inbound), resampling, and audiomotion-analyzer options.
6
+ */
7
+ import type { AudioMotionAnalyzer, ConstructorOptions } from 'audiomotion-analyzer';
8
+ /** Float32 [-1, 1] → Int16 PCM for encoding. */
9
+ export declare function floatTo16BitPCM(float32Array: Float32Array): Int16Array;
10
+ export declare const base64ToPCM16Data: (base64Data: string) => Int16Array;
11
+ export declare function linearToMuLaw(pcm: Int16Array): Uint8Array;
12
+ export declare const getBase64Audio: (audioData: Float32Array) => string;
13
+ export declare const resetAudioInput: (stream?: MediaStream) => void;
14
+ export declare const createWavHeader: (dataLength: number) => ArrayBuffer;
15
+ export declare const getAudioWorkletModule: () => string;
16
+ export declare const convertPCMDataToFloat32: (pcm16Data: Int16Array) => Float32Array;
17
+ export declare const convertPCMDataWithWavHeaderToFloat32: (pcm16Data: Int16Array) => Float32Array;
18
+ export declare const SAMPLE_RATE = 44100;
19
+ export declare const CHANNELS = 1;
20
+ export declare const BITS_PER_SAMPLE = 16;
21
+ export declare const WORKLET_NODE_OPTIONS: {
22
+ processorOptions: {
23
+ sampleRate: number;
24
+ channelCount: number;
25
+ };
26
+ numberOfInputs: number;
27
+ numberOfOutputs: number;
28
+ channelCount: number;
29
+ };
30
+ export declare const resampleAudio: (audioData: Float32Array, originalSampleRate: number, targetSampleRate: number) => Float32Array;
31
+ export declare const getVisualizerOptions: (source: AudioBufferSourceNode | MediaStreamAudioSourceNode) => ConstructorOptions;
32
+ export declare const applyCustomColor: (analyzer: AudioMotionAnalyzer, color?: string) => void;
33
+ //# sourceMappingURL=webVoiceUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webVoiceUtils.d.ts","sourceRoot":"","sources":["../src/webVoiceUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAE9B,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,YAAY,EAAE,YAAY,GAAG,UAAU,CAOtE;AAED,eAAO,MAAM,iBAAiB,eAAgB,MAAM,eAgBnD,CAAC;AAEF,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,CAqCzD;AAED,eAAO,MAAM,cAAc,cAAe,YAAY,WAUrD,CAAC;AAEF,eAAO,MAAM,eAAe,YAAa,WAAW,SAEnD,CAAC;AAEF,eAAO,MAAM,eAAe,eAAgB,MAAM,gBA0CjD,CAAC;AAEF,eAAO,MAAM,qBAAqB,cAmB/B,CAAC;AAEJ,eAAO,MAAM,uBAAuB,cAAe,UAAU,iBAO5D,CAAC;AAEF,eAAO,MAAM,oCAAoC,cAAe,UAAU,iBAazE,CAAC;AAEF,eAAO,MAAM,WAAW,QAAQ,CAAC;AACjC,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,eAAO,MAAM,oBAAoB;;;;;;;;CAQhC,CAAC;AAEF,eAAO,MAAM,aAAa,cACb,YAAY,sBACH,MAAM,oBACR,MAAM,KACvB,YA0BF,CAAC;AAEF,eAAO,MAAM,oBAAoB,WACvB,qBAAqB,GAAG,0BAA0B,KACzD,kBAqDD,CAAC;AAGH,eAAO,MAAM,gBAAgB,aACjB,mBAAmB,UACrB,MAAM,SAuBf,CAAC"}
@@ -0,0 +1,2 @@
1
+ export function floatTo16BitPCM(t){const e=new Int16Array(t.length);for(let o=0;o<t.length;o++){const r=Math.max(-1,Math.min(1,t[o]));e[o]=r<0?32768*r:32767*r}return e}export const base64ToPCM16Data=t=>{const e=atob(t),o=new ArrayBuffer(e.length),r=new Uint8Array(o);for(let t=0;t<e.length;t++)r[t]=e.charCodeAt(t);return new Int16Array(o)};export function linearToMuLaw(t){const e=new Uint8Array(t.length);for(let o=0;o<t.length;o++){let r=t[o],n=r>>8&128;n&&(r=-r),r>32635&&(r=32635),r+=132;let a,s=7;for(;s>0&&!(16384&r);s--)r<<=1;a=r>>9&15;let i=~(n|s<<4|a);e[o]=255&i}return e}export const getBase64Audio=t=>{const e=linearToMuLaw(floatTo16BitPCM(t));return btoa(String.fromCharCode.apply(null,Array.from(e)))};export const resetAudioInput=t=>{t?.getTracks().forEach(t=>t.stop())};export const createWavHeader=t=>{const e=new ArrayBuffer(44),o=new DataView(e);return o.setUint8(0,"R".charCodeAt(0)),o.setUint8(1,"I".charCodeAt(0)),o.setUint8(2,"F".charCodeAt(0)),o.setUint8(3,"F".charCodeAt(0)),o.setUint32(4,t+36,!0),o.setUint8(8,"W".charCodeAt(0)),o.setUint8(9,"A".charCodeAt(0)),o.setUint8(10,"V".charCodeAt(0)),o.setUint8(11,"E".charCodeAt(0)),o.setUint8(12,"f".charCodeAt(0)),o.setUint8(13,"m".charCodeAt(0)),o.setUint8(14,"t".charCodeAt(0)),o.setUint8(15," ".charCodeAt(0)),o.setUint32(16,16,!0),o.setUint16(20,1,!0),o.setUint16(22,CHANNELS,!0),o.setUint32(24,SAMPLE_RATE,!0),o.setUint32(28,SAMPLE_RATE*CHANNELS*(BITS_PER_SAMPLE/8),!0),o.setUint16(32,CHANNELS*(BITS_PER_SAMPLE/8),!0),o.setUint16(34,BITS_PER_SAMPLE,!0),o.setUint8(36,"d".charCodeAt(0)),o.setUint8(37,"a".charCodeAt(0)),o.setUint8(38,"t".charCodeAt(0)),o.setUint8(39,"a".charCodeAt(0)),o.setUint32(40,t,!0),e};export const getAudioWorkletModule=()=>URL.createObjectURL(new Blob(["\n class AudioProcessor extends AudioWorkletProcessor {\n process(inputs, outputs) {\n const input = inputs[0][0];\n if (input) {\n this.port.postMessage(input);\n }\n return true;\n }\n }\n registerProcessor('audio-processor', AudioProcessor);\n"],{type:"text/javascript"}));export const convertPCMDataToFloat32=t=>{const e=new Float32Array(t.length);for(let o=0;o<t.length;o++)e[o]=t[o]/(t[o]<0?32768:32767);return e};export const convertPCMDataWithWavHeaderToFloat32=t=>{const e=createWavHeader(t.byteLength),o=new Int16Array(e),r=new Int16Array(o.length+t.length);r.set(o),r.set(t,o.length);return convertPCMDataToFloat32(r)};export const SAMPLE_RATE=44100;export const CHANNELS=1;export const BITS_PER_SAMPLE=16;export const WORKLET_NODE_OPTIONS={processorOptions:{sampleRate:SAMPLE_RATE,channelCount:CHANNELS},numberOfInputs:1,numberOfOutputs:1,channelCount:CHANNELS};export const resampleAudio=(t,e,o)=>{const r=o/e,n=Math.floor(t.length*r),a=new Float32Array(n);for(let e=0;e<n;e++){const o=e/r,n=Math.floor(o),s=o-n;n>=t.length-1?a[e]=t[t.length-1]:a[e]=t[n]*(1-s)+t[n+1]*s}return a};export const getVisualizerOptions=t=>({source:t,smoothing:.8,lineWidth:16,maxFreq:1300,mode:2,width:400,height:200,volume:0,showScaleX:!1,showPeaks:!1,alphaBars:!1,ansiBands:!1,barSpace:.75,bgAlpha:1,channelLayout:"single",fadePeaks:!1,fillAlpha:1,frequencyScale:"log",gradient:"prism",gravity:8,ledBars:!1,linearAmplitude:!0,linearBoost:1.6,loRes:!1,lumiBars:!1,maxDecibels:-35,maxFPS:0,minDecibels:-85,minFreq:300,mirror:0,noteLabels:!1,outlineBars:!0,overlay:!0,peakFadeTime:750,peakHoldTime:500,peakLine:!1,radial:!1,radialInvert:!1,radius:.3,reflexAlpha:1,reflexBright:1,reflexFit:!0,reflexRatio:.5,roundBars:!0,showBgColor:!1,showFPS:!1,showScaleY:!1,spinSpeed:1,splitGradient:!1,trueLeds:!1,useCanvas:!0,weightingFilter:"A"});export const applyCustomColor=(t,e)=>{if(t&&t.canvas){const o=t.canvas,r=o.getContext("2d");if(!r)return;const n=r.drawImage;r.drawImage=function(t,...a){n.apply(r,[t,...a]),r.globalCompositeOperation="source-atop",r.fillStyle=e??"#9E77ED",r.fillRect(0,0,o.width,o.height),r.globalCompositeOperation="source-over"}}};
2
+ //# sourceMappingURL=webVoiceUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webVoiceUtils.js","names":["floatTo16BitPCM","float32Array","int16Array","Int16Array","length","i","s","Math","max","min","base64ToPCM16Data","base64Data","binaryString","atob","buffer","ArrayBuffer","view","Uint8Array","charCodeAt","linearToMuLaw","pcm","muLawCompressed","sample","sign","mantissa","exponent","ulawByte","getBase64Audio","audioData","muLawData","btoa","String","fromCharCode","apply","Array","from","resetAudioInput","stream","getTracks","forEach","track","stop","createWavHeader","dataLength","DataView","setUint8","setUint32","setUint16","CHANNELS","SAMPLE_RATE","BITS_PER_SAMPLE","getAudioWorkletModule","URL","createObjectURL","Blob","type","convertPCMDataToFloat32","pcm16Data","float32Data","Float32Array","convertPCMDataWithWavHeaderToFloat32","wavHeader","byteLength","headerView","combinedBuffer","set","WORKLET_NODE_OPTIONS","processorOptions","sampleRate","channelCount","numberOfInputs","numberOfOutputs","resampleAudio","originalSampleRate","targetSampleRate","ratio","newLength","floor","result","position","index","fraction","getVisualizerOptions","source","smoothing","lineWidth","maxFreq","mode","width","height","volume","showScaleX","showPeaks","alphaBars","ansiBands","barSpace","bgAlpha","channelLayout","fadePeaks","fillAlpha","frequencyScale","gradient","gravity","ledBars","linearAmplitude","linearBoost","loRes","lumiBars","maxDecibels","maxFPS","minDecibels","minFreq","mirror","noteLabels","outlineBars","overlay","peakFadeTime","peakHoldTime","peakLine","radial","radialInvert","radius","reflexAlpha","reflexBright","reflexFit","reflexRatio","roundBars","showBgColor","showFPS","showScaleY","spinSpeed","splitGradient","trueLeds","useCanvas","weightingFilter","applyCustomColor","analyzer","color","canvas","ctx","getContext","originalDrawImage","drawImage","image","args","globalCompositeOperation","fillStyle","fillRect"],"sources":["../src/webVoiceUtils.ts"],"mappings":"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","ignoreList":[]}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@gnani.ai/web-voice-hook",
3
+ "version": "0.0.3",
4
+ "description": "React hook for real-time bidirectional WebSocket voice (STT/TTS)",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc && node scripts/minify.mjs",
18
+ "typecheck": "tsc --noEmit",
19
+ "prepublishOnly": "npm run build",
20
+ "release:patch": "pnpm build && git add . && git commit -m \"build: v$npm_package_version\" || true && pnpm version patch && git push && git push --tags"
21
+ },
22
+ "peerDependencies": {
23
+ "react": ">=17.0.0",
24
+ "audiomotion-analyzer": ">=4.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "terser": "^5.36.0",
28
+ "typescript": "5.5.3",
29
+ "@types/react": "^18.2.0",
30
+ "react": "^18.2.0",
31
+ "audiomotion-analyzer": "^4.2.0"
32
+ },
33
+ "keywords": [
34
+ "react",
35
+ "hook",
36
+ "websocket",
37
+ "voice",
38
+ "stt",
39
+ "tts",
40
+ "audio"
41
+ ],
42
+ "license": "MIT",
43
+ "publishConfig": {
44
+ "access": "public"
45
+ }
46
+ }