-
-
Notifications
You must be signed in to change notification settings - Fork 60
Create Audio API
Audience: wallpaper creators. This page documents the audio‑reactive JavaScript feed: how to subscribe to it, the FFT spectrum array used for visualizers, and the now‑playing media‑session metadata that accompanies it. The audio feed is delivered only to Web wallpapers running on the WebView or CefSharp engines. To enable it you declare the SystemAudio hook in SucroseCompatible.json — see Create JS Bridge.
- Enabling the audio feed
- Subscribing in JavaScript
- The FFT spectrum (
obj.Data) - Now‑playing metadata fields
- Timing fields
- Visualizer example
- Notes and gotchas
- See also
Add the SystemAudio hook to your wallpaper's SucroseCompatible.json:
{ "SystemAudio": "SucroseAudioData({0});" }When this hook is non‑empty, the engine enables the Backgroundog audio channel for this wallpaper (AudioRequired = true), starts the live‑data transport, and calls your SucroseAudioData function each time new audio data arrives. The data is captured by the Backgroundog service via WASAPI loopback (the same audio your speakers are playing) and an FFT, then delivered to the engine and pushed into your page with ExecuteScriptAsync. See Backgroundog Service and Create Web Architecture for the full pipeline.
Define a global function whose name matches the template you put in SucroseCompatible.json (the convention is SucroseAudioData):
if (navigator.userAgent.startsWith("Sucrose")) {
window.SucroseAudioData = function (obj) {
// obj.Data is the FFT magnitude spectrum
// obj also carries now-playing metadata (Title, Artist, ...)
visualize(obj.Data);
};
}For a Lively / Wallpaper Engine fallback, feature‑detect window.wallpaperRegisterAudioListener first — see Create Compatibility.
The most important field is obj.Data:
- It is a number array — the FFT magnitude spectrum — and it is the field used for visualization.
- Its length is governed by
MaxSample = 128, so expect 128 samples. -
obj.Data[0]is the lowest band / bass; higher indices are higher frequencies. -
Silence produces all‑zero (or near‑zero) values. Showcase wallpapers commonly treat
obj.Data[0] === 0as silence and skip animation.
A simple bass reading sums the low bins:
function bassLevel(data) {
let sum = 0;
for (let i = 0; i < 8; i++) sum += data[i];
return sum;
}Alongside the spectrum, the audio object carries media‑session ("now playing") metadata sourced from the OS:
| Field | Meaning |
|---|---|
State |
Validity flag for the audio object (boolean). |
Title |
Track title. |
Artist |
Artist. |
Subtitle |
Subtitle. |
AlbumTitle |
Album title. |
AlbumArtist |
Album artist. |
AlbumTrackCount |
Number of tracks on the album. |
TrackNumber |
Current track number. |
SourceAppId |
The app providing the media session. |
ThumbnailString |
Album/track thumbnail (string form). |
MediaType |
Media type. |
PlaybackRate |
Current playback rate. |
PlaybackState |
Playback state. |
PlaybackMode |
Playback mode. |
RepeatMode |
Repeat mode. |
ShuffleEnabled |
Whether shuffle is on. |
PropsValid |
Whether the media‑session properties are valid. |
Most timing values are numbers in milliseconds — Position, StartTime, EndTime, MinSeekTime, and MaxSeekTime. The two file-time fields, LastPlayingFileTime and PositionSetFileTime, are instead emitted as ISO 8601 date/time strings, not millisecond numbers.
| Field | Meaning |
|---|---|
Position |
Current playback position. |
StartTime |
Start time. |
EndTime |
End time (track length). |
MinSeekTime |
Minimum seek time. |
MaxSeekTime |
Maximum seek time. |
LastPlayingFileTime |
Last‑playing file time. |
PositionSetFileTime |
Position‑set file time. |
You can build a progress bar from Position and EndTime, and show track info from Title / Artist / AlbumTitle.
A minimal frequency‑bar visualizer:
let frequencyArray = new Array(128).fill(0);
if (navigator.userAgent.startsWith("Sucrose")) {
window.SucroseAudioData = function (obj) {
frequencyArray = obj.Data || frequencyArray;
// now-playing display
if (obj.State) {
document.getElementById("title").textContent = obj.Title || "";
document.getElementById("artist").textContent = obj.Artist || "";
}
};
}
function render() {
const silent = frequencyArray[0] === 0;
if (!silent) {
for (let i = 0; i < frequencyArray.length; i++) {
drawBar(i, frequencyArray[i]); // frequencyArray[0] ~ bass
}
}
requestAnimationFrame(render);
}
render();- The audio feed only reaches
Webwallpapers on WebView/CefSharp — no audio data for MpvPlayer/VlcPlayer/Nebula/Vexana/Xavier/Aurora. -
obj.Datalength is 128;obj.Data[0]≈ bass; all‑zero means silence. - Audio is captured from WASAPI loopback — it reflects what is actually playing on the system's default output, not microphone input.
- Read
obj.Stateto confirm the now‑playing metadata is valid before displaying it. - The data arrives on a timer from the Backgroundog service; treat each call as a fresh snapshot and avoid heavy synchronous work inside
SucroseAudioData(drive your animation fromrequestAnimationFrame, as above).
Getting Started
- Installation
- System Requirements
- Quick Start
- Portal Interface Tour
- Updating Sucrose
- Uninstalling Sucrose
Wallpaper Types
Using Sucrose
- Managing Library
- Using Store
- Customizing Wallpaper
- Multi-Monitor
- Wallpaper Cycling
- Choosing Engines
- Performance Rules
- Theme, Tray & Startup
- Discord Rich Presence
Settings Reference
- Settings Overview
- Settings: General
- Settings: Personal
- Settings: Performance
- Settings: Wallpaper
- Settings: System
- Settings: Other
- Settings: All Keys
Creating Wallpapers
- Create Overview
- Create: Step By Step
- Create: Package Format
- Create: Customization Controls
- Create: JS Bridge
- Create: Audio API
- Create: System API
- Create: Property Listener & Filters
- Create: Web Architecture
- Create: Compatibility
- Create: Example Wallpapers
- Create: Sharing & Publishing
Engine Reference
- Engines Overview
- Engine: MpvPlayer
- Engine: VlcPlayer
- Engine: WebView
- Engine: CefSharp
- Engine: Nebula
- Engine: Vexana
- Engine: Xavier
- Engine: Aurora
- Engine Comparison
Automation & Command Line
Architecture & Internals
- Architecture Overview
- Lifecycle
- Commandog Dispatcher
- Single-Instance Mutexes
- IPC
- Backgroundog Service
- Crash Reporting
- Update Internals
- Property Service
- Undo Internals
Data, Files & Diagnostics
Building & Contributing
- Building From Source
- Repository Layout
- Shared Item Projects
- Code Conventions
- Preprocessor Symbols
- Publish Pipeline
- Bundle Installer Internals
- Extending Sucrose
- Contributing
- Translating with Localizer
- Localization Coverage
- Security Policy
- Privacy & Telemetry
Help & Support