67 lines
1.8 KiB
TypeScript
67 lines
1.8 KiB
TypeScript
'use client';
|
|
|
|
import { useRef, useState } from 'react';
|
|
import type { RecordButtonProps } from '@/types/component-props';
|
|
|
|
export default function RecordButton({
|
|
isRecording,
|
|
isTranscribing = false,
|
|
onStartRecording,
|
|
onStopRecording,
|
|
}: RecordButtonProps) {
|
|
const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);
|
|
const [audioChunks, setAudioChunks] = useState<Blob[]>([]);
|
|
|
|
const handleClick = async () => {
|
|
if (isRecording) {
|
|
// Stop recording
|
|
if (mediaRecorder) {
|
|
mediaRecorder.stop();
|
|
}
|
|
} else {
|
|
// Start recording
|
|
try {
|
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
const recorder = new MediaRecorder(stream);
|
|
const chunks: Blob[] = [];
|
|
|
|
recorder.ondataavailable = (e) => {
|
|
chunks.push(e.data);
|
|
};
|
|
|
|
recorder.onstop = () => {
|
|
const audioBlob = new Blob(chunks, { type: 'audio/webm' });
|
|
onStopRecording?.(audioBlob);
|
|
stream.getTracks().forEach(track => track.stop());
|
|
};
|
|
|
|
recorder.start();
|
|
setMediaRecorder(recorder);
|
|
setAudioChunks([]);
|
|
onStartRecording?.();
|
|
} catch (error) {
|
|
console.error('Failed to start recording:', error);
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<button
|
|
onClick={handleClick}
|
|
disabled={isTranscribing}
|
|
className={`
|
|
w-20 h-20 rounded-full flex items-center justify-center text-3xl
|
|
transition-all duration-200 shadow-lg
|
|
${isRecording
|
|
? 'bg-red-500 hover:bg-red-600 animate-pulse'
|
|
: 'bg-blue-500 hover:bg-blue-600'
|
|
}
|
|
${isTranscribing ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
text-white
|
|
`}
|
|
>
|
|
{isTranscribing ? '⏳' : isRecording ? '⏹️' : '🎙️'}
|
|
</button>
|
|
);
|
|
}
|