MCPcopy Create free account
hub / github.com/TanStack/ai / useAudioRecorder

Function useAudioRecorder

packages/ai-react/src/use-audio-recorder.ts:59–112  ·  view source on GitHub ↗
(
  options: UseAudioRecorderOptions<(recording: AudioRecording) => unknown> = {},
)

Source from the content-addressed store, hash-verified

57 options?: UseAudioRecorderOptions<undefined>,
58): UseAudioRecorderReturn<AudioRecording>
59export function useAudioRecorder(
60 options: UseAudioRecorderOptions<(recording: AudioRecording) => unknown> = {},
61): UseAudioRecorderReturn<unknown> {
62 const [isRecording, setIsRecording] = useState(false)
63 const [recording, setRecording] = useState<unknown>(null)
64 // Read the freshest callbacks at fire time without recreating the recorder.
65 const optionsRef = useRef(options)
66 optionsRef.current = options
67
68 const recorder = useMemo(
69 () =>
70 new AudioRecorder({
71 ...(options.audio !== undefined && { audio: options.audio }),
72 ...(options.mimeType !== undefined && { mimeType: options.mimeType }),
73 onError: (err) => optionsRef.current.onError?.(err),
74 }),
75 // Recorder config (audio/mimeType) is captured once at mount, matching the
76 // other hooks' create-once pattern.
77 [],
78 )
79
80 useEffect(() => {
81 const unsubscribe = recorder.subscribe((state) => {
82 setIsRecording(state === 'recording')
83 })
84 return () => {
85 unsubscribe()
86 recorder.cancel()
87 }
88 }, [recorder])
89
90 const start = useCallback(() => recorder.start(), [recorder])
91 const stop = useCallback(async () => {
92 const recording = await recorder.stop()
93 const transformed = await optionsRef.current.onComplete?.(recording)
94 // Only `undefined` (returning nothing) falls back to the raw recording, so
95 // a transform that returns null is preserved — matching the inferred type,
96 // which excludes only undefined/void/null from the transform's return.
97 const output = transformed === undefined ? recording : transformed
98 setRecording(() => output)
99 return output
100 }, [recorder])
101 const cancel = useCallback(() => recorder.cancel(), [recorder])
102
103 return {
104 recording,
105 isRecording,
106 // recording is client-only; if SSR'd, gate UI on a mounted flag.
107 isSupported: AudioRecorder.isSupported(),
108 start,
109 stop,
110 cancel,
111 }
112}

Callers 2

ChatPageFunction · 0.90

Calls 6

unsubscribeFunction · 0.85
isSupportedMethod · 0.80
subscribeMethod · 0.65
cancelMethod · 0.65
startMethod · 0.65
stopMethod · 0.45

Tested by

no test coverage detected