uTPro.Feature.TextToSpeech
18.0.1
dotnet add package uTPro.Feature.TextToSpeech --version 18.0.1
NuGet\Install-Package uTPro.Feature.TextToSpeech -Version 18.0.1
<PackageReference Include="uTPro.Feature.TextToSpeech" Version="18.0.1" />
<PackageVersion Include="uTPro.Feature.TextToSpeech" Version="18.0.1" />
<PackageReference Include="uTPro.Feature.TextToSpeech" />
paket add uTPro.Feature.TextToSpeech --version 18.0.1
#r "nuget: uTPro.Feature.TextToSpeech, 18.0.1"
#:package uTPro.Feature.TextToSpeech@18.0.1
#addin nuget:?package=uTPro.Feature.TextToSpeech&version=18.0.1
#tool nuget:?package=uTPro.Feature.TextToSpeech&version=18.0.1
uTPro.Feature.TextToSpeech
Documentation: https://docs.utpro.dev/uTPro.Feature.TextToSpeech/
Add a "listen to this article" player to any Umbraco 16, 17 or 18 page with one line in a template. You pass the text to read, visitors get an accessible audio player (play/pause, speed, progress, resume, download), and you choose the voice from a backoffice workspace. It is free and offline by default: the Browser voice needs no API key, no files and no outbound traffic. When you want consistent, higher-quality audio, map a culture to a server voice (Piper or Kokoro, fully local, or any OpenAI-compatible speech API). Server audio is generated in the background, cached on disk by content hash and reused, so a page render never waits for a synthesizer.
Part of the uTPro feature family (alongside Simple Cart, Simple Form Builder, SEO Audit and others).
Which package do I need?
Start with the core package. Add an offline engine only when you want a server voice.
| You want | Install | Cost |
|---|---|---|
| Read articles aloud, zero setup | uTPro.Feature.TextToSpeech only (Browser voice) |
Free |
| One consistent offline voice for everyone, incl. Vietnamese | core + uTPro.Feature.TextToSpeech.Piper |
Free |
| The most natural offline English | core + uTPro.Feature.TextToSpeech.Kokoro |
Free |
| Broadcast quality, many languages | core + an OpenAI-compatible API key (no add-on) | Paid API |
The core works on its own: the Browser voice and the OpenAI-compatible provider are both built in. Piper and Kokoro are optional add-ons for local server voices. You install an add-on instead of, not before, the core: each add-on depends on the core package, so dotnet add package uTPro.Feature.TextToSpeech.Piper pulls in uTPro.Feature.TextToSpeech automatically at the same version. If a mapped engine is missing or misconfigured, pages fall back to the Browser voice, so a culture is never silent.
Install
dotnet add package uTPro.Feature.TextToSpeech
That's it. The package self-wires its services, migration and backoffice UI through an Umbraco composer, so there are no changes to your Program.cs. Requires Umbraco 16, 17 or 18 (net9.0 / net10.0).
Optional offline voices are separate packages, so the core stays small:
dotnet add package uTPro.Feature.TextToSpeech.Piper # fast, local, includes Vietnamese
dotnet add package uTPro.Feature.TextToSpeech.Kokoro # natural English and a few other languages, local
Use it
In any template, pass the text you want read:
@await Component.InvokeAsync("TextToSpeechPlayer", new { content = Model, text = bodyHtml })
content is the page (for its culture and key), text is what to read (HTML is allowed and stripped). Leave text out and the player falls back to the first non-empty property in Rendering.TextPropertyAliases (bodyText, content by default).
The template decides what is read because article bodies are usually Block List / Block Grid, and only your template knows which blocks are prose.
Voices
| Engine | Where it runs | Needs | Languages | Audio file |
|---|---|---|---|---|
| Browser (default) | Visitor's browser (Web Speech API) | Nothing | Whatever the visitor's browser offers; Edge has neural Vietnamese voices | None |
| Piper (add-on) | Your server, offline | Piper binary + .onnx voice files |
~40 locales, including vi_VN |
Cached WAV |
| Kokoro (add-on) | Your server, offline | ~300 MB model (auto-download or file) | English, Spanish, French, Hindi, Italian, Japanese, Chinese, Portuguese | Cached WAV |
| OpenAI-compatible API | Your provider | Endpoint + API key | Provider's | Cached MP3/WAV |
Pick the voice per culture in Settings → Advanced Settings → Text To Speech → Voices. If a mapped engine is missing or not configured, the page falls back to the Browser voice, so a language is never silent.
How server audio works
- The template renders the player. The package normalises the text, applies your pronunciation rules and computes a content hash.
- It registers that hash in a database table and queues generation in the background. The page does not wait.
- The player streams
/api/text-to-speech/audio/{hash}. The file is generated once, stored underumbraco/Data/uTProTextToSpeechCache, and served with ETag and range support. - Publishing a page marks its audio stale; the next render produces new audio and the old file is purged after
OrphanRetentionDays(7).
Backoffice
Under Settings → Advanced Settings → Text To Speech:
- Voices - engine status cards, a voice per culture, preview.
- Pronunciation - replacement rules ("TP.HCM" becomes "Thành phố Hồ Chí Minh") with a before/after test box.
- Audio cache - every generated file with search, filters, play, download, regenerate and delete.
Every document also gets an Audio content app showing the audio of that page.
Configuration
Everything has a working default. Settings live under uTPro:Feature:TextToSpeech:
{
"uTPro": {
"Feature": {
"TextToSpeech": {
"Provider": "Auto",
"OpenAi": { "Endpoint": "https://api.openai.com", "ApiKey": "", "Model": "gpt-4o-mini-tts" },
"Piper": { "ExecutablePath": "", "ModelsRoot": "" },
"Kokoro": { "ModelPath": "", "WarmUp": true }
}
}
}
}
Keep ApiKey in user-secrets or environment variables, not in a committed file. The full reference is in the documentation.
Security
- The public audio endpoint accepts only a hash your own template registered. Visitors cannot send text, so the site cannot be used as a free text-to-speech service.
- Calls to the speech API are SSRF-guarded at connect time: loopback, private, link-local and reserved addresses are refused unless you opt in with
OpenAi:AllowLocalEndpoint. - The API key is never returned by any endpoint; the backoffice shows only that one is set.
- Piper is started with an argument list (never a shell), the voice id must be a bare file name inside the models folder, and every run has a timeout.
- Backoffice endpoints are authenticated; the Voices, Pronunciation and Audio cache tabs need Settings access, the Audio content app needs Content access.
Building / packing
dotnet build uTPro.Feature.TextToSpeech.sln -c Release
dotnet test tests/uTPro.Feature.TextToSpeech.Tests/uTPro.Feature.TextToSpeech.Tests.csproj -c Release
pwsh ./pack.ps1
pack.ps1 wipes bin/obj, packs the core and both add-ons into Build/, evicts the version from the local NuGet cache and mirrors the docs to the public repo.
Test site
src/uTPro.Feature.TextToSpeech.TestSite is a minimal Umbraco 18 host (SQLite, unattended install as admin@example.com). Run it yourself with dotnet run --project src/uTPro.Feature.TextToSpeech.TestSite, create a document type with a bodyText rich text property and a template that calls the player, then publish a page.
License
See LICENSE.txt. Free to use in your own Umbraco sites, including commercial ones.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Umbraco.Cms.Api.Management (>= 18.0.0 && < 19.0.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on uTPro.Feature.TextToSpeech:
| Package | Downloads |
|---|---|
|
uTPro.Feature.TextToSpeech.Kokoro
Kokoro offline voice engine for uTPro.Feature.TextToSpeech. Adds natural-sounding English and other Kokoro voices that run fully in-process on your server (ONNX, CPU only, no API key, no outbound traffic after the model is downloaded). Registers itself through the TextToSpeech engine collection, so no edits to the core package or the host Program.cs are needed. Windows and Linux. |
|
|
uTPro.Feature.TextToSpeech.Piper
Piper offline voice engine for uTPro.Feature.TextToSpeech. Adds fast, fully local server-side voices (no API key, no outbound traffic) by running the Piper binary you provide against .onnx voice models you download - including Vietnamese. Registers itself through the TextToSpeech engine collection, so no edits to the core package or the host Program.cs are needed. Windows and Linux. |
GitHub repositories
This package is not used by any popular GitHub repositories.
v17.0.1 / v18.0.1: Package title cleanup - the NuGet package title no longer carries the "for Umbraco N" suffix, so the marketplace listing shows the plain product name. No functional, API, UI or database changes. v17.0.0 / v18.0.0: Initial release. Ships as two version lines — 17.x for Umbraco 17 and 18.x for Umbraco 18 — with each line's Umbraco dependency boxed to that one major, so an Umbraco 17 host always resolves the 17.x line. TextToSpeechPlayer ViewComponent (text-first: the template passes the text to read), Browser voice by default, OpenAI-compatible speech API provider (SSRF-guarded), disk audio cache keyed by content hash, background generation queue, publish handling, orphan cleanup, and a backoffice workspace (Voices, Rules, Cache) with an Audio content app. Piper and Kokoro offline engines ship as separate add-on packages.