@@ -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 }
@@ -447,6 +454,114 @@ export const COMPONENTS = {
447454 ) ;
448455 } ,
449456
457+ // Audio bar visualizer
458+ AudioRadialVisualizer : ( ) => {
459+ const barCounts = [ '0' , '4' , '8' , '12' , '16' , '24' ] ;
460+ const sizes = [ 'icon' , 'sm' , 'md' , 'lg' , 'xl' ] ;
461+ const states = [
462+ 'disconnected' ,
463+ 'connecting' ,
464+ 'initializing' ,
465+ 'listening' ,
466+ 'thinking' ,
467+ 'speaking' ,
468+ ] as AgentState [ ] ;
469+
470+ const { microphoneTrack, localParticipant } = useLocalParticipant ( ) ;
471+ const [ barCount , setBarCount ] = useState < string > ( barCounts [ 0 ] ) ;
472+ const [ size , setSize ] = useState < audioRadialVisualizerVariantsSizeType > (
473+ 'md' as audioRadialVisualizerVariantsSizeType
474+ ) ;
475+ const [ state , setState ] = useState < AgentState > ( states [ 0 ] ) ;
476+
477+ const micTrackRef = useMemo < TrackReferenceOrPlaceholder | undefined > ( ( ) => {
478+ return state === 'speaking'
479+ ? ( {
480+ participant : localParticipant ,
481+ source : Track . Source . Microphone ,
482+ publication : microphoneTrack ,
483+ } as TrackReference )
484+ : undefined ;
485+ } , [ state , localParticipant , microphoneTrack ] ) ;
486+
487+ useMicrophone ( ) ;
488+
489+ return (
490+ < Container componentName = "AudioVisualizer" >
491+ < div className = "flex items-center gap-2" >
492+ < div className = "flex-1" >
493+ < label className = "font-mono text-xs uppercase" htmlFor = "state" >
494+ State
495+ </ label >
496+ < Select value = { state } onValueChange = { ( value ) => setState ( value as AgentState ) } >
497+ < SelectTrigger id = "state" className = "w-full" >
498+ < SelectValue placeholder = "Select a state" />
499+ </ SelectTrigger >
500+ < SelectContent >
501+ { states . map ( ( state ) => (
502+ < SelectItem key = { state } value = { state } >
503+ { state }
504+ </ SelectItem >
505+ ) ) }
506+ </ SelectContent >
507+ </ Select >
508+ </ div >
509+
510+ < div className = "flex-1" >
511+ < label className = "font-mono text-xs uppercase" htmlFor = "size" >
512+ Size
513+ </ label >
514+ < Select
515+ value = { size as string }
516+ onValueChange = { ( value ) => setSize ( value as audioRadialVisualizerVariantsSizeType ) }
517+ >
518+ < SelectTrigger id = "size" className = "w-full" >
519+ < SelectValue placeholder = "Select a size" />
520+ </ SelectTrigger >
521+ < SelectContent >
522+ { sizes . map ( ( size ) => (
523+ < SelectItem key = { size } value = { size as string } >
524+ { size . toUpperCase ( ) }
525+ </ SelectItem >
526+ ) ) }
527+ </ SelectContent >
528+ </ Select >
529+ </ div >
530+
531+ < div className = "flex-1" >
532+ < label className = "font-mono text-xs uppercase" htmlFor = "barCount" >
533+ Bar count
534+ </ label >
535+ < Select value = { barCount . toString ( ) } onValueChange = { ( value ) => setBarCount ( value ) } >
536+ < SelectTrigger id = "barCount" className = "w-full" >
537+ < SelectValue placeholder = "Select a bar count" />
538+ </ SelectTrigger >
539+ < SelectContent >
540+ { barCounts . map ( ( barCount ) => (
541+ < SelectItem key = { barCount } value = { barCount . toString ( ) } >
542+ { parseInt ( barCount ) || 'Default' }
543+ </ SelectItem >
544+ ) ) }
545+ </ SelectContent >
546+ </ Select >
547+ </ div >
548+ </ div >
549+
550+ < div className = "relative flex flex-col justify-center gap-4" >
551+ < div className = "grid place-items-center py-20" >
552+ < AudioRadialVisualizer
553+ size = { size as audioBarVisualizerVariantsSizeType }
554+ state = { state }
555+ audioTrack = { micTrackRef ! }
556+ barCount = { parseInt ( barCount ) || undefined }
557+ className = "mx-auto"
558+ />
559+ </ div >
560+ </ div >
561+ </ Container >
562+ ) ;
563+ } ,
564+
450565 // Agent control bar
451566 AgentControlBar : ( ) => {
452567 useMicrophone ( ) ;
0 commit comments