VoiceplayMusicstable

Play music

Plays hold/wait music to the caller — pick a track from the Prompts & music library (the system library or your own). Built for hold experiences: start at…

What it does

Plays hold/wait music to the caller. The track comes from the Prompts & music library — a system track or music your team uploaded. Unlike Play audio (a plain looped clip) it's built for hold experiences:

  • Start at an offset (seconds) into the track.
  • Play for a set number of seconds, then continue down the Finished playing path. Leave it blank to play the track once through.
  • Optionally let the caller press a key to skip, which routes a Key pressed branch.
  • Save the stop position to a variable so a later Play music step can pick up right where the caller left off.

When to use it

  • A resumable music bed split across several steps — save the offset on one step, feed it into Start at on the next to resume seamlessly.
  • Timed hold music: "play 30 seconds, then re-check the queue."
  • A "press any key to skip the intro" experience before a menu.

For a one-off clip or a simple Forever loop, use Play audio. For a spoken prompt or TTS, use Play prompt or audio (say).

Configuration

Plays hold/wait music to the caller — pick a track from the Prompts & music library (the system library or your own). Built for hold experiences: start at an offset, play for a set number of seconds, and optionally let the caller press a key to skip ahead. Save the stop position to a variable and feed it back into "Start at" on a later Play music step to pick up right where the caller left off. (To loop a clip or play a one-off one, use "Play audio"; for spoken prompts or TTS, use "Play prompt or audio".)

FieldLabelTypeRequiredDefaultNotes
musicMusicaudioRequired—Pick a music track from the Prompts & music library: a system track or one your team uploaded. A {{config.x}} / {{vars.x}} template that holds a library reference also works.
offsetSecsStart at (seconds)numberOptional0Where in the track to begin. Accepts a {{vars.x}} template so you can resume from a saved stop position. If it lands past the end of the track, playback restarts from the beginning.
playSecsPlay for (seconds)numberOptional30How long to play before the flow moves on down the "Finished playing" path. Leave blank to play the track once through to the end.
interruptOnDtmfLet the caller press a key to skipbooleanOptionalfalseWhen on, a keypad press during playback stops the music and routes the "Key pressed" branch. When off, keypresses are ignored and the music plays until the play time elapses (or the call is bridged / hangs up).
validDigitsKeys that interrupttextOptional1234567890*#Which keys are allowed to interrupt. Leave blank to accept any key. Only used when "Let the caller press a key to skip" is on.
saveOffsetVarSave stop position to variabletextOptionalmusicPosOptional. When this step ends — whether the play time elapsed or the caller pressed a key — the seconds-offset where playback stopped is written to this variable. Reference it later as {{vars.musicPos}} and drop it into "Start at" on another Play music step to resume.

Outgoing events: call.playback.ended, call.playback.dtmf, call.hangup

Examples

System hold music for 30 seconds

{
  "id": "hold-music",
  "type": "playMusic",
  "config": { "music": "sys:music/default-hold", "playSecs": 30 },
  "on": { "call.playback.ended": "check-queue", "call.hangup": "end" }
}

Resume where the caller left off

Two steps that share a position variable. The first plays 20s from the start and saves the stop offset to musicPos; the second resumes from there. {{vars.musicPos}} resolves before playback.

[
  {
    "id": "music-a",
    "type": "playMusic",
    "config": { "music": "sys:music/default-hold", "offsetSecs": 0, "playSecs": 20, "saveOffsetVar": "musicPos" },
    "on": { "call.playback.ended": "announce" }
  },
  {
    "id": "music-b",
    "type": "playMusic",
    "config": { "music": "sys:music/default-hold", "offsetSecs": "{{vars.musicPos}}", "playSecs": 20, "saveOffsetVar": "musicPos" },
    "on": { "call.playback.ended": "menu" }
  }
]

Press a key to skip the intro

With Let the caller press a key to skip on, a keypress stops the music and routes the Key pressed branch (call.playback.dtmf); otherwise it plays to the play-time and routes Finished playing (call.playback.ended). The key the caller pressed is available downstream as {{vars.gatheredDigits}}.

{
  "id": "intro",
  "type": "playMusic",
  "config": { "music": "sys:music/default-hold", "playSecs": 15, "interruptOnDtmf": true },
  "on": { "call.playback.dtmf": "menu", "call.playback.ended": "menu", "call.hangup": "end" }
}

Gotchas

  • Offsets are tracked in seconds. Every library track plays as 8 kHz mono, so the seconds ↔ samples conversion is exact.
  • Offset wrap works for every library track. "If Start at is past the end of the track, start from the beginning" uses the track length the library records for each track.
  • The saved offset on a key-press is an estimate. When key-interrupt is on, the platform reports which key was pressed but not where playback stopped, so the saved position is derived from elapsed time (accurate to within processing latency). The Finished playing path and the no-interrupt path save an exact position.
  • "Play for" longer than the track plays once to the end. There's no auto-loop for the timing fields — a 30s play time on a 20s clip plays 20s. To loop a clip, use Play audio with a loop count.
  • Key-interrupt off means keys are ignored. The music plays until the play-time elapses, the call is bridged (an agent answers), or the caller hangs up.
  • music is a library reference, never a URL. It holds asset:<uuid>, sys:music/<slug> or a {{…}} template that renders to one. A raw URL fails publish validation. If the track was deleted or disabled, the call hears the org's default hold music, then the system default.

See also