# Vietnamese Text to Speech & Voice Cloning (`andrew_babo/vieneu-tts`) Actor

Vietnamese text to speech at studio quality: 23 built-in voices (North, Central, South accents, male and female), voice cloning from a 3-8 second clip, English-Vietnamese mixed text and emotion cues. MP3, WAV and Opus output. No rental fee - you pay Apify compute only.

- **URL**: https://apify.com/andrew\_babo/vieneu-tts.md
- **Developed by:** [Andrew Babo](https://apify.com/andrew_babo) (community)
- **Categories:**
- **Stats:** 60 total users, 18 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Vietnamese Text to Speech & Voice Cloning (VieNeu-TTS v3 Turbo)

> Powered by the open-source **[VieNeu-TTS](https://github.com/pnnbao97/VieNeu-TTS)** model by **Phạm Nguyễn Ngọc Bảo** ([@pnnbao97](https://github.com/pnnbao97), Apache-2.0). Andrew Babo only packages and speed-optimises it for Apify — see [Credits & source](#credits--source). No rental or usage fee: you pay Apify compute only.

Turn Vietnamese text into natural, studio-clean **48 kHz speech** — with 23 built-in Vietnamese voices (North / Central / South accents, male & female), zero-shot **voice cloning** from a 3–8 second clip, English–Vietnamese code-switching, and inline emotion cues. Runs on CPU only, so it is cheap to run at scale on Apify.

**Keywords:** Vietnamese text to speech, Vietnamese TTS API, giọng đọc tiếng Việt AI, AI voice generator Vietnamese, voice cloning tiếng Việt, text to speech MP3, TTS for YouTube/TikTok voiceover.

### What you can build

- YouTube, TikTok and Reels **Vietnamese voiceovers**
- Audiobooks and story narration (`doc_truyen` style voices)
- News reading and e-learning narration (`tin_tuc` style voices)
- IVR prompts, notifications and accessibility read-aloud
- Cloned brand/personal voice for repeatable content

### Quick start

```json
{
  "text": "Xin chào, đây là giọng đọc tiếng Việt tự nhiên do AI tạo ra.",
  "voice": "Adam",
  "format": "mp3"
}
```

Run it from the API:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/andrew_babo~vieneu-tts/runs?token=$APIFY_TOKEN&waitForFinish=180" \
  -H "Content-Type: application/json" \
  -d '{"text":"Xin chào, đây là giọng nói tiếng Việt.","voice":"Trúc Ly","format":"mp3"}'
```

The audio file lands in the run key-value store (`audio.wav` / `audio.mp3` / `audio.ogg`) and one dataset row carries `audio_url` plus timing metrics.

### Voice IDs (23 built-in Vietnamese voices)

Pass the **exact** name in the `voice` field (Vietnamese diacritics included). Default: `Adam`.

| Voice ID | Gender | Accent (region) | Style |
|---|---|---|---|
| `Adam` (default) | Male | South (Nam) | Natural — tự nhiên |
| `Phạm Tuyên` | Male | North (Bắc) | Natural — tự nhiên |
| `Xuân Vĩnh` | Male | North (Bắc) | Natural — tự nhiên |
| `Mạnh Dũng` | Male | North (Bắc) | Natural — tự nhiên |
| `Minh Quân` | Male | North (Bắc) | Natural — tự nhiên |
| `Quang Sơn` | Male | Central (Trung) | Natural — tự nhiên |
| `Minh Đức` | Male | North (Bắc) | News — tin tức |
| `Minh Triết` | Male | South (Nam) | News — tin tức |
| `Thanh Bình` | Male | North (Bắc) | Storytelling — kể chuyện |
| `Anh Khôi` | Male | North (Bắc) | Storytelling — kể chuyện |
| `Thái Sơn` | Male | South (Nam) | Storytelling — kể chuyện |
| `Đức Trí` | Male | South (Nam) | Audiobook — đọc truyện |
| `Trúc Ly` | Female | North (Bắc) | Natural — tự nhiên |
| `Đoan Trang` | Female | North (Bắc) | Natural — tự nhiên |
| `Ngọc Huyền` | Female | North (Bắc) | Natural — tự nhiên |
| `Ngọc Trân` | Female | Central (Trung) | Natural — tự nhiên |
| `Mai Anh` | Female | North (Bắc) | News — tin tức |
| `Thùy Dung` | Female | South (Nam) | News — tin tức |
| `Ngọc Linh` | Female | North (Bắc) | Storytelling — kể chuyện |
| `Thục Đoan` | Female | South (Nam) | Storytelling — kể chuyện |
| `Quỳnh Anh` | Female | North (Bắc) | Audiobook — đọc truyện |
| `Mỹ Duyên` | Female | South (Nam) | Audiobook — đọc truyện |
| `Kim Thanh` | Female | South (Nam) | Audiobook — đọc truyện |

Picking a voice:

- **Ads / social videos:** `Adam`, `Trúc Ly`, `Thùy Dung`
- **News / corporate:** `Minh Đức`, `Mai Anh`, `Minh Triết`
- **Story & audiobook:** `Thái Sơn`, `Ngọc Linh`, `Quỳnh Anh`, `Kim Thanh`
- **Central accent:** `Quang Sơn`, `Ngọc Trân`

If a voice name is misspelled the run fails with the full list of valid IDs.

### Voice cloning (zero-shot, no training)

Give a public URL to a clean reference clip and the model speaks any Vietnamese text in that voice. Cloning **overrides** `voice`.

```json
{
  "text": "Đây là giọng đã được nhân bản từ đoạn ghi âm mẫu.",
  "ref_audio_url": "https://example.com/reference.wav",
  "denoise": true,
  "format": "wav"
}
```

Reference clip checklist:

| Requirement | Recommendation |
|---|---|
| Length | 3–8 seconds (6 s is the sweet spot) |
| Content | One speaker, natural sentences, no music or background voices |
| Format | WAV or MP3, mono, 16 kHz or higher, no heavy compression |
| Delivery | Record in the emotion you want — **emotion is transferred from the clip**, not from a parameter |
| Hosting | Direct-download URL (S3, key-value store, CDN). Google Drive share links do not work. |
| Consent | Only clone voices you own or have written permission to use |

`denoise: true` (default) cleans hiss and room noise before enrollment. Turn it off if your clip is already studio-quality and sounds over-processed after cloning.

Cloning tips:

- Same clip = consistent voice across many runs, so store it once and reuse the URL.
- A clip recorded cheerfully clones a cheerful voice; a calm clip clones a calm voice.
- Clips shorter than ~3 s or longer than ~10 s reduce similarity.

### Emotion cues (Vietnamese, exactly 3 supported)

Write cues inline in the text:

| Cue | Also accepted | Effect |
|---|---|---|
| `[cười]` | `[cuoi]`, `[laugh]`, `[chuckle]`, `[haha]` | Laughter |
| `[thở dài]` | `[tho dai]`, `[sigh]`, `[breath]` | Sigh |
| `[hắng giọng]` | `[hang giong]`, `[clear throat]`, `[cough]` | Throat clear |

Example:

```text
Mình không tin nổi chuyện đó [cười]. Thôi kể tiếp nhé [hắng giọng].
```

Any other bracketed tag (`[buồn]`, `[khóc]`, `[hét]`, …) is **not** an emotion. The actor strips unknown tags and reports them in the `warnings` field of the dataset row instead of reading them aloud.

### Tone presets and inline directives

`tone` sets delivery style (it fills `temperature` / `speed` only when you did not set them yourself):

| `tone` | Feel |
|---|---|
| `tự nhiên` | Natural (default) |
| `trầm` | Calm, slower |
| `nhẹ nhàng` | Gentle |
| `kể chuyện` | Storytelling |
| `vui` | Cheerful |
| `hào hứng` | Excited |
| `trang trọng` | Formal / news |

Inline directives inside `text` (sticky until the next marker):

```text
[tone: vui] Chào cả nhà, tin vui đây! [pause: 1s] [tone: trầm] Nhưng có một điều cần lưu ý.
```

`[pause]` inserts 0.5 s; `[pause: 1s]` inserts a custom silence (0.05–10 s).

### Input reference

| Field | Type | Default | Description |
|---|---|---|---|
| `text` | string | required | Vietnamese or Vi/En mixed text, up to 10,000 characters. |
| `voice` | enum | `Adam` | One of the 23 voice IDs above. |
| `ref_audio_url` | string | — | Reference clip URL for voice cloning; overrides `voice`. |
| `denoise` | boolean | `true` | Clean the reference clip before enrollment. |
| `tone` | enum | `tự nhiên` | Delivery preset (table above). |
| `expressiveness` | enum | `medium` | `low` / `medium` / `high`. Overridden by `temperature`. |
| `temperature` | number | `0.8` | 0.1–1.5. Higher = more expressive, less stable. |
| `speed` | string | `1.0` | `1.2` ≈ 20% faster. |
| `pitch_preserve` | boolean | `true` | Change speed without the chipmunk effect. |
| `precision` | enum | `auto` | `fp32` (cleanest) / `int8` (fastest) / `auto` follows `quality`. |
| `quality` | enum | `smooth` | `smooth` = seamless single pass for short text; `fast` = parallel, slightly faster. |
| `single_pass` | boolean | `false` | Force one engine to render the whole text. |
| `trim_silence` | boolean | auto | Trim edge silence; auto-off when emotion cues are present. |
| `format` | enum | `wav` | `wav` 48 kHz PCM, `mp3` 128 kbps, `opus` 64 kbps. |

### Output

```json
{
  "audio_url": "https://api.apify.com/v2/key-value-stores/<store-id>/records/audio.mp3",
  "engine": "vieneu-v3-turbo",
  "chars": 49,
  "chunks": 1,
  "duration_s": 5.8,
  "load_ms": 7300.0,
  "synth_ms": 2900.0,
  "ms_total": 10300.0,
  "rtf": 0.5,
  "peak_ram_mb": 1100.0,
  "cores": 4,
  "sample_rate": 48000,
  "bytes": 556844,
  "format": "mp3"
}
```

`rtf < 1` means synthesis is faster than realtime. `warnings` appears only when unknown bracketed tags were removed.

### Standby mode (low-latency API)

Enable Standby to keep the model warm and skip the ~15–40 s cold model load:

```bash
curl -X POST "https://<actor-standby-url>/" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text":"Xin chào từ chế độ Standby.","voice":"Mai Anh","format":"mp3"}' \
  --output speech.mp3
```

The response body is the audio file; timing metrics come back in the `X-TTS-Metrics` header. Warm requests typically run 7–13 s for a short sentence on a 16 GB / 4 vCPU container.

### Performance and cost notes

- CPU-only: no GPU required, 16 GB memory recommended (4 GB minimum).
- `int8` is the fastest mode; `fp32` is the reference-fidelity mode.
- Long narration: keep the whole passage in one run for prosody continuity, or split at sentence boundaries client-side and join with a short pause.

### Limitations

- Vietnamese-first. English words inside Vietnamese sentences work; full English paragraphs are better served by an English TTS actor.
- Emotion cues are experimental model behaviour, not guaranteed on every sentence.
- Cloning quality depends heavily on the reference clip.
- Cold start pays the model load once per container.

### Credits & source

The underlying model and Python library are **not** the work of the Actor publisher.

**Original author:** **Phạm Nguyễn Ngọc Bảo** — Speech AI Specialist and Medical NLP Researcher (Nhân dân Gia Định Hospital, Ho Chi Minh City, Vietnam), creator and maintainer of VieNeu-TTS.

| Resource | Link |
|---|---|
| Author (GitHub) | https://github.com/pnnbao97 |
| Source repository | https://github.com/pnnbao97/VieNeu-TTS |
| Models (Hugging Face) | https://huggingface.co/pnnbao-ump/VieNeu-TTS |
| Python package | https://pypi.org/project/vieneu/ |
| Project website | https://www.vieneu.io |

**Model lineage:** VieNeu-TTS is built on the `neuphonic/neutts-air` base and trained on the author's own Vietnamese speech datasets (`pnnbao-ump/VieNeu-TTS-140h`, then `VieNeu-TTS-1000h`); later v2/v3 lines add bilingual English–Vietnamese data and podcast-style multi-speaker support. This Actor runs the **v3 Turbo** line through the official `vieneu` package. Released under the **Apache License 2.0**.

**What Andrew Babo did:** Andrew Babo is *not* the model author. His role is to package VieNeu-TTS as an Apify Actor and optimise it for fast CPU inference on the Apify platform — a warm multi-engine pool, int8/fp32 precision selection, chunking and seam levelling for smooth joins, Standby warm start to cut cold-load time, inline `tone` / `pause` directives, emotion-cue validation, and MP3/Opus export.

**Pricing:** this Actor charges **no rental and no usage fee**. You pay only Apify platform compute for the time your run consumes.

### Licensing and consent

VieNeu-TTS weights, preset voices and the `vieneu` library are distributed by the original author under the **Apache License 2.0**; the copyright stays with Phạm Nguyễn Ngọc Bảo. Keep that attribution if you redistribute anything derived from this Actor, and review the upstream model card and dataset terms before commercial distribution. For cloning, use only recordings you own or are authorized to process — do not impersonate anyone without permission.

# Actor input Schema

## `text` (type: `string`):

Text to speak. Emotion cues: \[cười] (laugh), \[thở dài] (sigh), \[hắng giọng] (throat clear) — English/unaccented spellings like \[laugh] or \[tho dai] are mapped automatically; any other bracketed tag is silently dropped and reported in warnings. Inline directives: \[tone: hào hứng] switches delivery for the following text (tones: tự nhiên, trầm, nhẹ nhàng, kể chuyện, vui, hào hứng, trang trọng); \[pause] or \[pause: 1s] inserts silence.

## `voice` (type: `string`):

One of the 23 built-in Vietnamese voices (male/female, North / Central / South accent, natural / news / storytelling / audiobook styles). Ignored when a reference audio URL is provided.

## `ref_audio_url` (type: `string`):

Public direct-download URL of a clean 3-8 second clip of one speaker (WAV or MP3, no music). The cloned voice overrides the preset voice, and the emotion of the clip is carried into the output. Only clone voices you own or are authorized to use.

## `denoise` (type: `boolean`):

Clean up background noise in the reference clip before cloning the voice.

## `temperature` (type: `number`):

Expressiveness. ~0.8 is the author's most stable recommendation; higher = more expressive but less stable.

## `speed` (type: `string`):

Playback rate, 1.0 = normal, 1.2 = 20% faster.

## `pitch_preserve` (type: `boolean`):

Time-stretch without the chipmunk/deep-voice effect (ffmpeg atempo). Disable for the old plain resampling.

## `tone` (type: `string`):

Delivery style preset (temperature + speed). The model carries emotion in the voice/reference clip itself, so tone presets shift the delivery moderately — for a truly emotional read, supply a reference clip recorded in that emotion. Inline \[tone: ...] markers in the text override this per segment.

## `expressiveness` (type: `string`):

How much the delivery moves. High can drift into a sing-song, wobbly read on short lines; medium keeps colour without the drift. Overridden by Temperature when that is set explicitly.

## `precision` (type: `string`):

Auto uses fp32 in Smooth mode and int8 in Fast mode. int8 is quicker on Apify CPUs but adds a faint metallic buzz that is most audible in expressive speech.

## `format` (type: `string`):

Container/codec of the returned audio file.

## `quality` (type: `string`):

Smooth renders short text in a single pass so there are no chunk seams — up to 400 characters, or ~900 characters when the text contains emotion cues. Fast always parallelizes; quicker, with a small risk of audible seams.

## `trim_silence` (type: `boolean`):

Default: on, but automatically off when the text contains emotion cues so laugh/sigh tails are not clipped.

## `single_pass` (type: `boolean`):

Render the whole text on one engine, no matter how long it is. Seamless by definition, but slower on long text. Emotional text (with cues) already stays single-pass up to ~900 characters.

## Actor input object example

```json
{
  "text": "Xin chào, đây là VieNeu-TTS chạy trên Apify bằng CPU.",
  "voice": "Adam",
  "denoise": true,
  "temperature": 0.8,
  "speed": "1.0",
  "pitch_preserve": true,
  "expressiveness": "medium",
  "precision": "auto",
  "format": "wav",
  "quality": "smooth",
  "single_pass": false
}
```

# Actor output Schema

## `audio` (type: `string`):

Generated audio record stored in the run's key-value store (audio.wav / audio.mp3 / audio.ogg).

## `metrics` (type: `string`):

Dataset rows with engine, duration, synthesis time, RTF, peak RAM and the audio URL.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "text": "Xin chào, đây là VieNeu-TTS chạy trên Apify bằng CPU."
};

// Run the Actor and wait for it to finish
const run = await client.actor("andrew_babo/vieneu-tts").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "text": "Xin chào, đây là VieNeu-TTS chạy trên Apify bằng CPU." }

# Run the Actor and wait for it to finish
run = client.actor("andrew_babo/vieneu-tts").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "text": "Xin chào, đây là VieNeu-TTS chạy trên Apify bằng CPU."
}' |
apify call andrew_babo/vieneu-tts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,andrew_babo/vieneu-tts"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/bCSCFYaeeZlircD5W/builds/MAMKbvG7e820Vy9MI/openapi.json
