@@ -27,6 +27,10 @@ import {
2727 type GridOptions ,
2828} from '@/components/livekit/audio-visualizer/audio-grid-visualizer/audio-grid-visualizer' ;
2929import { gridVariants } from '@/components/livekit/audio-visualizer/audio-grid-visualizer/demos' ;
30+ import {
31+ AudioRadialVisualizer ,
32+ audioRadialVisualizerVariants ,
33+ } from '@/components/livekit/audio-visualizer/audio-radial-visualizer/audio-radial-visualizer' ;
3034import { Button , buttonVariants } from '@/components/livekit/button' ;
3135import { ChatEntry } from '@/components/livekit/chat-entry' ;
3236import {
@@ -45,6 +49,9 @@ type buttonVariantsType = VariantProps<typeof buttonVariants>['variant'];
4549type buttonVariantsSizeType = VariantProps < typeof buttonVariants > [ 'size' ] ;
4650type alertVariantsType = VariantProps < typeof alertVariants > [ 'variant' ] ;
4751type audioBarVisualizerVariantsSizeType = VariantProps < typeof audioBarVisualizerVariants > [ 'size' ] ;
52+ type audioRadialVisualizerVariantsSizeType = VariantProps <
53+ typeof audioRadialVisualizerVariants
54+ > [ 'size' ] ;
4855
4956export function useMicrophone ( ) {
5057 const { startSession } = useSession ( ) ;
@@ -199,7 +206,7 @@ export const COMPONENTS = {
199206 // Audio bar visualizer
200207 AudioBarVisualizer : ( ) => {
201208 const barCounts = [ '0' , '3' , '5' , '7' , '9' ] ;
202- const sizes = [ 'icon' , 'xs' , ' sm', 'md' , 'lg' , 'xl' ] ;
209+ const sizes = [ 'icon' , 'sm' , 'md' , 'lg' , 'xl' ] ;
203210 const states = [
204211 'disconnected' ,
205212 'connecting' ,
@@ -212,7 +219,7 @@ export const COMPONENTS = {
212219 const { microphoneTrack, localParticipant } = useLocalParticipant ( ) ;
213220 const [ barCount , setBarCount ] = useState < string > ( barCounts [ 0 ] ) ;
214221 const [ size , setSize ] = useState < audioBarVisualizerVariantsSizeType > (
215- sizes [ 3 ] as audioBarVisualizerVariantsSizeType
222+ 'md' as audioBarVisualizerVariantsSizeType
216223 ) ;
217224 const [ state , setState ] = useState < AgentState > ( states [ 0 ] ) ;
218225
@@ -263,7 +270,7 @@ export const COMPONENTS = {
263270 < SelectContent >
264271 { sizes . map ( ( size ) => (
265272 < SelectItem key = { size } value = { size as string } >
266- { size }
273+ { size . toUpperCase ( ) }
267274 </ SelectItem >
268275 ) ) }
269276 </ SelectContent >
@@ -290,7 +297,7 @@ export const COMPONENTS = {
290297 </ div >
291298
292299 < div className = "relative flex flex-col justify-center gap-4" >
293- < div className = "grid h-40 place-items-center" >
300+ < div className = "grid place-items-center py-8 " >
294301 < AudioBarVisualizer
295302 size = { size as audioBarVisualizerVariantsSizeType }
296303 state = { state }
@@ -300,7 +307,7 @@ export const COMPONENTS = {
300307 />
301308 </ div >
302309 < div className = "text-center" > Original BarVisualizer</ div >
303- < div className = "border-border grid h-40 place-items-center space-y-4 rounded-xl border p-4" >
310+ < div className = "border-border grid place-items-center rounded-xl border p-4 py-8 " >
304311 < BarVisualizer
305312 size = { size as audioBarVisualizerVariantsSizeType }
306313 state = { state }
@@ -422,6 +429,114 @@ export const COMPONENTS = {
422429 ) ;
423430 } ,
424431
432+ // Audio bar visualizer
433+ AudioRadialVisualizer : ( ) => {
434+ const barCounts = [ '0' , '4' , '8' , '12' , '16' , '24' ] ;
435+ const sizes = [ 'icon' , 'sm' , 'md' , 'lg' , 'xl' ] ;
436+ const states = [
437+ 'disconnected' ,
438+ 'connecting' ,
439+ 'initializing' ,
440+ 'listening' ,
441+ 'thinking' ,
442+ 'speaking' ,
443+ ] as AgentState [ ] ;
444+
445+ const { microphoneTrack, localParticipant } = useLocalParticipant ( ) ;
446+ const [ barCount , setBarCount ] = useState < string > ( barCounts [ 0 ] ) ;
447+ const [ size , setSize ] = useState < audioRadialVisualizerVariantsSizeType > (
448+ 'md' as audioRadialVisualizerVariantsSizeType
449+ ) ;
450+ const [ state , setState ] = useState < AgentState > ( states [ 0 ] ) ;
451+
452+ const micTrackRef = useMemo < TrackReferenceOrPlaceholder | undefined > ( ( ) => {
453+ return state === 'speaking'
454+ ? ( {
455+ participant : localParticipant ,
456+ source : Track . Source . Microphone ,
457+ publication : microphoneTrack ,
458+ } as TrackReference )
459+ : undefined ;
460+ } , [ state , localParticipant , microphoneTrack ] ) ;
461+
462+ useMicrophone ( ) ;
463+
464+ return (
465+ < Container componentName = "AudioVisualizer" >
466+ < div className = "flex items-center gap-2" >
467+ < div className = "flex-1" >
468+ < label className = "font-mono text-xs uppercase" htmlFor = "state" >
469+ State
470+ </ label >
471+ < Select value = { state } onValueChange = { ( value ) => setState ( value as AgentState ) } >
472+ < SelectTrigger id = "state" className = "w-full" >
473+ < SelectValue placeholder = "Select a state" />
474+ </ SelectTrigger >
475+ < SelectContent >
476+ { states . map ( ( state ) => (
477+ < SelectItem key = { state } value = { state } >
478+ { state }
479+ </ SelectItem >
480+ ) ) }
481+ </ SelectContent >
482+ </ Select >
483+ </ div >
484+
485+ < div className = "flex-1" >
486+ < label className = "font-mono text-xs uppercase" htmlFor = "size" >
487+ Size
488+ </ label >
489+ < Select
490+ value = { size as string }
491+ onValueChange = { ( value ) => setSize ( value as audioRadialVisualizerVariantsSizeType ) }
492+ >
493+ < SelectTrigger id = "size" className = "w-full" >
494+ < SelectValue placeholder = "Select a size" />
495+ </ SelectTrigger >
496+ < SelectContent >
497+ { sizes . map ( ( size ) => (
498+ < SelectItem key = { size } value = { size as string } >
499+ { size . toUpperCase ( ) }
500+ </ SelectItem >
501+ ) ) }
502+ </ SelectContent >
503+ </ Select >
504+ </ div >
505+
506+ < div className = "flex-1" >
507+ < label className = "font-mono text-xs uppercase" htmlFor = "barCount" >
508+ Bar count
509+ </ label >
510+ < Select value = { barCount . toString ( ) } onValueChange = { ( value ) => setBarCount ( value ) } >
511+ < SelectTrigger id = "barCount" className = "w-full" >
512+ < SelectValue placeholder = "Select a bar count" />
513+ </ SelectTrigger >
514+ < SelectContent >
515+ { barCounts . map ( ( barCount ) => (
516+ < SelectItem key = { barCount } value = { barCount . toString ( ) } >
517+ { parseInt ( barCount ) || 'Default' }
518+ </ SelectItem >
519+ ) ) }
520+ </ SelectContent >
521+ </ Select >
522+ </ div >
523+ </ div >
524+
525+ < div className = "relative flex flex-col justify-center gap-4" >
526+ < div className = "grid place-items-center py-20" >
527+ < AudioRadialVisualizer
528+ size = { size as audioBarVisualizerVariantsSizeType }
529+ state = { state }
530+ audioTrack = { micTrackRef ! }
531+ barCount = { parseInt ( barCount ) || undefined }
532+ className = "mx-auto"
533+ />
534+ </ div >
535+ </ div >
536+ </ Container >
537+ ) ;
538+ } ,
539+
425540 // Agent control bar
426541 AgentControlBar : ( ) => {
427542 useMicrophone ( ) ;
0 commit comments