Supported models
GAS describes more musical intent than any one model accepts. A connector declares how it handles each part of the language, and a valid score can load with warnings when the model will approximate or ignore some of it. The intent stays in the session either way.
Lyria RealTime, Google’s real-time music model, is the only connector that ships today. It is the /lyria subpath of @luna-estelar/gas. To add another model, see the connector interface.
What Lyria supports
The connector reports these support levels. This table is checked against the published package:
| Keyword | Support |
|---|---|
flavor |
supported |
tempo |
supported |
timbre |
supported |
key |
approximated |
level |
approximated |
time_signature |
unsupported |
notes |
unsupported |
motif |
unsupported |
- Supported: the connector carries the intent to the model as written.
- Approximated: the connector translates the intent with some loss, and the session warns.
- Unsupported: the session warns, and the model is not asked to act on that intent.
These levels describe what the connector sends, not what the generated audio will contain. Direct Lyria with flavor, timbre, and tempo, and treat key and track level as suggestions.
A score in 3/4 still compiles, and GAS’s clock still counts three beats to a bar, but Lyria is not told to play in 3/4. notes and motif compile too, but Lyria does not play their pitches. The session reports each of these as a warning when the score loads.
How Lyria reads a score
Lyria takes a set of weighted text prompts rather than a score, so the connector rebuilds those prompts from the session’s effective state whenever it changes.
- Tracks become prompts. Each active track becomes one prompt made from its description (or its name, if it has none), its
flavor, and itstimbre. A track that is stopped, or haslevel 0, contributes no prompt. Tracks that produce identical text share one prompt, with their weights added together. - Level sets prompt weight. A track’s
levelscales its prompt’s weight, with a small floor so a quiet track still colours the mix. This is why tracklevelis approximated: it changes the balance of influence, not the volume of a separate part. - Overall flavor is its own prompt. A document-level
flavoris sent as a separate prompt alongside the track prompts. With theper-trackstrategy, it is folded into each track’s prompt instead. - Nothing active means silence. With no active tracks there are no prompts, and the connector pauses the model until a track starts.
- Changes crossfade. When prompts change, the connector blends from the old set to the new one over about 1.5 seconds rather than switching at once.
Tempo
Lyria counts tempo in quarter notes per minute, as a whole number from 60 to 200. A GAS tempo counts the beats of the time signature, so the connector converts it with tempo × 4 / beatUnit. For example, tempo 120 in 6/8 is sent as 60.
The result is rounded to a whole number and clamped to 60–200. If the converted tempo is outside that range, the connector warns once per run for that tempo, with the code lyria-tempo-clamped.
Key
Lyria has twelve scale settings. Each pairs a major key with its relative minor, so key "C major" and key "A minor" select the same setting. The connector maps a plain major or minor key, such as "F# minor" or "Db major", to its matching setting. Accidentals must be a single # or b.
Any other key, such as a mode, a double accidental, or one written with ♯ or ♭, is sent as prompt text instead, alongside the overall flavor.
Tempo and key changes restart the model’s context
Lyria treats tempo and scale as part of its generation context, not its prompts. When a change alters the converted tempo or the scale, the connector sends the new settings and resets that context. Expect a more abrupt shift than a flavor or timbre change, which crossfades.
Generation settings
Lyria has settings of its own, outside the language. Read the current values with session.renderer.getConnectorConfig(), and change them with updateConnectorConfig(patch) while the session is stopped. LYRIA_CONFIG_SCHEMA describes the full surface, and validateLyriaConfig reports problems by JSON Pointer.
| Setting | Default | Effect |
|---|---|---|
prompt.strategy |
global-plus-tracks |
Send overall flavor as its own prompt, or fold it into each track’s (per-track) |
prompt.trackWeight |
1 | Base weight of a track prompt, before level scales it |
prompt.globalWeight |
0.8 | Weight of the separate overall-flavor prompt |
prompt.minimumPositiveWeight |
0.05 | Lowest weight an active, non-silent track can have |
prompt.transitionDurationMs |
1500 | How long a prompt change crossfades |
prompt.transitionSteps |
3 | How many prompt sends make up a crossfade |
generation.temperature |
1.1 | 0–3; higher values wander further from the prompts |
generation.guidance |
4 | 0–6; how firmly generation follows the prompts |
generation.topK |
40 | 1–1000; how many candidates each step samples from |
generation.mode |
quality |
quality for polish, diversity for variety |
generation.density |
unset | 0–1, from sparse to busy |
generation.brightness |
unset | 0–1, from dark to bright |
generation.muteBass, muteDrums, onlyBassAndDrums |
unset | Hold back the bass or drums, or generate only those |
generation.seed |
unset | Ask Lyria for a repeatable take |
seed is a Lyria setting, not something GAS guarantees. It does not carry over to other models, and the same score can still sound different on each run.
Audio
Lyria streams 48 kHz, 16-bit stereo PCM. It generates ahead of playback, so a change can take a few moments to be heard.
Access and keys
The connector uses the experimental lyria-realtime-exp model. Access, and any charges, depend on the Google account and project.
createLyriaConnector() takes no arguments. Its open settings are { apiKey, endpoint? }:
apiKeyis a Gemini API key for a project with access to Lyria RealTime. The connector never stores it.endpointis an optional HTTPS origin that speaks the Lyria WebSocket protocol, used instead of Google’s. The connector refuses an endpoint with a path, query string, fragment, or user information.
The browser’s WebSocket API cannot set arbitrary headers, so the key travels in the connection URL’s query string. Keep credential-bearing URLs out of logs and application messages, and never ship a provider secret in your JavaScript.
Relays and shared audio
A relay is a server you run at your own endpoint. The browser connects with a public placeholder key, and the relay swaps in the real provider secret before forwarding the connection, so the secret never reaches the browser.
This website uses a relay for Shared audio in its demos. Shared audio is available only while the relay is switched on and has capacity and budget; the dialog says when it is busy or off. Your own key connects your browser straight to Google, and the key stays in the page rather than going through the site’s relay. Shared audio is for trying GAS; an application built on GAS needs its own provider access, either a user’s key or its own relay.
Connection failures
The connector classifies WebSocket close codes and passes the raw code through as closeCode:
| Close code | reason |
Retryable |
|---|---|---|
| 1007 or 1008, before setup completes | auth |
No |
| 1002 or 1011 | provider |
Yes |
| Anything else | network |
Yes |
The connector treats 1007 and 1008 before setup as a malformed or rejected key. Codes from 4000 to 4999 belong to whoever operates the endpoint, such as your relay, so the connector reports them as network failures and leaves their meaning to your application. Troubleshooting covers what to do with each.