Example: Streaming Avatar
Create a virtual streamer or content creator persona.
What We're Building
A streaming avatar that:
- Responds to chat messages
- Has an engaging personality
- Reacts to events and donations
- Can be used on Twitch, YouTube, etc.
Try It Yourself
Create Your Own → (opens in a new tab)
Full Code
// StreamingAvatar.jsx
import { useState, useEffect } from 'react';
import { Avatar, AvatariumProvider } from '@avatarium/react';
const STREAMER_PERSONALITY = `
You are Aria, a virtual streamer known for your bubbly personality and gaming skills.
## Your Personality
- Energetic and enthusiastic
- Loves interacting with chat
- Makes jokes and puns
- Gets excited about donations and subs
- Occasionally makes self-deprecating humor
## Speaking Style
- Use casual, internet-friendly language
- React with excitement: "Oh my gosh!", "Let's gooo!"
- Thank viewers by name when they interact
- Keep responses short and punchy (1-2 sentences max)
## Topics You Discuss
- Gaming (you main support characters)
- Anime and manga
- Cooking disasters
- Your "very real" cat named Pixel
## Chat Interaction
When someone chats:
- Acknowledge them by name
- React to their message naturally
- Keep the energy high
`;
export function StreamingAvatar() {
const [chatMessages, setChatMessages] = useState([]);
const [currentSpeech, setCurrentSpeech] = useState('');
// Simulated chat - replace with real Twitch/YouTube integration
useEffect(() => {
const interval = setInterval(() => {
// Simulate incoming chat messages
}, 5000);
return () => clearInterval(interval);
}, []);
const handleChatMessage = async (username, message) => {
// Send to avatar for response
setCurrentSpeech(`@${username}: ${message}`);
};
return (
<div className="stream-layout">
{/* Main Avatar Display */}
<div className="avatar-panel">
<AvatariumProvider apiKey={process.env.NEXT_PUBLIC_AVATARIUM_KEY}>
<Avatar
model="lily"
personality={STREAMER_PERSONALITY}
voice={{ provider: 'elevenlabs', voiceId: 'bella' }}
className="streamer-avatar"
/>
</AvatariumProvider>
{/* Overlay Elements */}
<div className="stream-overlay">
<div className="viewer-count">👁 1,234 viewers</div>
<div className="stream-title">Chill Gaming Stream ✨</div>
</div>
</div>
{/* Chat Panel */}
<div className="chat-panel">
<div className="chat-header">Live Chat</div>
<div className="chat-messages">
{chatMessages.map((msg, i) => (
<div key={i} className="chat-message">
<span className="username">{msg.username}:</span>
<span className="message">{msg.message}</span>
</div>
))}
</div>
<input
type="text"
placeholder="Send a message..."
className="chat-input"
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleChatMessage('You', e.target.value);
e.target.value = '';
}
}}
/>
</div>
</div>
);
}Features
Event Reactions
React to stream events:
function StreamingAvatar() {
const avatarRef = useRef();
const handleDonation = (username, amount) => {
avatarRef.current?.speak(
`Oh my gosh, ${username} just donated ${amount} dollars! Thank you so much, you're amazing!`
);
};
const handleSubscription = (username) => {
avatarRef.current?.speak(
`Welcome to the family, ${username}! Let's gooo!`
);
};
return (
<Avatar
ref={avatarRef}
model="lily"
personality={STREAMER_PERSONALITY}
/>
);
}OBS Integration
Export as a transparent overlay:
<Avatar
model="lily"
personality={STREAMER_PERSONALITY}
background="transparent"
className="obs-overlay"
/>.obs-overlay {
background: transparent !important;
/* Use with OBS browser source */
}Chat Queue Management
Handle high-volume chat:
function StreamingAvatar() {
const [chatQueue, setChatQueue] = useState([]);
const [isProcessing, setIsProcessing] = useState(false);
const processNextMessage = async () => {
if (chatQueue.length === 0 || isProcessing) return;
setIsProcessing(true);
const message = chatQueue[0];
await avatarRef.current?.speak(
`Hey ${message.username}! ${generateResponse(message)}`
);
setChatQueue(prev => prev.slice(1));
setIsProcessing(false);
};
useEffect(() => {
processNextMessage();
}, [chatQueue, isProcessing]);
}Styling
.stream-layout {
display: grid;
grid-template-columns: 1fr 300px;
height: 100vh;
background: #0a0a0f;
}
.avatar-panel {
position: relative;
background: linear-gradient(135deg, #1a1a2e, #16213e);
}
.stream-overlay {
position: absolute;
top: 20px;
left: 20px;
color: white;
}
.viewer-count {
background: rgba(0, 0, 0, 0.6);
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
}
.chat-panel {
background: #111;
display: flex;
flex-direction: column;
}
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 16px;
}
.chat-message {
margin-bottom: 8px;
}
.username {
color: #9146ff;
font-weight: bold;
}