mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-17 13:50:39 -07:00
Add audio sample components for recording, system capture, and upload
- Introduced `AudioSampleRecording`, `AudioSampleSystem`, and `AudioSampleUpload` components to handle audio recording, system audio capture, and file uploads respectively. - Implemented play/pause functionality for audio playback across all components, enhancing user interaction. - Refactored `ProfileForm` and `SampleUpload` to utilize new audio components, improving code organization and maintainability. - Added hooks for audio playback management, ensuring consistent audio handling and cleanup across the application.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import { Monitor, Square, Play, Pause, Mic } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { FormControl, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
|
||||
import { formatAudioDuration } from '@/lib/utils/audio';
|
||||
|
||||
interface AudioSampleSystemProps {
|
||||
file: File | null | undefined;
|
||||
isRecording: boolean;
|
||||
duration: number;
|
||||
onStart: () => void;
|
||||
onStop: () => void;
|
||||
onCancel: () => void;
|
||||
onTranscribe: () => void;
|
||||
onPlayPause: () => void;
|
||||
isPlaying: boolean;
|
||||
isTranscribing?: boolean;
|
||||
}
|
||||
|
||||
export function AudioSampleSystem({
|
||||
file,
|
||||
isRecording,
|
||||
duration,
|
||||
onStart,
|
||||
onStop,
|
||||
onCancel,
|
||||
onTranscribe,
|
||||
onPlayPause,
|
||||
isPlaying,
|
||||
isTranscribing = false,
|
||||
}: AudioSampleSystemProps) {
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Capture System Audio</FormLabel>
|
||||
<FormControl>
|
||||
<div className="space-y-4">
|
||||
{!isRecording && !file && (
|
||||
<div className="flex flex-col items-center justify-center gap-4 p-4 border-2 border-dashed rounded-lg min-h-[180px]">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onStart}
|
||||
size="lg"
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<Monitor className="h-5 w-5" />
|
||||
Start Capture
|
||||
</Button>
|
||||
<p className="text-sm text-muted-foreground text-center">
|
||||
Capture audio from your system. Maximum duration: 30 seconds.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isRecording && (
|
||||
<div className="flex flex-col items-center justify-center gap-4 p-4 border-2 border-destructive rounded-lg bg-destructive/5 min-h-[180px]">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-3 w-3 rounded-full bg-destructive animate-pulse" />
|
||||
<span className="text-lg font-mono font-semibold">
|
||||
{formatAudioDuration(duration)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onStop}
|
||||
variant="destructive"
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<Square className="h-4 w-4" />
|
||||
Stop Capture
|
||||
</Button>
|
||||
<p className="text-sm text-muted-foreground text-center">
|
||||
{formatAudioDuration(30 - duration)} remaining
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{file && !isRecording && (
|
||||
<div className="flex flex-col items-center justify-center gap-4 p-4 border-2 border-primary rounded-lg bg-primary/5 min-h-[180px]">
|
||||
<div className="flex items-center gap-2">
|
||||
<Monitor className="h-5 w-5 text-primary" />
|
||||
<span className="font-medium">Capture complete</span>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground text-center">
|
||||
File: {file.name}
|
||||
</p>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
onClick={onPlayPause}
|
||||
>
|
||||
{isPlaying ? <Pause className="h-4 w-4" /> : <Play className="h-4 w-4" />}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={onTranscribe}
|
||||
disabled={isTranscribing}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<Mic className="h-4 w-4" />
|
||||
{isTranscribing ? 'Transcribing...' : 'Transcribe'}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={onCancel}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
Capture Again
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user