Use voiceAssistant components (#98)

This commit is contained in:
lukasIO
2024-09-16 10:47:15 +02:00
committed by GitHub
parent 302afd8844
commit e2c3b8bf35
10 changed files with 2839 additions and 290 deletions

View File

@@ -12,28 +12,22 @@ import {
PlaygroundTabbedTile,
PlaygroundTile,
} from "@/components/playground/PlaygroundTile";
import { AgentMultibandAudioVisualizer } from "@/components/visualization/AgentMultibandAudioVisualizer";
import { useConfig } from "@/hooks/useConfig";
import { useMultibandTrackVolume } from "@/hooks/useTrackVolume";
import { TranscriptionTile } from "@/transcriptions/TranscriptionTile";
import {
TrackReferenceOrPlaceholder,
BarVisualizer,
VideoTrack,
useConnectionState,
useDataChannel,
useLocalParticipant,
useRemoteParticipants,
useRoomInfo,
useTracks,
useVoiceAssistant,
} from "@livekit/components-react";
import {
ConnectionState,
LocalParticipant,
RoomEvent,
Track,
} from "livekit-client";
import { ConnectionState, LocalParticipant, Track } from "livekit-client";
import { QRCodeSVG } from "qrcode.react";
import { ReactNode, useCallback, useEffect, useMemo, useState } from "react";
import tailwindTheme from "../../lib/tailwindTheme.preval";
export interface PlaygroundMeta {
name: string;
@@ -55,15 +49,10 @@ export default function Playground({
}: PlaygroundProps) {
const { config, setUserSettings } = useConfig();
const { name } = useRoomInfo();
const [messages, setMessages] = useState<ChatMessageType[]>([]);
const [transcripts, setTranscripts] = useState<ChatMessageType[]>([]);
const { localParticipant } = useLocalParticipant();
const participants = useRemoteParticipants({
updateOnlyOn: [RoomEvent.ParticipantMetadataChanged],
});
const agentParticipant = participants.find((p) => p.isAgent);
const isAgentConnected = agentParticipant !== undefined;
const voiceAssistant = useVoiceAssistant();
const roomState = useConnectionState();
const tracks = useTracks();
@@ -75,32 +64,12 @@ export default function Playground({
}
}, [config, localParticipant, roomState]);
let agentAudioTrack: TrackReferenceOrPlaceholder | undefined;
const aat = tracks.find(
(trackRef) =>
trackRef.publication.kind === Track.Kind.Audio &&
trackRef.participant.isAgent
);
if (aat) {
agentAudioTrack = aat;
} else if (agentParticipant) {
agentAudioTrack = {
participant: agentParticipant,
source: Track.Source.Microphone,
};
}
const agentVideoTrack = tracks.find(
(trackRef) =>
trackRef.publication.kind === Track.Kind.Video &&
trackRef.participant.isAgent
);
const subscribedVolumes = useMultibandTrackVolume(
agentAudioTrack?.publication?.track,
5
);
const localTracks = tracks.filter(
({ participant }) => participant instanceof LocalParticipant
);
@@ -111,11 +80,6 @@ export default function Playground({
({ source }) => source === Track.Source.Microphone
);
const localMultibandVolume = useMultibandTrackVolume(
localMicTrack?.publication.track,
20
);
const onDataReceived = useCallback(
(msg: any) => {
if (msg.topic === "transcription") {
@@ -181,6 +145,18 @@ export default function Playground({
);
}, [agentVideoTrack, config, roomState]);
useEffect(() => {
document.body.style.setProperty(
"--lk-theme-color",
// @ts-ignore
tailwindTheme.colors[config.settings.theme_color]["500"]
);
document.body.style.setProperty(
"--lk-drop-shadow",
`var(--lk-theme-color) 0px 0px 18px`
);
}, [config.settings.theme_color]);
const audioTileContent = useMemo(() => {
const disconnectedContent = (
<div className="flex flex-col items-center justify-center gap-2 text-gray-700 text-center w-full">
@@ -195,19 +171,15 @@ export default function Playground({
</div>
);
// TODO: keep it in the speaking state until we come up with a better protocol for agent states
const visualizerContent = (
<div className="flex items-center justify-center w-full">
<AgentMultibandAudioVisualizer
state="speaking"
barWidth={30}
minBarHeight={30}
maxBarHeight={150}
accentColor={config.settings.theme_color}
accentShade={500}
frequencies={subscribedVolumes}
borderRadius={12}
gap={16}
<div
className={`flex items-center justify-center w-full h-48 [--lk-va-bar-width:30px] [--lk-va-bar-gap:20px] [--lk-fg:var(--lk-theme-color)]`}
>
<BarVisualizer
state={voiceAssistant.state}
trackRef={voiceAssistant.audioTrack}
barCount={5}
options={{ minHeight: 20 }}
/>
</div>
);
@@ -216,29 +188,29 @@ export default function Playground({
return disconnectedContent;
}
if (!agentAudioTrack) {
if (!voiceAssistant.audioTrack) {
return waitingContent;
}
return visualizerContent;
}, [
agentAudioTrack,
voiceAssistant.audioTrack,
config.settings.theme_color,
subscribedVolumes,
roomState,
voiceAssistant.state,
]);
const chatTileContent = useMemo(() => {
if (agentAudioTrack) {
if (voiceAssistant.audioTrack) {
return (
<TranscriptionTile
agentAudioTrack={agentAudioTrack}
agentAudioTrack={voiceAssistant.audioTrack}
accentColor={config.settings.theme_color}
/>
);
}
return <></>;
}, [config.settings.theme_color, agentAudioTrack]);
}, [config.settings.theme_color, voiceAssistant.audioTrack]);
const settingsTileContent = useMemo(() => {
return (
@@ -284,7 +256,7 @@ export default function Playground({
<NameValueRow
name="Agent connected"
value={
isAgentConnected ? (
voiceAssistant.agent ? (
"TRUE"
) : roomState === ConnectionState.Connected ? (
<LoadingSVG diameter={12} strokeWidth={2} />
@@ -293,7 +265,7 @@ export default function Playground({
)
}
valueColor={
isAgentConnected
voiceAssistant.agent
? `${config.settings.theme_color}-500`
: "gray-500"
}
@@ -318,7 +290,7 @@ export default function Playground({
title="Microphone"
deviceSelectorKind="audioinput"
>
<AudioInputTile frequencies={localMultibandVolume} />
<AudioInputTile trackRef={localMicTrack} />
</ConfigurationPanelItem>
)}
<div className="w-full">
@@ -350,12 +322,11 @@ export default function Playground({
localParticipant,
name,
roomState,
isAgentConnected,
localVideoTrack,
localMicTrack,
localMultibandVolume,
themeColors,
setUserSettings,
voiceAssistant.agent,
]);
let mobileTabs: PlaygroundTab[] = [];