Skip to content

Arabic TTS integrations

Add Arabic text to speech to LiveKit voice agents, applications and assistants using the OpenAI-compatible API, hosted MCP or coding-agent skill.

Use the speech API in your application or the official skill in a coding agent. Use Hosted MCP to connect an assistant through OAuth.

Choose a starting point

GoalStarting pointAvailability
Generate speech in an applicationSpeech API quickstartUse cURL or the OpenAI SDK to call Sawtak Arabi's model; save the streamed audio yourself.
Add Arabic speech to a LiveKit agentLiveKit TTS configurationConfigure LiveKit's existing OpenAI plugin with your Sawtak Arabi voice ID.
Make a narration file with a coding agentOfficial Sawtak Arabi skillReleased skill for Claude Code, Codex and compatible skill clients.
Let an assistant submit and retrieve voiceoversHosted MCPConnect at https://sawtakarabi.ai/mcp with a remote MCP client that supports OAuth.
Create an Arabic video with an agentGitHub starter and guidePublic editable project; generate or reuse scene WAVs and render with Remotion.

The Remotion starter is maintained in the public SawtakArabi/arabic-video-starter repository. Give that URL and your brief to a coding agent; it can clone the project and follow its instructions. The public skill has its own installation instructions.

Create a narrated video

The bilingual Remotion guide starts with a prompt for your agent and links to the GitHub starter. The repository includes editable scenes, original SVG illustrations, draft scripts and dialect writing guidance. The agent generates narration through the official skill or uses available completed MCP recordings, then renders with Remotion. Node.js, Python and a rendering machine are needed to run the project. The guide also walks through importing accepted WAVs and replacing one scene while preserving the other recordings. Confirm stream completion and review recordings before importing them; keep private operation receipts out of Git and shared source.

LiveKit TTS configuration

Use the maintained LiveKit OpenAI TTS plugin with Sawtak Arabi's endpoint and a voice ID. You need a Sawtak Arabi API key and an existing LiveKit agent. Keep the key on your server.

The TTS helper was tested on October 11, 2026 with Python 3.12, LiveKit Agents and its OpenAI plugin 1.8.6, and OpenAI SDK 2.54.0. These are the tested versions, not a claim about compatibility with every later release:

pip install "livekit-agents==1.8.6" "livekit-plugins-openai==1.8.6" "openai==2.54.0"

Save this as livekit_tts.py. It uses the plugin unchanged:

from collections.abc import AsyncIterator
from contextlib import asynccontextmanager

from livekit.plugins import openai
from openai import AsyncOpenAI, DefaultAsyncHttpxClient


@asynccontextmanager
async def sawtak_tts(*, api_key: str, base_url: str, voice: str) -> AsyncIterator[openai.TTS]:
    # The caller owns an injected SDK client, so close it after the plugin/session.
    async with AsyncOpenAI(
        api_key=api_key, base_url=base_url, max_retries=0, timeout=30.0,
        default_headers={"User-Agent": "Sawtak-LiveKit-Example/1.0"},
        http_client=DefaultAsyncHttpxClient(follow_redirects=False),
    ) as client:
        async with openai.TTS(client=client, model="arabic-tts-1", voice=voice,
                             response_format="pcm") as tts:
            yield tts

Configure your existing session inside the helper's context. Supply key from SAWTAK_API_KEY, set base_url to https://api.sawtakarabi.ai/v1, and use a voice ID accessible to your account:

from livekit.agents import AgentSession, APIConnectOptions
from livekit.agents.voice.agent_session import SessionConnectOptions
from livekit_tts import sawtak_tts

async with sawtak_tts(api_key=key, base_url=base_url, voice=voice_id) as tts:
    session = AgentSession(
        # Keep your existing VAD, turn handling and transport settings.
        stt=your_stt,
        llm=your_llm,
        tts=tts,
        conn_options=SessionConnectOptions(
            tts_conn_options=APIConnectOptions(max_retry=0),
        ),
    )
    try:
        await session.start(agent=your_agent, room=your_room)
        # Keep this context open for your normal job/room lifetime.
        await your_shutdown_event.wait()
    finally:
        await session.aclose()

This is the TTS portion of an existing agent, not a standalone calling application. Keep your own STT, LLM, room and shutdown handling. The plugin receives 24 kHz mono PCM. LiveKit handles text segmentation and playback; Sawtak Arabi receives a complete text input for each speech request and streams the audio response.

Disable retries at both the SDK and session layers, as shown. A request that delivers audio can be charged even if the caller interrupts; see interruptions and billing. For a standalone synthesis call, also pass APIConnectOptions(max_retry=0) to the plugin's synthesize method.

Validation scope: the TTS helper passed actual SDK/framework tests with synthetic audio, including custom voice IDs, streamed frames, upstream cancellation and no automatic retry after refusal. The session lifecycle above is an integration sketch; a complete spoken conversation and audible interruption in a hosted LiveKit room have not yet been verified. Evaluate those in your application before a customer rollout.

Preview examples for invited testers

n8n, Shotstack, Pipecat and Twilio examples are previews available to invited testers. Contact us for access and the setup supported by each example. MCP tools generate and retrieve recordings; they do not change an assistant's conversational speech provider.

Preserve audio across retries

For API speech, capture the stream and keep X-Request-Id. Operation inspection reports status and billing; it does not retrieve audio. Finalize a WAV only after completion checks.

In the Hosted MCP, recording capture is best effort. A completed, charged request may have no saved audio. When a recording is available, download it into the project and retain its recording ID. Signed links expire; retrieve the same recording again to renew a link before a renderer needs to fetch it. Treat the URL as a private sharing link, and never send your Sawtak API key to the renderer.

A renderer failure is not a reason to generate narration again. Reuse the accepted WAV and render ID, inspect their status, and ask before starting another paid take. See Agent recipes and Generation records for recovery and retention details.