Document .opus emote sound and add a converter for it - #27
Open
dima-dencep wants to merge 5 commits into
Open
Conversation
Emote sound moved from Note Block Studio to Opus, so creatingmusic.md now describes putting an .opus next to the emote, the LOOPSTART tag that makes it repeat, the limits the mod enforces, and why the file should not be normalised by hand. Note Block Studio stays at the end: current versions no longer play .nbs, but it is still passed through to older clients, so shipping both is worth explaining. Writing that file by hand means knowing that Emotecraft wants mono at 48 kHz and that the result has to fit in a network packet, which is a lot to ask of someone who just wants a song under their emote. /opus-converter does it in the browser instead: drop in any audio file, pick quality, trim and looping, and download something the mod will accept. It estimates the size before encoding and refuses to produce a file that is over the limit. ffmpeg.wasm does the encoding. Its wrapper comes from npm but is imported lazily so the static build never touches it, and the 31 MB core is fetched from a CDN rather than committed here. Encoding is constrained VBR: plain VBR overshot a 32 kbps target by 30%, which matters when the ceiling is 1 MB. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Deploying paldocs with
|
| Latest commit: |
6d8179e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://f2ca4977.paldocs.pages.dev |
| Branch Preview URL: | https://feature-emote-sound-converte.paldocs.pages.dev |
The page asked people to produce a file format they may never have seen, without saying what it is or how to play it back. Opus is ordinary audio, the same thing Discord uses, and it is here because it stays small enough to travel inside the emote packet. Opening one varies by system: Windows, Linux and Android handle it as is, macOS needs VLC, and dragging the file into a browser works everywhere. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`-ac 1` sums the two channels without halving them, so every file the converter produced came out 6 dB hot. Anything past full scale is lost when the decoder hands the mod int16 samples, which is heard as crackling. On a normal track that was 2.4% of samples clipped, peaking at +5.5 dBFS. The pan filter mixes the channels properly, and a limiter takes the overshoot the encoder itself adds at low bitrates. Both together bring the same clip to +1.75 dBFS with 0.037% past full scale. `level=disabled` is not optional: the limiter otherwise restores the level it just took off. Nothing gets quieter for it. The mod normalises every sound to the same loudness, so a file with fewer clipped peaks is attenuated less and ends up louder. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The legacy section said .nbs is passed along without saying what to do about it. An emote can hold both files at once: current clients get the .opus, older ones get the .nbs, and a server hands each player whichever they can play, so one pack covers every version. Keeping the .nbs costs a few kilobytes and is never sent to a client that would ignore it. Also noted that emotes from EmotecraftLibrary need none of this — it generates the .opus for anything that has a .nbs, so downloads already carry both. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Emote sound moved from Note Block Studio to Opus, so the page that told people to open Note Block Studio needed rewriting, and the format it now describes is one nobody can produce by hand without reading a spec.
creatingmusic.mdRewritten around putting an
.opusnext to the emote:.opuseven is — ordinary audio, the same format Discord uses, chosen here because it stays small enough to travel inside the emote packet — and how to play one back: Windows, Linux and Android open it as is, macOS needs VLC, and dragging the file into a browser works anywhereLOOPSTARTtag, with the ffmpeg command and the note that 48000 samples is one second.nbs, but it is still passed through to older clients, so keeping both files next to the emote is worth explaining/opus-converterMaking that file by hand means knowing the mod wants mono at 48 kHz and that the result has to survive a network packet. This page does it instead: drop in any audio file, choose quality, trim and looping, download something the mod accepts.
LOOPSTARTso nobody has to compute a sample offset.opusat all@ffmpeg/ffmpegand@ffmpeg/utilcome from npm and are imported lazily inside the click handler, so the static build never loads them. The 31 MB wasm core is fetched from a CDN rather than committed.Checked
Ran the whole path against the production build, then fed the downloaded file to Emotecraft's own parser: mono,
preSkip=312,LOOPSTARTread back, 401 packets, round trip byte-identical.Two things this turned up and fixed:
<audio>never reported metadata in Chrome, so the duration comes fromdecodeAudioDatainstead — immediate and exact.🤖 Generated with Claude Code