API and Hooks
Wiki updated as of 1.1.1 (Oct 2026)The API is available as game.modules.get('minstrel').api and as the global MINSTREL. It is created during ready and passed to the minstrel.ready hook.
Hooks.once('minstrel.ready', (api) => { api.runtime.apply('mood-id');});Mood playback and cue resolution run on the active GM’s client. runtime calls that change playback are forwarded to the active GM from another GM’s client and do nothing on a player’s client. cues.refresh does nothing off the active GM’s client, and soundboard.play does nothing on a player’s client. cues.suppress, video.play, and video.stop save world settings, so the calling user needs permission to modify world settings.
Console
Section titled “Console”| Function | Description |
|---|---|
MINSTREL.openConsole() | Opens or closes the Minstrel console. |
| Function | Returns | Description |
|---|---|---|
MINSTREL.moods.list() | object[] | Every saved mood. |
MINSTREL.moods.get(id) | object | null | The saved mood with this id. |
Runtime
Section titled “Runtime”| Function | Returns | Description |
|---|---|---|
MINSTREL.runtime.apply(id) | Promise | Applies the mood with this id. |
MINSTREL.runtime.stop(id) | Promise | Stops the mood with this id. |
MINSTREL.runtime.stopAll() | Promise | Stops every active mood. |
MINSTREL.runtime.stopEverything() | Promise | Stops every mood, playlist, pad, video, and Syrinscape sound. |
MINSTREL.runtime.skip(moodId, entryId) | Promise | Ends a playing entry and starts any entry chained to it. |
MINSTREL.runtime.stopEntry(moodId, entryId) | Promise | Stops a playing entry without starting chained entries. |
MINSTREL.runtime.setEntryGain(moodId, entryId, gain) | void | Sets an active entry’s volume from 0 to 1 for every client. |
MINSTREL.runtime.active() | object[] | Records for the active moods: { moodId, origin, appliedAt, entries }. |
MINSTREL.runtime.moodDef(id) | object | null | A mood definition, including the ones built for playlist and track cues. |
MINSTREL.runtime.isSynthetic(id) | boolean | Whether the id belongs to a mood built for a playlist or track cue. |
MINSTREL.runtime.cueSlot() | object | null | The cue currently driving playback. |
MINSTREL.runtime.releaseCue() | Promise | Releases the current cue and stops the moods only it started. |
MINSTREL.runtime.padDue(moodId, padId) | number | null | Server time in milliseconds when a mood’s scheduled pad next fires, on the active GM’s client. |
See Moods.
Soundboard
Section titled “Soundboard”| Function | Returns | Description |
|---|---|---|
MINSTREL.soundboard.list() | object[] | Every saved soundboard pad. |
MINSTREL.soundboard.get(id) | object | null | The pad with this id. |
MINSTREL.soundboard.play(id, { moodId }) | Promise | Plays the pad with this id. moodId ties the play to a mood. |
MINSTREL.soundboard.categories() | object[] | Every pad category, in board order. |
See Soundboard.
A cue object holds a moodId, or a playlistId with an optional soundId. It can also carry a priority and a replace mode: same, all, cue, or none.
| Function | Returns | Description |
|---|---|---|
MINSTREL.cues.read(doc, context) | object | null | The cue stored on a Scene, Actor, or Token for a context key. |
MINSTREL.cues.write(doc, context, cue) | Promise | Stores a cue on the document and refreshes. Pass null to clear it. |
MINSTREL.cues.active() | object | null | The candidate chosen by the last refresh. |
MINSTREL.cues.refresh() | Promise | Re-runs cue resolution and applies the winning cue. |
MINSTREL.cues.candidates() | object[] | Every cue that could play for the current scene and combat. |
MINSTREL.cues.resolve() | object | null | The candidate that would win right now, without changing playback. |
MINSTREL.cues.suppress(context, on = true) | Promise | Silences a context key, or restores it when on is false. |
MINSTREL.cues.isSuppressed(context) | boolean | Whether a context key is silenced. |
A candidate has the shape { context, doc, type, cue, priority }. The built-in context keys are area and combat. See Music Cues.
Sections
Section titled “Sections”registerSection
Section titled “registerSection”const handle = MINSTREL.registerSection({ id: 'my-module.weather', label: 'Weather', priority: 10, types: ['Scene'], predicate: () => game.myModule.isStormy, contextKey: 'weather', hint: 'Plays while a storm is active.'});Registered sections appear on the console’s Other tab and compete with the built-in sections during cue resolution. Registering a section refreshes cues.
| Property | Type | Description |
|---|---|---|
id | string | Required. Unique registry id. |
label | string | Section name shown in the console. |
priority | number | Default priority for cues in this section. Defaults to 0. |
types | string[] | Document types the section applies to: Scene, Actor, Token, DefaultMusic. |
predicate | Function | Called with no arguments on each refresh. A falsy return or a throw keeps the section silent. |
contextKey | string | Key used for cue flags and suppression. Defaults to id. Cannot be area or combat. |
hint | string | Text describing when the section plays. |
Minstrel does not watch your predicate’s state. Call handle.refresh() when that state changes.
An invalid definition is logged and the call returns null. A successful call returns a handle.
| Member | Description |
|---|---|
id | The registered id. |
contextKey | The resolved context key. |
unregister() | Removes the section and refreshes cues. |
refresh() | Re-runs cue resolution. |
Registry functions
Section titled “Registry functions”| Function | Returns | Description |
|---|---|---|
MINSTREL.unregisterSection(id) | boolean | Removes a registered section. Does not refresh cues. |
MINSTREL.getRegisteredSections() | object[] | Every registered section definition. |
Ducking
Section titled “Ducking”MINSTREL.duck('music', 0.3, 4000);Lowers a core audio channel on every connected client, holds it for holdMs, then ramps it back. The arguments are channel (music, environment, or interface), factor (multiplies the channel volume), and holdMs. All three are optional and default to music, 0.3, and 4000. The ramp time comes from the Ducking Fade setting.
| Function | Returns | Description |
|---|---|---|
MINSTREL.video.open({ detached }) | Promise | Opens the video window. Pass detached: true to open it in its own window. |
MINSTREL.video.play(url, { at, title }) | string | null | Plays a YouTube link or video id for everyone, starting at at seconds. Returns the video id. |
MINSTREL.video.stop() | Promise | Stops the shared video. |
MINSTREL.video.state() | object | null | The shared video state: { id, title, playing, time, at }. |
See Video.
Syrinscape
Section titled “Syrinscape”MINSTREL.syrinscape exposes the integration module.
| Function | Description |
|---|---|
syrinscapeEnabled() | Whether the integration is on and a token is set. |
listSoundsets() | Resolves to the soundsets in your Syrinscape library. |
listMoods(uuid) | Resolves to the moods in a soundset. |
listElements(uuid) | Resolves to the elements in a soundset. |
play({ kind, id }, label) | Plays a mood or element. kind is mood or element. |
stop({ kind, id }) | Stops a mood or element. |
stopAll() | Stops all Syrinscape audio. |
setElementVolume(id, volume) | Sets an element’s volume from 0 to 1. |
nowPlaying() | The playing Syrinscape mood as { id, title }, or null. |
nowPlayingElements() | The playing elements as { id, name, type, icon, volume }. |
sessionId() | The joined Syrinscape session id, or null. |
See Syrinscape.
| Hook | Arguments | Fires |
|---|---|---|
minstrel.ready | api | On every client at the end of Minstrel’s ready setup. |
minstrel.moodApplied | mood | On the active GM’s client after a mood is applied. |
minstrel.moodStopped | mood | On the active GM’s client after a mood is stopped. |
minstrel.entryState | state | On every client when the active mood state changes. |
minstrel.padPlayed | pad | On the client that played a soundboard pad. |
minstrel.cueChanged | { cue, mood } | On the active GM’s client after a cue refresh switches playback. |
minstrel.suppressionChanged | Set<string> | On the client that changed suppression. Passes the suppressed context keys. |
minstrel.syrinscapeChanged | { id, title } | null | On clients running the Syrinscape player when the playing mood or its elements change. |
minstrel.padChanged | none | On every client, when a soundboard pad’s audio starts or stops playing. |
minstrel.nowPlayingRotated | none | On a client, when the user steps to another playing source. |
When a cue targets a playlist or track, moodApplied, moodStopped, and cueChanged receive a mood object built from that playlist.
Hooks.call('minstrel.openConsole') opens or closes the console. Pass { tab } to open it on a tab instead.
Glyph actions
Section titled “Glyph actions”With Glyph active, three Minstrel actions are available: Set Mood (Minstrel), Play Soundboard Pad (Minstrel), and Duck Audio (Minstrel).