A .SerumPreset is a text-and-binary hybrid: an 8-byte XferJson magic, a tiny binary length preamble, a UTF-8 JSON metadata block (name, author, tags, product, version), then one opaque binary blob carrying the wavetable and modulation state. Because the head is JSON, the searchable metadata is plain text — readable verbatim, no binary decode — while the blob stays a black box. Serum 2 adds a twist: it zstd-compresses that blob. The tabs open each region, drawn byte by byte from a real Serum 2 preset. Hover a field to light its bytes, click a field with a + for its table. Color marks kind (see the key).
Most synth presets are all binary — you need a walker to read a single tag. Serum took the opposite bet: it leads with plain JSON. A .SerumPreset is three regions in a row: an 8-byte XferJson magic and a short binary length preamble, a UTF-8 JSON object holding every bit of searchable metadata, and then the binary blob that is the actual patch (the wavetables, the modulation matrix, embedded samples). The metadata is legible without decoding anything; only the blob is opaque. The preset below is a real Serum 2 patch.
.fxp presets (the CcnK container); the native .SerumPreset with its XferJson magic arrives with Serum 2.product: "Serum2". It zstd-compresses the binary blob and can embed sample data (the Embedded-Data tag), so a preset carries its own audio.{, not by trusting the binary preamble — that is robust to preamble changes between Serum versions. The u32 at offset 9 (just past the flag byte at offset 8) does encode the JSON byte length (335 here), a useful cross-check, but the brace scan is what drives the parse.28 B5 2F FD — the zstd magic (little-endian 0xFD2FB528). Serum 2 compresses the wavetable and modulation state; Serum 1 stored it raw. Two u32s precede the frame: the uncompressed size (108,892 bytes here) at the blob's start, then a small count (2) immediately before the magic. The decompressed interior has no documented format either.presetName/tags a human reads are what an indexer stores. Contrast Bitwig or Native Instruments, whose metadata is buried in binary trees that each need their own decoder.The file opens with the 8-byte XferJson magic — the signature that identifies any Serum preset or .fxp. Immediately after sits a 9-byte binary preamble: a flag byte, a u32 that equals the JSON block's byte length, and a reserved word. Then the JSON begins at its opening {. The map is the full 17-byte head of a real Serum 2 preset.
Hover json_length — 0x0000014F = 335, exactly the JSON block's size.
"XferJson" is the same first eight bytes for Serum presets, wavetables and FXP wrappers; use it only to identify the file, then find the metadata by scanning for the first {. The preamble's json_length is a cross-check, not the source of truth — so a version that resizes the preamble still parses.The metadata block is a single JSON object — ordinary UTF-8 text you can read in any hex viewer. It carries the preset's identity and every searchable field: fileType, presetName, presetAuthor, presetDescription, product, productVersion, a tags array, vendor, a content hash, and a struct version. These lift straight into a library index — no decoder, because there is nothing to decode.
The first 24 bytes of the block — plain ASCII. Hover any byte: it is just text.
product: "Serum2" with productVersion: "2.0.18" marks a Serum 2 preset; a Serum 1 preset reports "Serum". The version field (7.0 here) is the JSON schema version, distinct from the plugin version — two different numbers to keep apart.tags array (Wavetable, Embedded-Data, Mono) is exactly what a library browser wants, sitting in plain text. Embedded-Data means the preset carries its own sample content inside the blob — it is self-contained, not referencing an external wavetable.Everything the JSON does not say lives here: the wavetables, the modulation matrix, oscillator and effect state, and (when tagged Embedded-Data) the sample content itself. There is no public format for the interior — it reads as one opaque byte region. What is legible is the framing: this Serum 2 preset opens the blob with a small header and then a Zstandard frame. The map is the blob's first 16 bytes.
Hover zstd_magic — the Zstandard signature that marks the compressed frame.
28 B5 2F FD, the little-endian zstd magic 0xFD2FB528. The uncompressed size (0x0001A95C = 108,892) sits at the blob's start, with a small count (2) between it and the magic; the byte after the magic is the zstd frame-header descriptor. Serum 1 wrote the blob uncompressed, so its byte-8 signature is absent — a quick way to tell the two generations apart beyond the product string.