mirror of
https://github.com/siteboon/claudecodeui.git
synced 2025-12-17 13:29:32 +00:00
Update package dependencies, add Git API routes, and implement audio transcription functionality. Introduce new components for Git management, enhance chat interface with microphone support, and improve UI elements for better user experience.
This commit is contained in:
109
src/hooks/useAudioRecorder.js
Executable file
109
src/hooks/useAudioRecorder.js
Executable file
@@ -0,0 +1,109 @@
|
||||
import { useState, useRef, useCallback } from 'react';
|
||||
|
||||
export function useAudioRecorder() {
|
||||
const [isRecording, setRecording] = useState(false);
|
||||
const [audioBlob, setAudioBlob] = useState(null);
|
||||
const [error, setError] = useState(null);
|
||||
const mediaRecorderRef = useRef(null);
|
||||
const streamRef = useRef(null);
|
||||
const chunksRef = useRef([]);
|
||||
|
||||
const start = useCallback(async () => {
|
||||
try {
|
||||
setError(null);
|
||||
setAudioBlob(null);
|
||||
chunksRef.current = [];
|
||||
|
||||
// Request microphone access
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
audio: {
|
||||
echoCancellation: true,
|
||||
noiseSuppression: true,
|
||||
sampleRate: 16000,
|
||||
}
|
||||
});
|
||||
|
||||
streamRef.current = stream;
|
||||
|
||||
// Determine supported MIME type
|
||||
const mimeType = MediaRecorder.isTypeSupported('audio/webm')
|
||||
? 'audio/webm'
|
||||
: 'audio/mp4';
|
||||
|
||||
// Create media recorder
|
||||
const recorder = new MediaRecorder(stream, { mimeType });
|
||||
mediaRecorderRef.current = recorder;
|
||||
|
||||
// Set up event handlers
|
||||
recorder.ondataavailable = (e) => {
|
||||
if (e.data.size > 0) {
|
||||
chunksRef.current.push(e.data);
|
||||
}
|
||||
};
|
||||
|
||||
recorder.onstop = () => {
|
||||
// Create blob from chunks
|
||||
const blob = new Blob(chunksRef.current, { type: mimeType });
|
||||
setAudioBlob(blob);
|
||||
|
||||
// Clean up stream
|
||||
if (streamRef.current) {
|
||||
streamRef.current.getTracks().forEach(track => track.stop());
|
||||
streamRef.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
recorder.onerror = (event) => {
|
||||
console.error('MediaRecorder error:', event);
|
||||
setError('Recording failed');
|
||||
setRecording(false);
|
||||
};
|
||||
|
||||
// Start recording
|
||||
recorder.start();
|
||||
setRecording(true);
|
||||
console.log('Recording started');
|
||||
} catch (err) {
|
||||
console.error('Failed to start recording:', err);
|
||||
setError(err.message || 'Failed to start recording');
|
||||
setRecording(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const stop = useCallback(() => {
|
||||
console.log('Stop called, recorder state:', mediaRecorderRef.current?.state);
|
||||
|
||||
try {
|
||||
if (mediaRecorderRef.current && mediaRecorderRef.current.state === 'recording') {
|
||||
mediaRecorderRef.current.stop();
|
||||
console.log('Recording stopped');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error stopping recorder:', err);
|
||||
}
|
||||
|
||||
// Always update state
|
||||
setRecording(false);
|
||||
|
||||
// Clean up stream if still active
|
||||
if (streamRef.current) {
|
||||
streamRef.current.getTracks().forEach(track => track.stop());
|
||||
streamRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const reset = useCallback(() => {
|
||||
setAudioBlob(null);
|
||||
setError(null);
|
||||
chunksRef.current = [];
|
||||
}, []);
|
||||
|
||||
return {
|
||||
isRecording,
|
||||
audioBlob,
|
||||
error,
|
||||
start,
|
||||
stop,
|
||||
reset
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user