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

# silk mulberry 1.6

> our multilingual text-to-speech voice for 22 indian languages.

export const VoiceSample = ({tone, label, note, description, text, src}) => {
  const TONE_PILL = {
    happy: "bg-amber-100 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300",
    excited: "bg-orange-100 text-orange-700 dark:bg-orange-500/10 dark:text-orange-300",
    sad: "bg-sky-100 text-sky-700 dark:bg-sky-500/10 dark:text-sky-300",
    whisper: "bg-indigo-100 text-indigo-700 dark:bg-indigo-500/10 dark:text-indigo-300",
    angry: "bg-red-100 text-red-700 dark:bg-red-500/10 dark:text-red-300",
    neutral: "bg-gray-100 text-gray-600 dark:bg-white/10 dark:text-gray-300"
  };
  const PLAY_EVENT = "voicesample:play";
  const fmtTime = s => {
    if (!s || !isFinite(s)) return "0:00";
    const m = Math.floor(s / 60);
    const sec = Math.floor(s % 60).toString().padStart(2, "0");
    return m + ":" + sec;
  };
  const audioRef = React.useRef(null);
  const idRef = React.useRef(null);
  if (idRef.current === null) idRef.current = Math.random();
  const [playing, setPlaying] = React.useState(false);
  const [cur, setCur] = React.useState(0);
  const [dur, setDur] = React.useState(0);
  const [copied, setCopied] = React.useState(false);
  React.useEffect(() => {
    const onOther = e => {
      if (e.detail !== idRef.current && audioRef.current) {
        audioRef.current.pause();
        setPlaying(false);
      }
    };
    window.addEventListener(PLAY_EVENT, onOther);
    return () => window.removeEventListener(PLAY_EVENT, onOther);
  }, []);
  const toggle = () => {
    const a = audioRef.current;
    if (!a) return;
    if (playing) {
      a.pause();
      setPlaying(false);
    } else {
      window.dispatchEvent(new CustomEvent(PLAY_EVENT, {
        detail: idRef.current
      }));
      a.play();
      setPlaying(true);
    }
  };
  const copyValue = description ? "description: " + description + "\ntext: " + text : text;
  const copy = () => {
    if (navigator.clipboard) navigator.clipboard.writeText(copyValue);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  };
  const seekTo = (clientX, el) => {
    const a = audioRef.current;
    if (!a || !dur) return;
    const rect = el.getBoundingClientRect();
    const ratio = Math.min(1, Math.max(0, (clientX - rect.left) / rect.width));
    a.currentTime = ratio * dur;
    setCur(a.currentTime);
  };
  const pct = dur ? cur / dur * 100 : 0;
  const pill = label ? TONE_PILL.neutral : TONE_PILL[tone] || TONE_PILL.neutral;
  const pillLabel = label || "[" + (tone || "neutral") + "]";
  const lbl = "text-gray-400 dark:text-gray-500";
  return <div className="not-prose my-3 flex flex-col gap-3 rounded-2xl border border-gray-200 bg-white p-4 dark:border-white/10 dark:bg-white/[0.03]">
      <div className="flex items-start justify-between gap-3">
        <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
          <span className={"rounded-md px-2 py-0.5 font-mono text-xs font-semibold " + pill}>
            {pillLabel}
          </span>
          {note && <span className="text-xs text-gray-500 dark:text-gray-400">{note}</span>}
        </div>
        <button type="button" onClick={copy} aria-label={copied ? "Copied" : "Copy prompt"} className="flex shrink-0 items-center gap-1 rounded-md px-2 py-1 text-xs text-gray-500 transition hover:bg-gray-100 hover:text-gray-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 dark:text-gray-400 dark:hover:bg-white/10 dark:hover:text-gray-200">
          {copied ? <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <path d="M20 6 9 17l-5-5" />
            </svg> : <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <rect x="9" y="9" width="13" height="13" rx="2" />
              <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
            </svg>}
          {copied ? "copied" : "copy"}
        </button>
      </div>

      <div className="overflow-hidden rounded-lg bg-gray-50 px-3 py-2.5 font-mono text-xs leading-relaxed break-words whitespace-pre-wrap text-gray-700 dark:bg-white/5 dark:text-gray-300">
        {description ? <>
            <span className={lbl}>description:</span> {description}
            {"\n"}
            <span className={lbl}>text:</span> {text}
          </> : text}
      </div>

      <audio ref={audioRef} src={src} preload="metadata" onLoadedMetadata={e => setDur(e.currentTarget.duration)} onTimeUpdate={e => setCur(e.currentTarget.currentTime)} onEnded={() => {
    setPlaying(false);
    setCur(0);
    if (audioRef.current) audioRef.current.currentTime = 0;
  }} />

      <div className="flex items-center gap-3">
        <button type="button" onClick={toggle} aria-label={playing ? "Pause" : "Play " + (label || tone || "voice") + " sample"} className="flex size-9 shrink-0 items-center justify-center rounded-full bg-gray-900 text-white transition hover:bg-gray-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-gray-900 focus-visible:ring-offset-2 dark:bg-white dark:text-gray-900 dark:focus-visible:ring-white dark:focus-visible:ring-offset-gray-900">
          {playing ? <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
              <rect x="6" y="5" width="4" height="14" rx="1" />
              <rect x="14" y="5" width="4" height="14" rx="1" />
            </svg> : <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
              <path d="M8 5v14l11-7z" />
            </svg>}
        </button>

        <div role="slider" aria-label="Seek" aria-valuemin={0} aria-valuemax={Math.round(dur) || 0} aria-valuenow={Math.round(cur)} tabIndex={0} onClick={e => seekTo(e.clientX, e.currentTarget)} onKeyDown={e => {
    const a = audioRef.current;
    if (!a || !dur) return;
    if (e.key === "ArrowRight") {
      a.currentTime = Math.min(dur, a.currentTime + 2);
      setCur(a.currentTime);
    } else if (e.key === "ArrowLeft") {
      a.currentTime = Math.max(0, a.currentTime - 2);
      setCur(a.currentTime);
    }
  }} className="relative h-1.5 flex-1 cursor-pointer rounded-full bg-gray-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 dark:bg-white/15">
          <div className="absolute inset-y-0 left-0 rounded-full bg-gray-900 dark:bg-white" style={{
    width: pct + "%"
  }} />
        </div>

        <span className="shrink-0 font-mono text-xs tabular-nums text-gray-500 dark:text-gray-400">
          {fmtTime(cur)} / {fmtTime(dur)}
        </span>
      </div>
    </div>;
};

**silk mulberry 1.6** is our multilingual voice. it speaks 22 indian languages,
each written in its own script, in four named voices. you steer the delivery with
a short style, accent and pace. it streams, so it's a good fit for voice agents in
any of those languages. it's available over `/v1/tts`, `/v1/tts/json`, websocket
streaming and the playground; the dashboard's hosted agents and phone calls don't
offer it yet.

<VoiceSample label="telugu" description="professional, Telugu accent, steady pace" text="నమస్కారం, మీరు ఎలా ఉన్నారు? ఈ రోజు వాతావరణం చాలా బాగుంది." src="/audio/mulberry-1-6/telugu.mp3" />

## at a glance

| field    | value                                                                         |
| -------- | ----------------------------------------------------------------------------- |
| model id | `mulberry-1.6`                                                                |
| language | 22 indian languages, each in its own script. english words can stay in latin. |
| best for | voice agents, support lines and narration in indian languages                 |
| steering | an optional `description` of style, accent and pace, plus a named `speaker`   |
| length   | up to 2000 characters, and about 80 seconds of audio, per request             |

## quickstart

one call, one `.wav` file:

```bash theme={null}
curl -X POST https://silk-api.rumik.ai/v1/tts \
  -H "Authorization: Bearer rk_live_•••••••••" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mulberry-1.6",
    "text": "வணக்கம், உங்கள் ஆர்டர் நாளை மாலைக்குள் வந்து சேரும்.",
    "description": "professional, Tamil accent, steady pace"
  }' \
  --output mulberry-1-6.wav
```

to receive `opus`, `pcm`, `mulaw`, `alaw`, or `mp3`, add `audio_format` to the
request. see [audio formats](/audio-formats) for exact values and examples.

write your text in the language's own script and put the delivery in
`description`. there's no `language` field: the text decides. the full request
schema is in the [api reference](/api-reference).

## supported languages

write each language in its own script, and don't romanise it. if your
`description` names no accent, silk picks one from the script of the text.

| language          | write it in                        | default accent                                                                          |
| ----------------- | ---------------------------------- | --------------------------------------------------------------------------------------- |
| assamese          | bengali-assamese script            | `Bengali accent`                                                                        |
| bengali           | bengali-assamese script            | `Bengali accent`                                                                        |
| bodo              | devanagari                         | `Hindi accent`                                                                          |
| dogri             | devanagari                         | `Hindi accent`                                                                          |
| english           | latin                              | `Indian English accent`                                                                 |
| gujarati          | gujarati                           | `Indian English accent`                                                                 |
| hindi             | devanagari                         | `Hindi accent`                                                                          |
| kannada           | kannada                            | `Kannada accent`                                                                        |
| kashmiri          | perso-arabic                       | `Indian English accent`                                                                 |
| konkani           | devanagari                         | `Hindi accent`                                                                          |
| maithili          | devanagari                         | `Hindi accent`                                                                          |
| malayalam         | malayalam                          | `Indian English accent`                                                                 |
| manipuri (meitei) | meetei mayek or bengali            | `Bengali accent` in bengali script, else `Indian English accent`                        |
| marathi           | devanagari                         | `Hindi accent`                                                                          |
| nepali            | devanagari                         | `Hindi accent`                                                                          |
| odia              | odia                               | `Indian English accent`                                                                 |
| punjabi           | gurmukhi                           | `Punjabi accent`                                                                        |
| sanskrit          | devanagari                         | `Hindi accent`                                                                          |
| santali           | devanagari, latin, bengali or odia | `Hindi accent` in devanagari, `Bengali accent` in bengali, else `Indian English accent` |
| tamil             | tamil                              | `Tamil accent`                                                                          |
| telugu            | telugu                             | `Telugu accent`                                                                         |
| urdu              | perso-arabic                       | `Indian English accent`                                                                 |

name an accent in `description` to pick it yourself. the full list is in the
[prompting guide](/prompting-mulberry-1-6#vocabulary).

## preset voices

pick one of four named voices with `speaker`. leave it out and you get `ira`.

| voice                       | gender |
| --------------------------- | ------ |
| `ira` `aisha` `siya` `zoya` | female |

```bash theme={null}
curl -X POST https://silk-api.rumik.ai/v1/tts \
  -H "Authorization: Bearer rk_live_•••••••••" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mulberry-1.6",
    "text": "নমস্কার, আপনি কেমন আছেন? আজকের আবহাওয়াটা খুব সুন্দর।",
    "description": "happy, Bengali accent, steady pace",
    "speaker": "aisha"
  }' \
  --output aisha.wav
```

names are case-insensitive. send a name we don't know and you get `ira`, not an
error, so a typo sounds like the wrong voice rather than failing loudly. when you
send `speaker`, `/v1/tts/json` echoes the voice it used, e.g. `"Ira"`.

<Note>
  **coming from mulberry 1.5?** its numbered preset values, `speaker_1` to
  `speaker_4`, map to `ira`, `siya`, `aisha` and `zoya`, in that order.
</Note>

## parameters

| field                | default             | notes                                                                                                                                                                                          |
| -------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text`               | n/a                 | required. up to 2000 characters, and about 80 seconds of speech. `<laugh>`, `<chuckle>` and `<sigh>` are performed where you place them; any other `<tag>` marker is removed before synthesis. |
| `description`        | n/a                 | optional. `style, accent, pace`, e.g. `happy, Tamil accent, steady pace`. a part you leave out becomes `professional`, the script's accent, or `fast pace`.                                    |
| `speaker`            | `ira`               | optional. `ira`, `aisha`, `siya` or `zoya`.                                                                                                                                                    |
| `temperature`        | `0.8`               | sampling temperature.                                                                                                                                                                          |
| `top_p`              | `1.0`               | nucleus sampling.                                                                                                                                                                              |
| `top_k`              | `30`                | top-k sampling.                                                                                                                                                                                |
| `max_new_tokens`     | sized from the text | output length cap, set from your text: never below `2048`, up to `8192`. a larger value you send is kept, so you don't need to set it.                                                         |
| `repetition_penalty` | n/a                 | accepted and ignored.                                                                                                                                                                          |

<Note>
  **long text?** one request speaks up to about 80 seconds of audio: roughly
  1,200 english characters, or about 600 characters of indic-script text at a
  steady pace. split longer text into sentences. a generation that can't finish
  comes back as an error instead of cut-off audio, and it isn't charged:
  `502 GENERATION_TOO_LONG` over http, or an `error` frame with code
  `GENERATION_TOO_LONG` over a websocket. any other failure, like the engine
  being unreachable, is `GENERATION_ERROR`.
</Note>

## how it differs from mulberry 1.5

silk mulberry 1.5 (`mulberry`) is unchanged. pick the model per request.

|                    | silk mulberry 1.5                                    | silk mulberry 1.6                                                                                                            |
| ------------------ | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| model id           | `mulberry`                                           | `mulberry-1.6`                                                                                                               |
| languages          | hindi in devanagari, english in latin (code-mixed)   | 22 indian languages, each in its own script                                                                                  |
| voices             | twelve named voices, or one built from `description` | four named voices, `ira` by default                                                                                          |
| `description`      | required. one natural-language sentence              | optional. `style, accent, pace`                                                                                              |
| delivery cues      | `description` plus inline tags like `<laugh>`        | `description` plus `<laugh>`, `<chuckle>` and `<sigh>`; other `<tag>` markers are dropped, `[tone]` markers aren't supported |
| sampling defaults  | `temperature` `0.6`, `top_p` `0.95`, `top_k` `50`    | `temperature` `0.8`, `top_p` `1.0`, `top_k` `30`                                                                             |
| `max_new_tokens`   | `2048`. raise it for long lines                      | sized from your text                                                                                                         |
| too long to finish | the audio comes back cut off                         | `GENERATION_TOO_LONG`, and not charged                                                                                       |
| endpoints          | `/v1/tts`, `/v1/tts/json`, websocket streaming       | the same, with the same frames                                                                                               |
| dashboard agents   | yes, with phone calls                                | not yet                                                                                                                      |

→ to write good descriptions, read the [prompting guide](/prompting-mulberry-1-6).
