Skip to content

Commit 07a69e9

Browse files
authored
feat: add initial agent video prototype into panel (#11)
Big issue though: I can't get the animation fade in to look decent, the problem is the video element shows up before the data stream fully starts which means regular fade in animations mostly happen while the video is black which makes them invisible
1 parent 2191da8 commit 07a69e9

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

components/embed-popup/popup-view.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import useChatAndTranscription from '@/hooks/use-chat-and-transcription';
1717
import { useDebugMode } from '@/hooks/useDebug';
1818
import type { EmbedErrorDetails } from '@/lib/types';
1919
import { cn } from '@/lib/utils';
20+
import { AvatarTile } from '../livekit/avatar-tile';
2021
import { ChatInput } from '../livekit/chat/chat-input';
2122

2223
function isAgentAvailable(agentState: AgentState) {
@@ -37,7 +38,13 @@ export const PopupView = ({
3738
}: React.ComponentProps<'div'> & SessionViewProps) => {
3839
const room = useRoomContext();
3940
const transcriptRef = useRef<HTMLDivElement>(null);
40-
const { state: agentState, audioTrack: agentAudioTrack } = useVoiceAssistant();
41+
const {
42+
state: agentState,
43+
audioTrack: agentAudioTrack,
44+
videoTrack: agentVideoTrack,
45+
} = useVoiceAssistant();
46+
const agentHasAvatar = agentVideoTrack !== undefined;
47+
4148
const {
4249
micTrackRef,
4350
// FIXME: how do I explicitly ensure only the microphone channel is used?
@@ -166,6 +173,29 @@ export const PopupView = ({
166173
</div>
167174
</div>
168175

176+
<motion.div
177+
initial={{ opacity: 0, scale: 0 }}
178+
variants={{
179+
visible: { opacity: 1, scale: 1 },
180+
hidden: { opacity: 0, scale: 0 },
181+
}}
182+
animate={agentHasAvatar ? 'visible' : 'hidden'}
183+
exit={{ opacity: 0, scale: 0 }}
184+
transition={{
185+
type: 'spring',
186+
stiffness: 675,
187+
damping: 75,
188+
mass: 1,
189+
}}
190+
className={cn('absolute inset-1 h-full overflow-hidden rounded-t-[24px] pb-8', {
191+
'pointer-events-none': !agentHasAvatar,
192+
})}
193+
>
194+
{agentVideoTrack ? (
195+
<AvatarTile videoTrack={agentVideoTrack} className="h-full object-cover" />
196+
) : null}
197+
</motion.div>
198+
169199
<div
170200
aria-label="Voice assistant controls"
171201
className="bg-bg1 border-separator1 relative mx-1 flex h-12 shrink-0 grow-0 items-center gap-1 rounded-full border px-1 drop-shadow-md"

components/livekit/avatar-tile.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { type TrackReference, VideoTrack } from '@livekit/components-react';
2+
3+
interface AgentAudioTileProps {
4+
videoTrack: TrackReference;
5+
className?: string;
6+
}
7+
8+
export const AvatarTile = ({ videoTrack, className }: AgentAudioTileProps) => {
9+
return (
10+
<VideoTrack
11+
trackRef={videoTrack}
12+
width={videoTrack?.publication.dimensions?.width ?? 0}
13+
height={videoTrack?.publication.dimensions?.height ?? 0}
14+
className={className}
15+
/>
16+
);
17+
};

0 commit comments

Comments
 (0)