FolioTier 1
music
Control the music channel - play or stop a background track.
The music construct drives the background score - the single track that sets the emotional register of a scene. Reach for it whenever you want a new cue underneath the dialogue, want silence, or want to nudge the overall music level without interrupting what's already playing.
Because a scene usually carries one score at a time, music defaults to a dedicated channel and swapping tracks with play simply replaces whatever was there. If you need a second layer running alongside it, such as a low ambience under a melodic theme, route one of the two through on to a different channel instead of trying to stack them both on music.
Stop takes no reference - if you're naming a track, you want play. Use volume when you want to turn the music down for a hushed scene or back up afterward without touching the cue itself; the track keeps playing through the change.
Loop and once only matter when you're being explicit about repeat behavior or routing to a custom channel that doesn't loop by default - on the ordinary music channel, looping is already the default, so most play lines need neither. Muted is for save-load correctness: it lets the script state reflect that a track is 'playing' without anyone hearing it, and if you also pass volume(), muted overrides it.
Fade behaves differently depending on which action it rides with - fade-in on play, fade-out on stop - so a single with fade(2) clause reads correctly either way. Leave it off when you want a hard cut or an instant start; add fade(0) if you want that abruptness to be unambiguous to the next person reading the script.
Parameters
| Parameter | Kind | Required | Default | Notes |
|---|---|---|---|---|
| action | identifier | yes | - | One of `play`, `stop`, or `volume`. `play` starts a new track immediately; `stop` stops the music channel without starting anything new; `volume <0-100>` sets the channel volume from that point on without touching playback (Ren'Py's `renpy.music.set_volume`). |
| reference | identifier | no | - | Audio reference registered in the project's audio table. Required for `play`; omit for `stop` (a `music stop` with a reference is a parse error). Quoted form is accepted when the reference contains characters outside the identifier pattern. |
| once | identifier | no | - | Optional `play` modifier - `music play stinger once` plays the track a single time without looping (Ren'Py's `noloop`). Omit for the default looping behavior on the music channel. Exclusive with `loop`. |
| loop | identifier | no | - | Optional `play` modifier - `music play theme loop` pins looping explicitly (Ren'Py's `play music "theme.ogg" loop`). The `music` / `bgm` channels already loop by default, so on a music line it changes nothing; it exists so an explicit Ren'Py `loop` round-trips honestly and so a music line routed `on` a custom one-shot channel can still repeat. Same slot as `once`; the two are exclusive. In Studio the audio inspector's Loop control (Channel default / Loop / Play once) writes it. |
| volume | number | no | - | Optional `play` modifier - `music play theme volume(60)` sets the per-cue volume to 60%. Accepts 0-100; multiplies with the listener's master + music-channel sliders. Omit to use the channel default. |
| muted | identifier | no | - | Optional `play` flag - `music play theme muted` plays the cue at zero volume. Useful when a creator wants the channel state to follow the script (save-load behavior) without audible playback. Combines with `volume()`; mute wins. |
| fade | number | no | - | Optional `with fade(N)` clause, on both actions. On `play` it ramps the track up from silence over N seconds (Ren'Py's `fadein N`); on `stop` it fades the music gain down over N seconds before releasing the channel (Ren'Py's `fadeout N`). It rides last, after any `on <channel>`. Bare `play` starts at full volume and bare `stop` hard-cuts; `fade(0)` spells either one explicitly. |
| level | number | no | - | The `volume` action's argument - `music volume 40` sets the music channel to 40% from here on. Required for `volume`, bare number 0-100 (out-of-range values clamp with a warning). The playing track keeps playing at the new level. |
| on | identifier | no | music | Optional channel override. `music` lines default to the `music` channel - pass `on <channel>` to route to a different one (rare; usually for layered background ambiences on a second channel). The channel is a single identifier (letters, digits, `. - _`); it rides after the cue and any `once` / `loop` / `volume()` / `muted` modifiers, and before any `with fade(...)` clause. |
Canonical example
music play kitchen-theme
music play stinger once
music play tense-bed volume(60)
music play dread-bed with fade(2)
music volume 40
music stop with fade(1)play music "kitchen-theme.ogg"
play music "stinger.ogg" noloop
play music "tense-bed.ogg"
play music "dread-bed.ogg" fadein 2
$ renpy.music.set_volume(0.4)
stop music fadeout 1music is the background-track verb. It takes an action keyword
(play, stop, volume) followed by the audio reference for play,
or nothing for stop. Folio folds Ren'Py's play music/stop music
pair into a single verb with three actions so the Story Map can
render music control as one block type rather than two.
Notes
The channel defaults to music. Most projects never override it -
the on <channel> clause exists for the unusual cases (a layered
ambient bed on a second channel while music is also playing). The
importer's deterministic pass maps Ren'Py's play audio "..." channel "<name>" shape onto this clause.
Ren'Py's queue music was retired: at runtime it behaved identically
to play, so the importer lowers both to music play and the
authoring surfaces only offer play and stop.
Across scenes and episodes
Music keeps playing across scenes until you stop it or the episode
ends. A play is not tied to the scene it sits in: the track carries
through scene changes, jumps, and calls, exactly as in Ren'Py, and
only a music stop, a new music play on the channel, or the end of
the episode silences it. At the episode's end every track still
playing fades out (the length is set per episode; zero cuts). In
Studio the timeline shows a carried-in row above a scene that opens
with a track already sounding, and a play's inspector card says where
it will stop.
Modifiers
Five optional modifiers cover the common Ren'Py audio idioms plus per-cue volume control:
once- appended toplay. Plays the track a single time without looping. Mirrors Ren'Pyplay music "stinger.ogg" noloop. Useful for one-shot stinger SFX layered on the music channel that should stop on their own rather than loop until the nextmusic stop. Exclusive withloop.loop- appended toplay. Pins looping explicitly (Ren'Pyplay music "..." loop). Themusicchannel already loops by default, so it changes nothing there; it round-trips an author's explicitloophonestly and lets a music line routedona one-shot channel repeat. Same slot asonce; a line with both is an error. In Studio the audio inspector's Loop control (Channel default / Loop / Play once) writes it.volume(N)- appended toplay(whereNis 0-100, integer or decimal). Sets the per-cue volume for this track only - multiplies with the listener's master volume and music-channel slider. Omit to use the channel default (100% × the music channel's built-in 0.72× attenuation). Has no Ren'Py equivalent.muted- appended toplay. Plays the cue at zero volume while keeping the channel state in sync with the script (so a latermusic stopstill has something to stop, saves round-trip cleanly, etc.). Combines withvolume(); mute wins.with fade(N)- appended toplayorstop(whereNis seconds, integer or decimal). Onplayit ramps the track up from silence (Ren'Pyfadein N); onstopit fades the music gain down before releasing the channel (Ren'Pyfadeout N). Bareplaystarts at full volume and baremusic stophard-cuts.
The modifiers compose with on <channel> and conditional if
tails. Order: <action> <ref> [once|loop] [volume(N)] [muted] [on <channel>] [if <cond>]
and stop [on <channel>] [with fade(N)] [if <cond>].