# Voice and Text Chat

The SDK includes a voice and text chat system built on LiveKit, separate from the video stream. This enables real-time communication between users viewing the same stream or application.

## Video Tutorial

{% embed url="<https://youtube.com/watch?v=DpMA9a9KjuA>" %}
Built-in Voice and Text Chat for Pixel Streaming
{% endembed %}

## Import

```javascript
import { StreamPixelVoiceChat } from 'streampixelsdk';
```

## Creating a Chat Instance

```javascript
const voiceChat = new StreamPixelVoiceChat(
  'my-room',       // Room name — users in the same room can communicate
  'John',          // Display name for this user
  true,            // Enable voice chat (true) or text-only (false)
  'https://example.com/avatar.png',  // Avatar URL
  true             // Start with microphone enabled
);
```

### Constructor Parameters

| Parameter   | Type      | Description                                                                     |
| ----------- | --------- | ------------------------------------------------------------------------------- |
| `roomName`  | `string`  | Room identifier. Users in the same room can communicate.                        |
| `userName`  | `string`  | Display name for this user                                                      |
| `voiceChat` | `boolean` | `true` to enable voice chat, `false` for text-only                              |
| `avatar`    | `string`  | URL to the user's avatar image                                                  |
| `micStart`  | `boolean` | `true` to start with microphone enabled (only applies if `voiceChat` is `true`) |

## Joining and Leaving

```javascript
// Join the room
await voiceChat.join();

// Leave the room
await voiceChat.leave();
```

`join()` automatically:

* Fetches an access token from the Streampixel API
* Connects to the LiveKit server
* Subscribes to other participants' audio tracks
* Enables the microphone if `micStart` is `true`

## Voice Controls

```javascript
// Toggle microphone on/off
await voiceChat.toggleMic();
```

### Muting Other Participants

```javascript
// Mute all remote participants (local only — does not affect their actual mic)
await voiceChat.muteAllRemote();

// Unmute all remote participants
await voiceChat.unmuteAllRemote();

// Mute a specific participant by their identity
await voiceChat.muteSelected('user123');

// Unmute a specific participant
await voiceChat.unmuteSelected('user123');
```

{% hint style="warning" %}
Muting is local only — it controls whether **you** hear the participant, not whether they are actually transmitting. The muted participant's microphone remains active for other users in the room.
{% endhint %}

## Text Chat

```javascript
// Send a text message to the room
voiceChat.sendMessage('Hello everyone!');
```

### Receiving Messages

```javascript
voiceChat.onMessage((msg) => {
  console.log(`${msg.from}: ${msg.text}`);
  console.log(`Avatar: ${msg.avatar}`);
});
```

| Property     | Type     | Description                                       |
| ------------ | -------- | ------------------------------------------------- |
| `msg.from`   | `string` | Sender's identity (`"You"` for your own messages) |
| `msg.text`   | `string` | Message content                                   |
| `msg.avatar` | `string` | Sender's avatar URL                               |

## Participant Updates

Track who's in the room and who's speaking:

```javascript
voiceChat.onParticipantUpdate((data) => {
  // Local participant (you)
  console.log('You:', data.localParticipant.id, data.localParticipant.speaking);

  // Remote participants
  data.remoteParticipants.forEach((p) => {
    console.log(`${p.id}: speaking=${p.speaking}, avatar=${p.avatar}`);
  });
});
```

### Participant Data Shape

```javascript
{
  localParticipant: {
    id: 'your-username',
    avatar: 'https://example.com/avatar.png',
    speaking: true   // true if currently speaking
  },
  remoteParticipants: [
    {
      id: 'other-user',
      avatar: 'https://example.com/other-avatar.png',
      speaking: false
    }
  ]
}
```

{% hint style="info" %}
The `speaking` boolean updates in real-time and can be used to drive speaking indicators in your UI, such as highlighting the active speaker or showing a microphone animation.
{% endhint %}

## Full Example

{% code lineNumbers="true" %}

```javascript
import { StreamPixelVoiceChat } from 'streampixelsdk';

const chat = new StreamPixelVoiceChat('room-1', 'Alice', true, '/avatar.png', true);

// Join the room
await chat.join();

// Listen for messages
chat.onMessage((msg) => {
  appendToChat(`${msg.from}: ${msg.text}`);
});

// Track participants
chat.onParticipantUpdate((data) => {
  updateParticipantList(data.remoteParticipants);
});

// Send a message
document.getElementById('send-btn').addEventListener('click', () => {
  const text = document.getElementById('chat-input').value;
  chat.sendMessage(text);
});

// Toggle mic
document.getElementById('mic-btn').addEventListener('click', () => {
  chat.toggleMic();
});
```

{% endcode %}
