{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "mic-selector-demo", "registryDependencies": [ "https://ui.elevenlabs.io/r/mic-selector.json", "https://ui.elevenlabs.io/r/live-waveform.json", "button", "card", "separator" ], "files": [ { "path": "examples/mic-selector-demo.tsx", "content": "\"use client\"\n\nimport { useCallback, useEffect, useRef, useState } from \"react\"\nimport { Disc, Pause, Play, Trash2 } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Card } from \"@/components/ui/card\"\nimport { LiveWaveform } from \"@/components/ui/live-waveform\"\nimport { MicSelector } from \"@/components/ui/mic-selector\"\nimport { Separator } from \"@/components/ui/separator\"\n\ntype RecordingState = \"idle\" | \"loading\" | \"recording\" | \"recorded\" | \"playing\"\n\nexport default function MicSelectorDemo() {\n const [selectedDevice, setSelectedDevice] = useState(\"\")\n const [isMuted, setIsMuted] = useState(false)\n const [state, setState] = useState(\"idle\")\n const [audioBlob, setAudioBlob] = useState(null)\n\n const mediaRecorderRef = useRef(null)\n const audioChunksRef = useRef([])\n const audioElementRef = useRef(null)\n\n const startRecording = useCallback(async () => {\n try {\n setState(\"loading\")\n\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: selectedDevice ? { deviceId: { exact: selectedDevice } } : true,\n })\n\n const mediaRecorder = new MediaRecorder(stream)\n mediaRecorderRef.current = mediaRecorder\n audioChunksRef.current = []\n\n mediaRecorder.ondataavailable = (event) => {\n if (event.data.size > 0) {\n audioChunksRef.current.push(event.data)\n }\n }\n\n mediaRecorder.onstop = () => {\n const blob = new Blob(audioChunksRef.current, { type: \"audio/webm\" })\n setAudioBlob(blob)\n stream.getTracks().forEach((track) => track.stop())\n setState(\"recorded\")\n }\n\n mediaRecorder.start()\n setState(\"recording\")\n } catch (error) {\n console.error(\"Error starting recording:\", error)\n setState(\"idle\")\n }\n }, [selectedDevice])\n\n const stopRecording = useCallback(() => {\n if (mediaRecorderRef.current && state === \"recording\") {\n mediaRecorderRef.current.stop()\n }\n }, [state])\n\n const playRecording = useCallback(() => {\n if (!audioBlob) return\n\n const audio = new Audio(URL.createObjectURL(audioBlob))\n audioElementRef.current = audio\n\n audio.onended = () => {\n setState(\"recorded\")\n }\n\n audio.play()\n setState(\"playing\")\n }, [audioBlob])\n\n const pausePlayback = useCallback(() => {\n if (audioElementRef.current) {\n audioElementRef.current.pause()\n setState(\"recorded\")\n }\n }, [])\n\n const restart = useCallback(() => {\n if (audioElementRef.current) {\n audioElementRef.current.pause()\n audioElementRef.current = null\n }\n setAudioBlob(null)\n audioChunksRef.current = []\n setState(\"idle\")\n }, [])\n\n // Stop recording when muted\n useEffect(() => {\n if (isMuted && state === \"recording\") {\n stopRecording()\n }\n }, [isMuted, state, stopRecording])\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (mediaRecorderRef.current) {\n mediaRecorderRef.current.stop()\n }\n if (audioElementRef.current) {\n audioElementRef.current.pause()\n }\n }\n }, [])\n\n const showWaveform = state === \"recording\" && !isMuted\n const showProcessing = state === \"loading\" || state === \"playing\"\n const showRecorded = state === \"recorded\"\n\n return (\n
\n \n
\n
\n \n
\n
\n \n {state === \"idle\" && (\n
\n \n Start Recording\n \n
\n )}\n {showRecorded && (\n
\n \n Ready to Play\n \n
\n )}\n
\n
\n
\n
\n
\n \n \n
\n {state === \"idle\" && (\n \n \n \n )}\n {(state === \"loading\" || state === \"recording\") && (\n \n \n \n )}\n {showRecorded && (\n \n \n \n )}\n {state === \"playing\" && (\n \n \n \n )}\n \n \n \n \n
\n
\n
\n \n \n )\n}\n", "type": "registry:example" } ], "type": "registry:example" }