Examples
Streaming Avatar

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;
}

Download Full Example → (opens in a new tab)