Skip to content

Google Lyria

Lyria 3 is Google’s music model exposed through @effect-uai/google. Sync generation only. streamGeneration falls back to a single chunk; streamGenerationFrom (bidi session updates) is a compile-time error against this Layer until Lyria RealTime lands.

For language-model use of Gemini see Providers / Gemini. For speech (TTS / STT) see Speech / Gemini. This page covers music only.

Install

Terminal window
pnpm add @effect-uai/core @effect-uai/google effect

Layer

import { Config, Effect, Layer } from "effect"
import { FetchHttpClient } from "effect/unstable/http"
import { layer as lyriaLayer } from "@effect-uai/google/LyriaGenerator"
const lyria = Layer.unwrap(
Effect.gen(function* () {
const apiKey = yield* Config.redacted("GOOGLE_API_KEY")
return lyriaLayer({ apiKey })
}),
)
const mainLayer = lyria.pipe(Layer.provide(FetchHttpClient.layer))

lyriaLayer registers two service tags from one underlying implementation:

  • LyriaGenerator: the typed tag. Yield this for autocomplete on model: LyriaModel.
  • MusicGenerator: the generic tag. Yield this in provider-portable code.

Does not register MusicInteractiveSession: calling streamGenerationFrom is a compile error.

Models

ModelDurationOutputNotes
lyria-3-clip-previewFixed 30 sMP3Default; fastest
lyria-3-pro-previewUp to ~2 minMP3 or WAVSlower, higher quality

LyriaModel is a literal union with (string & {}) tail: pass any string for models the SDK hasn’t been updated for.

Request shape

type LyriaGenerateRequest = {
readonly model: LyriaModel
readonly prompt: string // single string; forwarded verbatim
readonly lyrics?: string // dropped with a logged warning
readonly duration?: Duration.Duration // dropped with a logged warning
readonly seed?: number // dropped with a logged warning
readonly outputFormat?: AudioFormat // mp3 or wav (pro only)
}

Lyria 3 sync’s wire (generateContent) has no structured field for lyrics, duration, or seed. The 0.7 adapter does not splice those into your prompt text on your behalf. Prompt construction is the developer’s job. Setting them on the request logs a structured CapabilityWarning and proceeds with the prompt unchanged. If you want vocals to follow specific lyrics, embed them in your prompt with [Verse] / [Chorus] tags.

Provider-typed extras that exist on the Lyria RealTime surface (weighted prompts, BPM as a structured enum, scale enum, density / brightness / mute-stems) will land with that adapter under its own service tag.

Output

type MusicResult = {
readonly audio: AudioBlob
readonly provider?: "lyria"
readonly lyrics?: string // text part when Lyria returned one
readonly watermark?: Watermark // always "synthid"
}

Returned as GenerateResult with one variant (Lyria 3 sync returns exactly one track per call; primary === variants[0]). Every Lyria output carries a SynthID watermark in the audio. The adapter surfaces it via result.primary.watermark so downstream code can verify or attribute provenance.

Wire / auth notes

Sync endpoint: POST https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent with generationConfig.responseModalities: ["AUDIO"]. Response is base64 MP3 (or WAV for lyria-3-pro-preview with audio/wav requested).

Same GOOGLE_API_KEY as the language-model and speech Gemini layers.

Errors

Standard HTTP → AiError mapping. Lyria-specific:

Request shapeError
WAV requested on lyria-3-clip-previewAiError.Unsupported (clip is MP3-only)
Output container ≠ mp3 / wavAiError.Unsupported
Empty audio part in the responseAiError.GenerationFailed (likely a prompt-filter rejection: Lyria filters artist names and copyrighted lyrics)
streamGenerationFrom callCompile-time error (no marker)

See also