TTS voices: Difference between revisions

From Wiki G1R-MP G1 Remake Multiplayer
Jump to navigation Jump to search
Clarify all supported TTS languages; neutral voice-profile examples and separate Ukrainian backend note
Release 0.1.7 / BUILD199 / Protocol 39: current API availability, setup and improvements
 
Line 1: Line 1:
'''Coming in 0.1.7 — not released yet.''' Not included in public 0.1.6. Use matching TTS-capable server and clients.
'''Available since 0.1.7.''' Use matching TTS-capable server and clients.


See [[TTS configuration]] for installation and [[Server TTS]] for rendering, persistent audio and remote playback.
See [[TTS configuration]] for installation and [[Server TTS]] for rendering, persistent audio and remote playback.

Latest revision as of 23:49, 10 October 2026

Available since 0.1.7. Use matching TTS-capable server and clients.

See TTS configuration for installation and Server TTS for rendering, persistent audio and remote playback.

Voice and preset configuration

Chatterbox Multilingual V3 supports 23 languages: Arabic (ar), Danish (da), Dutch (nl), English (en), Finnish (fi), French (fr), German (de), Greek (el), Hebrew (he), Hindi (hi), Italian (it), Japanese (ja), Korean (ko), Malay (ms), Norwegian (no), Polish (pl), Portuguese (pt), Russian (ru), Spanish (es), Swahili (sw), Swedish (sv), Turkish (tr) and Chinese (zh). Select any supported language in a voice or preset; use getTtsLanguages("chatterbox_v3") to read the available codes.

Ukrainian backend note: Ukrainian (uk) is supported through the separate StyleTTS2 engine: engine="styletts2_uk", language="uk". It requires that engine to be installed/enabled and an authorized reference sample. It is not a Chatterbox language; its engine-specific parameters are listed below.

Both engines support a server-owned reference sample. Place it under the worker's voices directory, not under game resources. Use WAV, FLAC or OGG, 1–30 seconds, mono/stereo, 8–96 kHz, at most 8 MiB. Supply its lowercase SHA-256. Use recordings you are authorized to use. Ukrainian requires a reference; Chatterbox can use its built-in voice.

Adding a downloaded or recorded voice

Step 1. Obtain an audio sample that you have permission to use for synthesized speech, for example a speaker's explicitly permitted sample or your own recording. Being publicly downloadable does not itself grant that permission. Keep the source and permission information in your operator records. Do not impersonate a person without their consent. Step 2. Prefer clean speech from one speaker, without music, overlapping voices or long silence. A practical starting point is 5–15 seconds; the accepted range remains 1–30 seconds. Voice similarity and accent are not guaranteed. For Ukrainian, start with a clearly spoken Ukrainian reference. Step 3. If necessary, convert the actual audio to WAV/OGG/FLAC in an audio editor. Renaming .mp3 to .wav does not convert it. For a simple interoperable sample, use mono PCM WAV. Keep it within the limits above. Step 4. Choose a simple ASCII filename with a lowercase extension, e.g. guard.wav or guards/voice.ogg. Avoid spaces, accented filenames, absolute paths, .., symlinks and URLs. Copy it into tts/voices on the machine running the worker. An external worker needs its own identical copy, not just a file on the game server. Step 5. Calculate the hash of the final file after conversion/copying:

(Get-FileHash -Algorithm SHA256 .\tts\voices\guard.wav).Hash.ToLowerInvariant()
sha256sum tts/voices/guard.wav

Step 6. Put the relative filename and the 64-character lowercase hash in a server-side voice/preset below, or use the private /ttstest voice commands. The owner provisions the file; the game client never uploads a voice through this API. A new filename under the existing voice directory can be used by the next request; changing startup configuration requires restarting the server. Step 7. Render a short sentence and listen before rendering a whole dialogue library. Replacing the sample requires updating its hash. For a changed permanently named clip, also choose a new saveAs name.

A voice sample is not a downloadable TTS model. Arbitrary .pt, .pth, .safetensors, .onnx, Python scripts or executables are not accepted by the voice API. Do not install a downloaded “voice pack” into tts/runtime: the supported engine weights are provisioned separately. ZIPs must not be passed as references; if an authorized archive contains audio, extract and inspect the actual audio sample outside the server first.

A ready-made spoken recording that you want to play unchanged is different again: add it as a normal audio asset to a resource and use the existing client resource-audio API. Do not pass it through TTS just to play it, and do not manually insert it into tts/data; that directory contains generated clips with validated metadata. loadTtsAudio loads a name previously created by saveAs, not an arbitrary file path or internet URL.

Voice profiles and language selection

These are examples in a server-side Lua resource. The first profile works with any language listed for Chatterbox: change language to the supported code you need (en below is only an example). Replace each hash with the hash of the corresponding private sample. createTtsVoice does not train a model or render a recording: it stores a validated reusable configuration.

local voice, why = createTtsVoice("guard", {
    engine = "chatterbox_v3", language = "en", seed = 12345,
    reference = "guard.wav", referenceHash = "REPLACE_WITH_64_LOWERCASE_HEX_CHARACTERS",
    parameters = {exaggeration=0.5, cfgWeight=0.5, temperature=0.8}
})
if not voice then outputDebugString("TTS profile rejected: " .. tostring(why)) end

For Ukrainian only, select the separate backend and its parameters instead:

local preset, why = createTtsPreset("guard_uk", {
    engine = "styletts2_uk", language = "uk", seed = 12345,
    reference = "guards/guard_uk.ogg", referenceHash = "REPLACE_WITH_64_LOWERCASE_HEX_CHARACTERS",
    parameters = {speed=1.0, alpha=0.0, beta=0.0, embeddingScale=1.0, diffusionSteps=10}
})
if not preset then outputDebugString("TTS preset rejected: " .. tostring(why)) end

Then select {voice="guard"} or the corresponding preset in generation options. Use updateTtsVoice / updateTtsPreset when the name already exists. Multiple profiles can point to one reference with different languages/parameters; changing those options creates a different cache request. Switching profiles never changes a player's game voice-language setting.

createTtsPreset("guard", {
    engine = "chatterbox_v3", language = "en", seed = 12345,
    reference = "guard.ogg", referenceHash = "REPLACE_WITH_64_LOWERCASE_HEX_CHARACTERS",
    parameters = {exaggeration=0.5, cfgWeight=0.5, temperature=0.8}
})
local job = renderTts("Stop!", {preset="guard", saveAs="guard_stop"})

Presets and voices store a complete generation configuration, not engine pointers. Request overrides replace top-level fields. Use either voice or preset, not both. Replacing the parameters table uses defaults for omitted values. getTtsCapabilities().engines[engine].parameters[name] returns a three-element array: [1] default, [2] minimum, [3] maximum (not named fields):

Engine Parameter Default Allowed range
Chatterbox V3 exaggeration 0.5 0–2
Chatterbox V3 cfgWeight 0.5 0–1
Chatterbox V3 temperature 0.8 0.05–5
Chatterbox V3 repetitionPenalty 1.2 1–3
Chatterbox V3 minP 0.05 0–1
Chatterbox V3 topP 1.0 0.01–1
Ukrainian StyleTTS2 speed 1.0 0.5–2
Ukrainian StyleTTS2 alpha, beta 0.0 each 0–1
Ukrainian StyleTTS2 embeddingScale 1.0 0.1–3
Ukrainian StyleTTS2 diffusionSteps 10 integer 1–50

seed is an integer 0–4294967295 (default 0). Start with defaults and change one setting at a time. There is no separate pitch, gender, emotion-name or universal speed control in this API; in particular, speed is not a Chatterbox parameter. Select a different authorized voice sample for a different speaker, rather than passing unsupported keys.

Only actual engine parameters are accepted. Unsupported keys fail instead of being silently ignored. Voices/presets live in the resource VM session. Persist them with the existing resource storage API:

writeResourceData("tts_profiles", toJSON(exportTtsPresets()))
local text = readResourceData("tts_profiles")
if type(text) == "string" then
    local profiles = fromJSON(text)
    local ok, why = importTtsPresets(profiles)
    if not ok then outputDebugString(why) end
end

Import validates the entire document before replacing that resource's collections. It never installs Python, loads a URL, or accepts executable model files from Lua.