audioserve: a Rust server that turns a folder of audio files into a personal audiobook library
Simple personal server to serve audiofiles files from folders. Intended primarily for audio books, but anything with decent folder structure will do.
At a glance
- What is it?
- Audioserve serves audio files straight from directories on disk, with no database to populate and no metadata format to conform to, and it adds a web PWA client, an Android client and a simple API on top. It is written in Rust, caches collection data in an embedded key value store, and is explicit about the security work you still have to do before exposing it to the internet.
- Who is it for?
- Audioserve fits a person or a household that already has audio files arranged in folders and wants them reachable from a phone and a browser without importing anything into a media server's catalogue. It does not fit a library that expects tagged, indexed media, because browsing is by directory and by filename and search covers folder names only.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Serving a folder rather than building a media catalogue
Audioserve is a personal server that serves audio files from directories, and the design decision that follows from that is the absence of an import step. The README states that the server serves files in exactly the same structure they have on disk, with support for .m4b and similar single file audiobooks where chapters are presented as virtual files. Audio tags are not used for browsing; they can optionally be displayed.
The recommended directory layout is two or three levels:
Author Last Name, First Name/Audio Book Name
Author Last Name, First Name/Series Name/Audio Book NameAnd the recommended file naming is a padded number prefix:
001 - First Chapter Name.opus
002 - Second Chapter Name.opusFiles should be named so they come out in the right order, but the padding is no longer strictly necessary: natural ordering is supported by default and can be switched off with the `no-natural-files-ordering` argument. The documentation is explicit that the structure is not mandatory, since you will just see whatever directories and files you have.
Two conventions are worth respecting. File and folder names are assumed to be in UTF-8 or a compatible encoding, and the characters `$$` and `|` are reserved for internal use and should not appear in names. Folders can carry extra metadata files: the first available image in jpeg or png becomes the cover picture, and the first text file in html, txt or md becomes the folder description. Search is done over folder names only, not individual files and not audio metadata tags.
Several collections are supported by passing several collection directories as command arguments, with the client able to switch between them, and a typical use is to keep separate collections for different languages. Symbolic links are not followed by default, because incorrect use of them can hurt search and browsing badly, but `--allow-symlinks` enables them.
The collection cache is the price of the fast search
The README is refreshingly honest about why the cache exists. The author originally assumed everything could be served straight from the file system, but experience and user feedback revealed two problems: for larger collections search was slow, and a folder with many audio files was slow to load, because basic metadata has to be collected for each file, namely duration and bitrate.
The fix was caching collection data into an embedded key value database using sled, and the author's assessment is that it makes the server fast. The trade is stated just as plainly, since the cache brings more complexity into the program.
Three consequences follow from that design, and they are operational details rather than caveats. On start, audioserve scans and caches the collection directories, and the first scan can take a long time, potentially tens of minutes for larger collections, during which search may not work reliably. You can force a full rescan at runtime by sending the program the signal `sigusr1`. And the contents of the cache are influenced by a specific list of arguments: `--tags`, `--tags-custom`, `tags-encoding`, `--ignore-chapters-meta`, `--no-dir-collaps`, `--allow-sym-link`, `-chapters-duration`, `--chapters-from-duration`, `read-playlist`, `--collapse-cd-folders`, `cd-folders-regexp` and `no-natural-files-ordering`. If you restart the server after changing one of those, it should perform a full cache reload.
That last point is the one that bites. A change to how tags are read or how CD subfolders are collapsed changes the cached view of your library, and the server's own answer is to rebuild it.
Security is a section, not a footnote
The README carries a warning near the top that if you install audioserve and make it available on the internet you should not underestimate security. There is a whole Security section covering TLS and SSL, reverse proxy deployment, request rate limits and CORS, and a separate Security Best Practices subsection, plus a SECURITY.md file at the top of the repository.
The structural choice is to let the server terminate TLS itself or sit behind something that does. The Cargo.toml features list makes that explicit, with tls and behind-proxy among the default enabled features:
default = [
"tls",
"symlinks",
"folder-download",
"shared-positions",
"behind-proxy",
]So the default build supports TLS, follows symbolic links, allows folder downloads, supports shared playback positions and expects to be reachable through a reverse proxy. The ring crate at version 0.17 provides the cryptography, and the behind-proxy feature is what lets the server work when it is not the outermost listener. Request rate limiting and CORS are documented as separate configuration points rather than being folded into a single hardened mode.
There is a demo instance linked from the README with a shared secret, which is a reasonable way to see the interface before installing anything, but it is also a reminder that a personal audiobook server is a thing people run on the open internet and therefore a thing that needs authentication and transport encryption before it holds anything you care about.
Clients, transcoding and the API
The server is written in Rust and the current web client is a PWA built with TypeScript and Svelte, aimed at modern browsers and making use of recent functionality such as a Service Worker. An older, less demanding web client is still around for constrained environments. There is also an old Android client in its own repository, and a simple API described in docs/api.md for custom clients.
Transcoding is a first class feature rather than an afterthought. The Cargo.toml shows it is optional and feature gated, with async-tar and async-zip used for the folder download support, tokio-util with the codec feature, and a cron and chrono pair behind the shared-positions feature. Audio files can be re-encoded on the fly, which is what makes a single opus library usable on an old device.
Apple users need extra configuration, and the README calls this out in a note near the top as well as in a dedicated section on alternative transcodings and transcoding configuration for Apple users. Playback position sharing between clients is implemented with a websocket, the websock crate, and the same feature also brings in cron and chrono, so position synchronisation is scheduled work rather than something done purely on request.
Performance features include a transcoding cache, response compression and HTTP/2 support. A static build is available for Linux through a dedicated Dockerfile.static and build_static.sh, alongside the ordinary multi stage Dockerfile.
Building and running the Docker image
The Dockerfile shows a three stage build: an Alpine build stage that compiles the Rust server and runs the tests, a Node stage that clones the web client repository and builds the service worker and the client bundle, and a final Alpine image that copies both into place. The final image adds a non-root user with uid 1000, chowns the tree to it, and switches to that user before the entrypoint runs.
The runtime environment is set with two variables:
ENV PORT=3000
ENV RUST_LOG=infoThe image also installs libbz2, zlib and ffmpeg in the final stage, which is the sign that transcoding happens on the server and needs an external encoder available at runtime. The build stage installs the matching development packages including ffmpeg-dev, so ffmpeg is a hard dependency of a transcoding deployment whether it is in the container or on a bare machine.
The Cargo.toml pins the toolchain expectations, with edition 2021 and rust-version 1.79, and the workspace is arranged with a members glob over crates/* so the collection, file cache, websocket, async tar and async zip pieces are separate crates in the same tree. The repository also carries Cargo.lock, a Cross.toml for cross compilation, a renovate.json for dependency updates, a codecov.yml, and test_data and tests directories.
Where audioserve is the wrong choice
The clearest mismatch is with a tagged media library. Browsing here is by directory and by filename, and search covers folder names only, not individual files and not audio tags. If your collection is a folder of files with meaningful ID3 or Vorbis metadata and you expect to search inside it, this server will not do that. Tag data can be displayed, but it is not the index.
There is also a cost to the folder convention that the README glosses over: the reserved characters `$$` and `|`, the UTF-8 assumption, and the fact that ordering depends on filenames. A collection assembled from many sources will need renaming, and that renaming is yours to maintain.
The security surface is the second consideration. This is a server meant to be reachable, it can transcode arbitrary audio on request, and it will happily serve a whole folder as an archive when the folder-download feature is enabled. That is exactly the combination that gets a public instance scanned. The project's own guidance is to read the security section before exposing it, and to consider a reverse proxy.
Compared with a general purpose media server, the difference in approach is that audioserve does one thing, keeps its state in the filesystem, and lets you read the whole thing in a single README. The trade is that you lose the metadata indexing, the transcoding profiles and the multi-user support that the larger tools provide, in exchange for a server you can reason about.
Licensing is the loose end. The licence field on the repository is unknown and there is no licence file among the top-level entries, which are the Dockerfiles, the Cargo manifests, the source directories and the documentation. If you plan to redistribute a build of it, ask the author directly.
Editorial conclusion
Audioserve fits a person or a household that already has audio files arranged in folders and wants them reachable from a phone and a browser without importing anything into a media server's catalogue. It does not fit a library that expects tagged, indexed media, because browsing is by directory and by filename and search covers folder names only. Before exposing it publicly, follow its own security guidance, since the project states plainly that you should not underestimate it, terminate TLS in front of it or enable its TLS support, set the request rate limit, and confirm that your folder layout avoids the two characters the server reserves for itself, the double dollar sign and the vertical bar.
Frequently asked questions
How do I organize audio files for audioserve?
The recommended layout is Author Last Name, First Name/Audio Book Name, or Author Last Name, First Name/Series Name/Audio Book Name, with files named so they sort correctly, for example 001 - First Chapter Name.opus. Natural filename ordering is supported by default and can be switched off with the no-natural-files-ordering argument.
Does audioserve use audio tags to build its library?
No. Audio tags are not used for browsing and can only optionally be displayed. Browsing follows the directory structure on disk, search covers folder names only, and the first image or text file in a folder is taken as its cover or description.
Why is the first run of audioserve slow?
On start the server scans and caches the collection directories, and a first scan of a large collection can take tens of minutes, during which search may not work reliably. You can force a full rescan by sending the program the sigusr1 signal.
Which clients can I use with audioserve?
There is a web PWA client written in TypeScript and Svelte, an older less demanding web client, an Android client in its own repository, and a simple API in docs/api.md for custom clients. Playback positions can be shared between clients through a websocket.
Does audioserve need ffmpeg for transcoding?
The Dockerfile installs libbz2, zlib and ffmpeg in the final runtime image, and the build stage installs the matching development packages, so an encoder has to be present for transcoding to work. The Docker image also sets PORT=3000 and RUST_LOG=info and runs the server as a non-root user.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/izderadicka-audioserve)Was this useful?