User avatar
Site Admin
Roblox TTS Asset Generation (October 2026): the Four Fields CreateAssetAsync Reads, the Rate Limit, and the Voice List
Quick Summary
  • On October 22, 2026, Roblox expanded

    Code: Select all

    AssetService:CreateAssetAsync()
    to accept

    Code: Select all

    AudioTextToSpeech
    objects, so speech can be generated once in Studio and stored as a normal audio asset instead of being synthesised every time it plays.
  • The point is rate limits. Live text-to-speech is throttled by a formula based on concurrent players, so a game with a lot of dynamic dialogue can hit the ceiling. An asset that already exists plays instantly and consumes none of that budget.
  • Only four properties of the object are read by the asset service:

    Code: Select all

    Text
    ,

    Code: Select all

    VoiceId
    ,

    Code: Select all

    Pitch
    and

    Code: Select all

    Speed
    . Everything else on the object is ignored.
  • Three things are still missing: you cannot add a name or description to the uploaded asset, you cannot specify a creator ID, and every generated asset is named

    Code: Select all

    TTS_Asset_
    followed by its asset ID.
  • The API is a Studio-side tool. It cannot be called from inside a running experience, which is a separate limitation from the rate limits and worth knowing before you plan around it.
Why This Landed Now

Roblox first opened text-to-speech to creators in beta at the end of June 2025, and announced the full release in October 2025 alongside higher rate limits and observability dashboards on Creator Hub. The original

Code: Select all

CreateAssetAsync
API is older still. It arrived in December 2024 for Studio plugins and Open Cloud Luau execution, and at launch it supported four asset types:

Code: Select all

Enum.AssetType.Model
,

Code: Select all

Enum.AssetType.Plugin
,

Code: Select all

Enum.AssetType.Mesh
and

Code: Select all

Enum.AssetType.Image
. Audio was not among them.

The October 2026 change closes that gap. Roblox's own framing is that running text-to-speech at play time is what forces you into the rate limit in the first place, and generating the asset in Studio removes the request from the running experience entirely. If your dialogue is static, or mostly static with a few dynamic lines mixed in, this is the difference between a voice that works and a voice that silently fails to play during a busy match.

The Rate Limit Problem, With Numbers

The live API is throttled per experience, not per player, and the formula scales with concurrency:

Code: Select all

max requests per minute per experience = 1 + (6 * number_of_concurrent_users)
Work that out for a few sizes and the shape of the problem becomes clear:
  • 10 concurrent players gives 61 requests per minute across the whole experience.
  • 100 concurrent players gives 601 requests per minute.
  • 1,000 concurrent players gives 6,001 requests per minute.
  • 10,000 concurrent players gives 60,001 requests per minute, which is the number Roblox itself uses in the release announcement.
On top of that there is a client-side throttle of 4 requests per second per user, and a hard cap of 300 characters of text per request. The 300 character cap means longer dialogue has to be split across multiple requests, which multiplies the pressure on that per-minute budget.

So the honest trade is this. The formula is generous for a small game, and tight for a big one the moment you start synthesising a lot of speech on the fly. Asset generation moves the cost to a build-time operation that nobody in a live server is paying for.

Which Properties the Asset Service Actually Reads

The announcement lists four. Read them carefully, because two of the four are not what most people expect them to be:
  • Code: Select all

    text
    (string): the text you intend to have voiced.
  • Code: Select all

    voiceId
    (string): the ID describing the speaker.
  • Code: Select all

    pitch
    (number): defaults to 0, valid range from -12.0 to 12.0.
  • Code: Select all

    speed
    (number): defaults to 1, valid range from 0.5 to 2.0.
The trap is in the names. On the

Code: Select all

AudioTextToSpeech
instance itself, the playback-rate property is

Code: Select all

Speed
, while

Code: Select all

PlaybackSpeed
is a different property with a range of 0 to 20 that multiplies how fast the audio plays back and therefore changes its perceived pitch. For asset generation only

Code: Select all

Speed
is read, and

Code: Select all

PlaybackSpeed
is not among the fields the service considers. If you have been tuning a voice by dragging

Code: Select all

PlaybackSpeed
in the Properties window, that tuning does not survive the conversion.

The Voice List, and How AutoLocalize Interacts With It

Code: Select all

VoiceId
takes a string, so the value goes in as a quoted number rather than a bare one. The full list of artificial voices, as documented:
  • 1 British male, 2 British female
  • 3 United States male #1, 4 United States female #1
  • 5 United States male #2, 6 United States female #2
  • 7 Australian male, 8 Australian female
  • 9 Retro voice #1, 10 Retro voice #2
  • 11 Host voice, added in August 2026 alongside the new languages
  • 101 and 102 Spanish male and female
  • 201 and 202 German male and female
  • 301 and 302 Italian male and female
  • 401 and 402 French male and female
  • 501 and 502 Chinese (Mandarin) male and female
  • 601 and 602 Hindi male and female
  • 701 and 702 Japanese male and female
  • 801 and 802 Arabic male and female
  • 901 and 902 Korean male and female
  • 1001 and 1002 Portuguese male and female

Code: Select all

AutoLocalize
defaults to

Code: Select all

true
. When it is on, Roblox translates the text into the player's language and routes it to a voice appropriate for that language, matching the register of the voice you picked. So if you set a female English voice ID and the player is on a Spanish client, the system moves to a female Spanish voice. That is the behaviour you get for free, and it is also why the voice you baked into an asset is a fixed choice: the asset stores one recording in one language, and no amount of

Code: Select all

AutoLocalize
on the source object rewrites it after the fact.

The automatic translation path covers eleven languages: Arabic, Chinese (Mandarin), English, French, German, Hindi, Italian, Japanese, Korean, Portuguese and Spanish. Speech-to-text, the sibling feature, supports a wider set, including Indonesian, Polish, Russian, Thai, Turkish, Vietnamese and both Simplified and Traditional Chinese.

The documentation recommends reading

Code: Select all

Player.LocaleId
to pick a voice ID that matches the player's language. That is sensible for live calls. For baked assets the equivalent is to generate one asset per language and select at runtime.

Step by Step: Baking a Voice Line Into an Asset
  1. Enable the

    Code: Select all

    CreateAssetAsync
    Luau API beta feature in Studio. It is not on by default, and Roblox states that it will not be auto-enabled even for accounts enrolled in automatic beta enrollment.
  2. Create a local plugin, or call the API from the command bar. The API does not work from plugins acquired from the Creator Store, because untrusted code uploading assets on your behalf is a real risk.
  3. Insert an

    Code: Select all

    AudioTextToSpeech
    object under SoundService and set

    Code: Select all

    Text
    ,

    Code: Select all

    VoiceId
    ,

    Code: Select all

    Pitch
    and

    Code: Select all

    Speed
    .
  4. Call

    Code: Select all

    AssetService:CreateAssetAsync(ttsObject, Enum.AssetType.Audio, {})
    . Pass an empty options table for now, since no options are supported for this asset type.
  5. Read the result. A successful call returns

    Code: Select all

    Enum.CreateAssetResult.Success
    plus the new asset ID as a number. A failure returns the result enum plus a string error.
  6. Wire the returned asset ID into an

    Code: Select all

    AudioPlayer
    and connect it to an

    Code: Select all

    AudioDeviceOutput
    with a

    Code: Select all

    Wire
    , exactly as you would for an audio file you imported.
  7. Roblox also ships a sample script in the announcement thread that takes a table of voice lines with their speed, pitch and ID and generates the ones that need it. Worth using if you have more than a handful of lines.
A note on scale: the original

Code: Select all

CreateAssetAsync
beta was limited to 30 requests per minute. Batch your generation and expect to wait rather than firing hundreds of calls in a loop.

What You Still Cannot Do

The announcement is short on purpose, and the gaps are the part people hit first:
  • No names or descriptions. You cannot attach metadata to the uploaded asset.
  • No creator ID. You cannot specify who the asset belongs to, which matters for group-owned projects.
  • Automatic naming. Every generated asset is called

    Code: Select all

    TTS_Asset_1234567890
    , where the number is the asset ID. If you generate fifty lines, you get fifty identically-prefixed entries in your inventory and you will be renaming them by hand or not at all.
  • No in-experience use. The API is for creator tooling, so you cannot generate speech on the fly from a live server or from a client.
  • No options table. Unlike the mesh and image paths, there is nothing to configure in the request parameters for audio.
That naming issue is the one that will actually cost you time. It is also the reason the sample script exists.

Where This Fits Against the Other Audio Work
  • Text-to-speech, live: one request per playback, counted against the per-minute budget, limited to 300 characters per call.
  • Text-to-speech, baked: one asset per line, generated in Studio, no per-minute cost at runtime, but a fixed voice and language per asset.
  • Speech-to-text: a separate feature entirely, converting a player's microphone input into text. It needs

    Code: Select all

    VoiceChatService.UseAudioApi
    enabled and an

    Code: Select all

    AudioDeviceInput
    wired to an

    Code: Select all

    AudioSpeechToText
    object.
  • Text generation: the third leg of the set, which is what makes freeform NPC conversation possible when you combine all three.
Roblox is explicit that text-to-speech should not be used to let users have freeform real-time conversations with each other. Conversations with NPCs are fine.

Moderation Responsibility Depends on the API You Use

This is the detail most easily missed, and it changes who gets punished for bad output. Roblox splits it by API:
  • For the real-time

    Code: Select all

    AudioTextToSpeech
    API, you are not held responsible for potentially violative audio output unless you intentionally program the system to generate violating content.
  • For the asset generation path, the generated audio is saved to your inventory, and any moderation action is taken against your account as the asset owner. Roblox directly recommends against letting players input text for audio asset generation because of this.
  • All text and audio output is filtered before processing, and violative input returns an error with no audio generated.
That second bullet is the practical warning: do not build a feature where a player types a string and a speech asset gets created from it. If you want player-driven dialogue, keep it on the real-time API.

FAQ

Is text-to-speech free to use?
The baseline utilisation is free, with rate limits and character limits in place. Roblox also integrates it with Extended Services, so you can purchase additional usage if the free tier is not enough for your experience.

Can I call CreateAssetAsync from inside my game?
No. The API can only be used in locally loaded plugins and in Open Cloud Luau execution. It is not available in-experience, and Roblox says these APIs are explicitly not meant for that context.

Does using TTS change my content maturity rating?
No. Roblox states a rating is not impacted solely because you include an AI component, including text-to-speech. Only an experience where users can have unlimited conversations with an AI model receives the Restricted rating.

Why does my baked asset sound different from the live version?
Because

Code: Select all

PlaybackSpeed
is not one of the four properties the asset service reads. Only

Code: Select all

text
,

Code: Select all

voiceId
,

Code: Select all

pitch
and

Code: Select all

speed
are carried across. If you were tuning the voice through playback speed, bake again after moving that tuning into

Code: Select all

Pitch
and

Code: Select all

Speed
.

Can I name my generated speech assets?
Not yet. Roblox lists the lack of name and description support as a current limitation, so every asset comes out named

Code: Select all

TTS_Asset_
plus its ID.

Do I need to handle multiple languages separately?
For baked assets, yes.

Code: Select all

AutoLocalize
applies to live synthesis and picks the voice to match the player's language. An asset holds one recording in one language, so multilingual games generate one asset per language and select at runtime.

Sources