@@ -13,15 +13,20 @@ import { MicrophoneIcon } from '@phosphor-icons/react/dist/ssr';
1313import { useSession } from '@/components/app/session-provider' ;
1414import { AgentControlBar } from '@/components/livekit/agent-control-bar/agent-control-bar' ;
1515import { TrackControl } from '@/components/livekit/agent-control-bar/track-control' ;
16- import { TrackDeviceSelect } from '@/components/livekit/agent-control-bar/track-device-select' ;
17- import { TrackToggle } from '@/components/livekit/agent-control-bar/track-toggle' ;
16+ // import { TrackDeviceSelect } from '@/components/livekit/agent-control-bar/track-device-select';
17+ // import { TrackToggle } from '@/components/livekit/agent-control-bar/track-toggle';
1818import { Alert , AlertDescription , AlertTitle , alertVariants } from '@/components/livekit/alert' ;
1919import { AlertToast } from '@/components/livekit/alert-toast' ;
2020import { BarVisualizer } from '@/components/livekit/audio-visualizer/audio-bar-visualizer/_bar-visualizer' ;
2121import {
2222 AudioBarVisualizer ,
2323 audioBarVisualizerVariants ,
2424} from '@/components/livekit/audio-visualizer/audio-bar-visualizer/audio-bar-visualizer' ;
25+ import {
26+ AudioGridVisualizer ,
27+ type GridOptions ,
28+ } from '@/components/livekit/audio-visualizer/audio-grid-visualizer/audio-grid-visualizer' ;
29+ import { gridVariants } from '@/components/livekit/audio-visualizer/audio-grid-visualizer/demos' ;
2530import { Button , buttonVariants } from '@/components/livekit/button' ;
2631import { ChatEntry } from '@/components/livekit/chat-entry' ;
2732import {
@@ -191,8 +196,8 @@ export const COMPONENTS = {
191196 </ Container >
192197 ) ,
193198
194- // Audio visualizer
195- AudioVisualizer : ( ) => {
199+ // Audio bar visualizer
200+ AudioBarVisualizer : ( ) => {
196201 const barCounts = [ '0' , '3' , '5' , '7' , '9' ] ;
197202 const sizes = [ 'icon' , 'xs' , 'sm' , 'md' , 'lg' , 'xl' ] ;
198203 const states = [
@@ -309,6 +314,114 @@ export const COMPONENTS = {
309314 ) ;
310315 } ,
311316
317+ // Audio grid visualizer
318+ AudioGridVisualizer : ( ) => {
319+ const rowCounts = [ '0' , '3' , '5' , '7' , '9' ] ;
320+ const states = [
321+ 'disconnected' ,
322+ 'connecting' ,
323+ 'initializing' ,
324+ 'listening' ,
325+ 'thinking' ,
326+ 'speaking' ,
327+ ] as AgentState [ ] ;
328+
329+ const { microphoneTrack, localParticipant } = useLocalParticipant ( ) ;
330+ const [ rowCount , setRowCount ] = useState ( rowCounts [ 0 ] ) ;
331+ const [ state , setState ] = useState < AgentState > ( states [ 0 ] ) ;
332+ const [ demoIndex , setDemoIndex ] = useState ( 0 ) ;
333+
334+ const micTrackRef = useMemo < TrackReferenceOrPlaceholder | undefined > ( ( ) => {
335+ return state === 'speaking'
336+ ? ( {
337+ participant : localParticipant ,
338+ source : Track . Source . Microphone ,
339+ publication : microphoneTrack ,
340+ } as TrackReference )
341+ : undefined ;
342+ } , [ state , localParticipant , microphoneTrack ] ) ;
343+
344+ useMicrophone ( ) ;
345+
346+ return (
347+ < Container componentName = "AudioVisualizer" >
348+ < div className = "flex items-center gap-2" >
349+ < div className = "flex-1" >
350+ < label className = "font-mono text-xs uppercase" htmlFor = "state" >
351+ State
352+ </ label >
353+ < Select value = { state } onValueChange = { ( value ) => setState ( value as AgentState ) } >
354+ < SelectTrigger id = "state" className = "w-full" >
355+ < SelectValue placeholder = "Select a state" />
356+ </ SelectTrigger >
357+ < SelectContent >
358+ { states . map ( ( state ) => (
359+ < SelectItem key = { state } value = { state } >
360+ { state }
361+ </ SelectItem >
362+ ) ) }
363+ </ SelectContent >
364+ </ Select >
365+ </ div >
366+
367+ < div className = "flex-1" >
368+ < label className = "font-mono text-xs uppercase" htmlFor = "rowCount" >
369+ Row count
370+ </ label >
371+ < Select value = { rowCount . toString ( ) } onValueChange = { ( value ) => setRowCount ( value ) } >
372+ < SelectTrigger id = "rowCount" className = "w-full" >
373+ < SelectValue placeholder = "Select a bar count" />
374+ </ SelectTrigger >
375+ < SelectContent >
376+ { rowCounts . map ( ( rowCount ) => (
377+ < SelectItem key = { rowCount } value = { rowCount . toString ( ) } >
378+ { parseInt ( rowCount ) || 'Default' }
379+ </ SelectItem >
380+ ) ) }
381+ </ SelectContent >
382+ </ Select >
383+ </ div >
384+
385+ < div className = "flex-1" >
386+ < label className = "font-mono text-xs uppercase" htmlFor = "demoIndex" >
387+ Demo
388+ </ label >
389+ < Select
390+ value = { demoIndex . toString ( ) }
391+ onValueChange = { ( value ) => setDemoIndex ( parseInt ( value ) ) }
392+ >
393+ < SelectTrigger id = "demoIndex" className = "w-full" >
394+ < SelectValue placeholder = "Select a demo" />
395+ </ SelectTrigger >
396+ < SelectContent >
397+ { gridVariants . map ( ( _ , idx ) => (
398+ < SelectItem key = { idx } value = { idx . toString ( ) } >
399+ Demo { String ( idx + 1 ) }
400+ </ SelectItem >
401+ ) ) }
402+ </ SelectContent >
403+ </ Select >
404+ </ div >
405+ </ div >
406+
407+ < div className = "grid place-items-center py-12" >
408+ < AudioGridVisualizer
409+ key = { `${ demoIndex } -${ rowCount } ` }
410+ state = { state }
411+ audioTrack = { micTrackRef ! }
412+ columnCount = { parseInt ( rowCount ) || 5 }
413+ options = { gridVariants [ demoIndex ] as GridOptions }
414+ />
415+ </ div >
416+ < div className = "border-border bg-muted rounded-xl border p-8" >
417+ < pre className = "text-muted-foreground text-sm" >
418+ < code > { JSON . stringify ( gridVariants [ demoIndex ] , null , 2 ) } </ code >
419+ </ pre >
420+ </ div >
421+ </ Container >
422+ ) ;
423+ } ,
424+
312425 // Agent control bar
313426 AgentControlBar : ( ) => {
314427 useMicrophone ( ) ;
0 commit comments