Repository navigation
feat(export): songs export to WAV, AIFF, FLAC, Apple Lossless, MP3, AAC, Opus and Ogg Vorbis, and song.mp3 no longer needs ffmpeg - #46
Merged
Conversation
…AC, Opus and Ogg Vorbis, and song.mp3 no longer needs ffmpeg
devlato
enabled auto-merge (squash)
October 20, 2026 02:22
devlato
added a commit
that referenced
this pull request
Oct 20, 2026
The formats `claudius export` writes ([#46](#46)) are now everywhere else too. - **Studio:** an **export** menu in the toolbar, after the stems menu. It lists the presets in two groups, lossless and compressed. Each is a download of the latest render, named after the song. A format this machine cannot write is greyed out and says why on hover: AAC and Apple Lossless without Core Audio or ffmpeg. The menu says when the render predates the latest change. It works in the native and the web studio; the demo, which has no server, shows no menu. - **MCP:** an `export` tool, with `formats` and an optional `path`. It writes into the song's folder (or `path`), rendering first when the song changed since its last render. - **API:** - `Command::Export` writes from the latest render when it is of the song as it is now, and otherwise says to render first. - `GET /api/export/{version}/{name}.{ext}?format=SPEC` serves that render as a download (`Content-Disposition: attachment`), with the format's media type. It is encoded on request, and the latest export is kept in memory for a second click. CodeQL flagged the first version of the download (9 `rust/path-injection` alerts). The version came from `Path<(u64, String)>`, and the format named a cache file. Neither could leave the cache, but the route now parses the version from a string, as `/api/audio` does, and keeps nothing on disk. No path is built from the request except the render's number. - `State.exports` lists every preset, with its label and why it cannot be written here, when it cannot. Docs: the Exporting page gains the studio, the tool and the API. Also updated: the MCP tool table, the HTTP routes and commands, the studio page, and the skill's tool list and saving section. How I checked: - **A new server test:** a rendered song exports by command (two formats into a folder; a bad spec is refused) and as a download. The download is checked for type, filename and a decodable 44.1 kHz FLAC, plus a 400 for a mismatched extension and a 404 for a render that isn't there. - **MCP:** the test checks that `save` and `export` are listed. - **The native studio**, driven by `CLAUDIUS_UI_PLAN`: it rendered a song, and the export menu was opened and captured with all thirteen presets. - `cargo xtask ci` passes, and `cargo xtask site` builds the web studio, with lychee reporting 0 broken links.
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.
Songs can be exported in every popular format, including the ones the web plays, and every song folder gets its
song.mp3without ffmpeg.claudius export <song folder or audio file> -f mp3,flac:16,opuswrites the master as:--listshows every format, and any this machine cannot write. The studio menu, MCP tool and HTTP download come in a follow-up pull request.How it's built
A new crate,
claudius-encode, the counterpart ofclaudius-decode:rusty_mp3) and Opus (opus-pure).vorbis_rs, which compiles libvorbis with aoTuV viacc.afconverton macOS, and from ffmpeg elsewhere when it is installed.Licences: Apache-2.0 and BSD-3 only. LAME (LGPL) was ruled out by
deny.toml. A pure-Rust AAC encoder exists (oxideav-aac), but it took 36 s to encode 30 s of audio.What else is in it:
claudius-decodegainsdecode_bytes;exportmodule;song.mp3and the server's playback MP3 are encoded in process;exportcommand. It needs a redeploy after the merge.How I checked
Quality, on 30 s of a real render, against ffmpeg's encoders at the same bitrate (mean difference in third-octave band energy, decoded by ffmpeg):
Every format of a 3.5-minute song, all ten exported in 4.4 s, decodes:
Tests:
cargo xtask ci,cargo deny check,cargo xtask sitewith lychee (0 broken links), and the Worker's tests pass.