> ## Documentation Index
> Fetch the complete documentation index at: https://docs.avaturn.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Methods

> Methods exposed by the AvaturnHead instance.

## Lifecycle

### `init()`

Initializes the session and connects to the avatar room. Returns a Promise that resolves when the avatar's video track is ready, or rejects on failure. If `immediatelyJoin` is `true` (default), `init()` calls [`join()`](#join) automatically.

```javascript theme={null}
try {
  await avatar.init();
} catch (e) {
  console.error("Avatar init failed:", e);
}
```

### `join()`

Connects to the avatar room. Called automatically by `init()` unless `immediatelyJoin: false`. Use this when you want manual control over the moment of connection.

<ParamField path="opts.startAudioOff" type="boolean">
  Start with microphone muted. Defaults to the SDK config's `startAudioOff`.
</ParamField>

```javascript theme={null}
const root = document.querySelector<HTMLDivElement>("#avaturn-video")!;
const avatar = new AvaturnHead(root, { sessionToken, immediatelyJoin: false });
await avatar.init();
// ...user interaction...
await avatar.join({ startAudioOff: false });
```

### `dispose()`

Terminates local SDK state — destroys the Daily call object and aborts pending requests. Does **not** close the backend session directly; the backend session ends via `user_absent_timeout` (default 60s) or an explicit [`DELETE /api/v1/sessions/{id}`](/api-reference/terminate-session). Call this on unmount.

```javascript theme={null}
await avatar.dispose();
```

### `attachDOMNode(node)`

Moves the avatar video into a different DOM element without re-initializing. Also use this when you constructed `AvaturnHead` without a DOM element and now want to render it. Takes effect after `init()` has resolved.

<ParamField path="node" type="HTMLElement" required>
  New container for the avatar video.
</ParamField>

```javascript theme={null}
avatar.attachDOMNode(document.getElementById("avatar-container")!);
```

## Events

### `on(event, callback)` / `off(event, callback)`

Subscribe to or unsubscribe from SDK events. See [Events](/web-sdk/reference/events) for the full list.

<ParamField path="event" type="string" required>
  Event name.
</ParamField>

<ParamField path="callback" type="function" required>
  Handler invoked when the event fires.
</ParamField>

```javascript theme={null}
function onInit() { console.log("avatar ready"); }

avatar.on("init", onInit);
avatar.off("init", onInit);
```

## Media devices

### `requestMediaDevices()`

Returns the list of available media devices (microphones, speakers, cameras).

```javascript theme={null}
const { devices } = await avatar.requestMediaDevices();
const microphones = devices.filter(d => d.kind === "audioinput");
```

### `setInputDevices({ audioDeviceId?, videoDeviceId? })`

Selects input devices for the session. Pass only the keys you want to change — both fields are optional at runtime. Use `false` or `null` to disable a device.

<ParamField path="audioDeviceId" type="string | false | null">
  Microphone device id from `requestMediaDevices()`.
</ParamField>

<ParamField path="videoDeviceId" type="string | false | null">
  Camera device id. Most integrations leave this unset — the avatar's video comes from the server, not the user's camera.
</ParamField>

```javascript theme={null}
await avatar.setInputDevices({ audioDeviceId: "microphone-id-123" });
```

Returns [`DailyDeviceInfos`](https://docs.daily.co/reference/daily-js/instance-methods/set-input-devices-async) from the underlying transport.

### `setOutputDevice({ outputDeviceId })`

Selects the speaker for avatar audio output. Always pass `outputDeviceId`.

<ParamField path="outputDeviceId" type="string" required>
  Device id from `requestMediaDevices()`.
</ParamField>

```javascript theme={null}
await avatar.setOutputDevice({ outputDeviceId: "speaker-id-123" });
```

<Note>
  If `outputDeviceId` is omitted, the SDK silently returns the list of input devices instead of switching output. Always pass `outputDeviceId` explicitly.
</Note>

Returns [`DailyDeviceInfos`](https://docs.daily.co/reference/daily-js/instance-methods/set-input-devices-async).

### `toggleLocalAudio(value?)`

Mutes or unmutes the user's microphone. With no argument, toggles the current state.

<ParamField path="value" type="boolean">
  `true` = unmute, `false` = mute.
</ParamField>

```javascript theme={null}
avatar.toggleLocalAudio();      // toggle
avatar.toggleLocalAudio(false); // mute
```

***

## Legacy: text-echo

<Warning>
  **Legacy.** These methods belong to the [text-echo flow](/legacy/text-echo). New integrations should drive speech through a [conversation engine](/howtos/openai_realtime_api) instead.
</Warning>

### `task(text)`

Sends text for the avatar to speak. If the avatar is already speaking, the fragment is queued. Returns `{ task_id: string }`.

<ParamField path="text" type="string" required>
  The text to speak.
</ParamField>

```javascript theme={null}
const { task_id } = await avatar.task("Hello, world!");
```

### `cancelAllTasks()`

Stops the current utterance and clears the queue.

```javascript theme={null}
await avatar.cancelAllTasks();
```

### `changeVoice(config)`

Switches the text-echo TTS voice for subsequent `task()` calls. Patches the session's conversation engine config to a new `text-echo` config with the supplied TTS.

<ParamField path="config" type="TTSConfig" required>
  `{ engine: "elevenlabs", voice_id: string }`. Only `elevenlabs` is currently accepted by the backend.
</ParamField>

```javascript theme={null}
await avatar.changeVoice({ engine: "elevenlabs", voice_id: "voice_id_123" });
```
