> For the complete documentation index, see [llms.txt](https://docs.ojin.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ojin.ai/guides/troubleshooting.md).

# Troubleshooting

> Common symptoms when building real-time avatars, with their cause and fix.

{% hint style="info" %}
**🟢 SDK-handled** — the [Python SDK](/models/build-with-python-sdk.md) and [Pipecat](/models/introduction/integrations.md) take care of this for you; it surfaces only on the raw WebSocket API (or if you turn a feature off). The simplest fix is usually "use the SDK."

**🟠 Your setup** — you own this regardless of integration: deployment, network, credentials, capacity, or raw-API tuning.
{% endhint %}

## Avatar's mouth barely moves / only idle animation

🟢 **SDK-handled**

**Cause:** the model is **starving**. You're sending too little audio, or forwarding tiny TTS fragments one at a time, so the model can't sustain speech at 25 fps and emits idle frames in between.

**Fix:** feed audio with a lead — **prime \~1 s, then send the largest chunks you can (\~400 ms)**. See [Optimizing Performance → Feed audio](/guides/optimizing-performance.md#feed-audio-for-stable-low-latency-lip-sync). `OjinSTVClient` already does this for you, so the simplest fix is to drive the model through the [Python SDK](/models/build-with-python-sdk.md) or [Pipecat](/models/introduction/integrations.md).

## Lip-sync drifts out of sync with the audio

🟢 **SDK-handled**

**Cause:** on the SDK path, you're adding your own A/V re-sync on top of an already-synced stream; or on the raw API, video is played off the audio clock or frames were reordered during async decode.

**Fix:** with the SDK or Pipecat, `output_stream()` is already aligned at 25 fps — **don't re-sync it yourself**. Present each frame as it arrives, or pass each frame's `pts` to your media transport (e.g. WebRTC) and let it handle sync. If you build your own loop on the raw API, drive playback from the audio clock and keep decode order stable — see [Audio and Video Synchronization](/models/introduction/api.md#audio-and-video-synchronization) in the API Reference.

## Choppy or crackling playback

🟢 **SDK-handled**

**Cause:** audio isn't playing at a steady rate, or the event loop is blocked.

**Fix:** play audio gaplessly at a steady rate; never stop it just because a video frame is late. Keep your frame handlers light — heavy synchronous work stalls the playback tick. See [Optimizing Performance → Play back at realtime](/guides/optimizing-performance.md#play-back-at-realtime).

## No video frames at all

🟢 **SDK-handled**

**Cause:** you haven't received `SESSION_READY` / `SessionReady` yet, or (SDK) you're reading `frame.rgb` while using a `PassthroughDecoder`.

**Fix:** wait for the session-ready signal before sending audio. With the SDK, the default decoder populates `frame.rgb`; a `PassthroughDecoder` leaves `rgb` as `None` and delivers the raw JPEG in `source_bytes` instead — read that, or keep the default decoder. See [Optimizing Performance → Relay frames](/guides/optimizing-performance.md#relay-frames-without-re-encoding).

## Growing latency over time

🟢 **SDK-handled** · 🟠 **Your setup** (deployment)

**Cause:** your buffer is too large, or frames backed up after a network stall. The model delivers at realtime 25 fps, so the buffer shouldn't grow on its own — keep only a small jitter buffer.

**Fix:** keep the buffer small (a few frames). If frames do back up on a poor connection, trim idle frames (`frame_type == 0`) to recover; never drop speech, start-of-speech, or fade-out frames. The SDK keeps the buffer small for you. Run the client on a backend in **US East** over a stable connection — see [Optimizing Performance → Where to run](/guides/optimizing-performance.md#where-to-run).

## Frame lag during speech (raw API)

🟠 **Your setup** (raw-API tuning)

**Cause:** the model's smoothing filter is adding responsiveness lag on the raw WebSocket protocol.

**Fix:** reduce the `speech_filter_amount` parameter — lower is more responsive but less smooth. (The SDK paces output for you, so this only applies when driving the raw API.)

## "No backend servers available"

🟠 **Your setup**

**Cause:** inference capacity is momentarily exhausted.

**Fix:** retry shortly with backoff. On the SDK this surfaces as an `ERROR` event with code `NO_BACKEND_SERVER_AVAILABLE`; on the raw API as an `ErrorResponse` (or plain-text message) with `BACKEND_UNAVAILABLE`.

## Connection or authentication fails

🟠 **Your setup**

**Fix:**

* ✓ Verify your API key and `config_id`, and that the config exists in your [dashboard](https://ojin.ai/dashboard)
* ✓ The `Authorization` header must use the **raw API key** (no `Bearer` prefix)
* ✓ Ensure your network allows WebSocket connections on port 443

## Interruptions look abrupt, or the avatar keeps speaking after a barge-in

🟢 **SDK-handled**

**Cause:** frames already sent or buffered keep playing after you cancel.

**Fix:** the SDK's `interrupt()` fades audio and cancels server-side for you. On the raw API, pick an interruption strategy for your latency/smoothness trade-off — clear the buffer for an instant cut, or keep playing video while stopping audio for a smoother look. See [Interruption Handling](/models/introduction/api.md#interruption-handling) in the API Reference.

***

Still stuck? [Contact support](/getting-started/support.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ojin.ai/guides/troubleshooting.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
