Rust · MIT · early development

A self-hosted media server in Rust.

Mythos is a single-binary media server with an embedded SvelteKit UI. It scans your library, enriches metadata from TMDb, and streams direct-play when it can — hardware-accelerated HLS, with HDR→SDR tonemapping, when it can't. Movies and TV today; music, photos, and books are next.

~/mythos — cargo run
$ cargo run --release --bin mythos-server
 config        listen=0.0.0.0:8080 · data_dir=./data
 migrate       25 migrations applied · sqlite ./data/mythos.db
 hwaccel       probe ffmpeg · nvenc + nvdec + scale_cuda
 tonemap       filters available · software · tonemapx · cuda
 jwt           loaded ./data/jwt.secret · 32 bytes
 embed         spa from rust-embed · 142 assets
 ready         serving http://0.0.0.0:8080
$ 

See it running

And it looks like this.

These are the Android and Google TV builds against a live Mythos server — the same REST API the web and desktop clients use. The Android UI is foldable-aware: it reflows from the folded cover screen to the full unfolded display. Apple TV is next.

# android — foldable · folded · flex · unfolded

  1. Mythos home screen on an unfolded Galaxy Z Fold — Continue watching and Recently added rows beside a left navigation rail.
    Unfolded Home Continue watching and recently-added rails fill the unfolded inner display.
  2. The same Mythos home screen on the folded Galaxy Z Fold cover display, with Continue watching, Recently added, and a bottom tab bar.
    Folded Home The same home, reflowed for the folded cover screen with a bottom tab bar.
  3. Mythos in flex mode on a half-folded Galaxy Z Fold — the movie plays on the upright top screen while playback controls sit on the flat lower deck.
    Flex mode Player Half-fold it and the video stands up while the controls drop to the deck.
  4. Blade Runner 2049 detail page with a full-bleed backdrop, codec and HDR badges, and a Resume button.
    Unfolded Movie detail Cinematic detail pages — resume right where you left off.
  5. Battlestar Galactica series page with season tabs and an episode list.
    Unfolded TV series Seasons and episodes, the same surface as movies.
  6. Aliens detail page showing cast headshots, HEVC and HDR badges, and the library's A to Z jump rail.
    Unfolded Cast & crew Cast headshots, codec and HDR badges, and an A–Z library rail.
  7. Search results for "matrix" listing movies across the library.
    Unfolded Search One box searches every movie and series at once.

# google tv — 10-foot, D-pad native

  1. Mythos home screen on Google TV with a Continue watching row of poster art, driven by a D-pad.
    Home Continue watching, built for the remote.
  2. Blade Runner 2049 detail page on Google TV with a full-screen backdrop, poster, codec and HDR badges, and Resume / From start buttons.
    Movie detail Cinematic detail pages, sized for the living room.
  3. Blade Runner 2049 playing on Google TV with the transport overlay — scrubber, 4K and HDR badges, and subtitle and audio controls.
    Player 4K HDR playback on the big screen.
  4. Blade Runner 2049 playing on Google TV, paused mid-scene, with the transport overlay — scrubber, time remaining, 4K and HDR badges, and audio and subtitle controls.
    Now playing Transport overlay — scrub, switch audio and subtitles, 4K and HDR.
  5. Game of Thrones series page on Google TV with season tabs and a row of episode thumbnails.
    TV series Seasons and episodes, all from the remote.
  6. Google TV library grid of movie posters with an A to Z jump rail down the right edge.
    Library Browse the whole library with an A–Z jump rail.
  7. Search results for "matrix" on Google TV showing movie posters.
    Search Find any title from the couch.

How it fits together

Scan, enrich, stream — one binary.

  1. 01 · source on disk · on the network
    library root · media files you bind-mount in TMDb · titles · overviews · art
  2. 02a · scan jwalk + ffprobe
    walk media_files identify movies · series · seasons · episodes
    02b · enrich TMDb client + poster cache
    search titles · overviews art posters · backdrops · stills
  3. 03 · serve axum HTTP API
    routes auth · library · movie · series · episode · play · hls
  4. 04a · direct play HTTP byte ranges
    stream raw container, resumable
    04b · HLS transcode ffmpeg session · ABR up to 4K
    hwaccel NVENC · QSV · VAAPI · VT tonemap HDR SDR
  5. 05 · client web · Qt desktop · Android · tvOS · webOS
    player media-chrome + hls.js · mini-bar across nav pair many servers per client · fan-out browse / search

What works today

Thirteen things Mythos already does.

  1. 01

    Single binary, embedded UI.

    The SvelteKit build is baked into the Rust binary via rust-embed. One file boots the server and serves the SPA.

  2. 02

    Library scan + TMDb enrichment.

    Parallel filesystem walk via jwalk, technical metadata via ffprobe, titles and posters from TMDb — for both movies and TV. Posters are proxied locally so clients never hit TMDb directly.

  3. 03

    Movies and TV.

    Series → seasons → episodes are scanned, identified from SxxEyy / 1x01 filenames (with a season-dir fallback), enriched with TMDb episode stills, and played from a shared player component.

  4. 04

    Direct play with byte ranges.

    If your browser can decode the file, Mythos streams it raw with HTTP range requests. Resume points are debounced and persisted per-user across movies and episodes.

  5. 05

    HLS transcoding, ABR up to 4K.

    For browser-incompatible codecs (HEVC, AV1, DTS, …) Mythos spawns an ffmpeg session, segments to HLS, and tears it down when the player goes away. The ABR ladder runs from 360p through 2160p with H.264 Level 5.1 hints — and tiers that would only upscale get pruned from the master per-source so a 1080p file is never offered 4K. A manual quality picker in the player sits next to Auto, exposing every source-feasible tier.

  6. 06

    Hardware-accelerated, end-to-end.

    NVENC, QSV, VAAPI, and VideoToolbox are probed and smoke-tested at startup. The NVENC path stays on the GPU end-to-end (NVDEC + scale_cuda), and a build with the encoder compiled in but a missing driver falls back to CPU cleanly.

  7. 07

    HDR→SDR tonemapping.

    4K HEVC HDR sources are tonemapped on the way out via a configurable pipeline — software, tonemapx (jellyfin-ffmpeg's SIMD CPU kernel), VAAPI, OpenCL, or CUDA — picked from filters Mythos probes for at startup. Hable / Mobius / Reinhard / BT.2390 algorithms; admin-editable from the settings UI.

  8. 08

    Subtitles done right.

    Text subtitles ride along as WebVTT sidecars — embedded streams and .srt files dropped next to the video (or in a sibling Subs/ directory) are both picked up. Image subtitles (PGS/VobSub) burn in during transcode so they survive every device. Continue-watching and auto-play-next stitch episodes together across the library.

  9. 09

    Title search across the library.

    A single search box queries movies and series together via GET /api/search — case-insensitive prefix match against the sort title. Results render inline with keyboard navigation (/ to walk, Enter to open). Backed by SQLite LIKE today; will graduate to FTS5 once libraries get big enough to chug.

  10. 10

    Playback that survives navigation.

    The player is hoisted into the root layout and managed by a singleton session — start a movie, hit PiP, and the modal collapses into an 88 px bar pinned to the bottom of the page. Browse anywhere; the same <video> / HLS session keeps playing. Click the small video to expand back to fullscreen; Esc minimizes instead of closing. The library page itself gets a Plex-style vertical alphabet rail that strips leading articles ("The Matrix" buckets under M).

  11. 11

    Native clients, not just the browser.

    Beyond the embedded web UI there's a fleet of native clients talking to the same REST API: a Qt 6 + cxx-qt desktop app (apps/mythos-qt/) that swaps <video>+hls.js for libmpv so HEVC, AV1, and HDR direct-play without the browser codec gauntlet; a Kotlin + Jetpack Compose Android build that ships both a phone/foldable app and a D-pad-native Google TV app on Media3/ExoPlayer; a SwiftUI Apple TV app on AVPlayer; and an LG webOS TV launcher. They build with their own toolchains (Gradle, Xcode, ares-package); only the Qt app is a Cargo workspace member.

  12. 12

    Pair every client with every server.

    The server stays single-tenant, but each client keeps its own list of paired Mythos servers and fans browse, search, and continue-watching out across all of them at once — tiles, images, and playback all route back to the server they came from. The only server-side support is a public GET /api/server-info that hands back a display name and version so a freshly-paired server can be labelled.

  13. 13

    Collections, cast & crew, and sharing.

    Movies group into Plex-style collections — auto-generated from TMDb franchises or hand-curated. Detail pages carry a cast & crew strip (top billing plus directors / writers / producers) with cached headshots. And libraries have an owner and a visibility: public to every user, or restricted to the owner, admins, and explicit shares — invisible content returns 404, never 403.

Where we are

Roadmap — track the phase, don't pull work forward.

phase 0 — 2

Done. Workspace, embedded SPA, axum boot, SQLite + migrations, argon2id + HS256 JWTs (cookie or Bearer), libraries CRUD, movies scanner + browse UI, TMDb enrichment with an admin-editable key, direct-play streaming with byte ranges, debounced watch progress, resume.

phase 4 — 5

Done. Phase 4 ships HLS transcoding for incompatible media. Phase 5 lights up hardware acceleration (NVENC / QSV / VAAPI / VT), a multi-rendition ABR ladder up to 2160p — AVC and HEVC side by side — with source-resolution-aware pruning, subtitle burn-in, client-declared device profiles, a manual quality picker in the player, HDR→SDR tonemapping with a configurable filter pipeline, and Dolby Vision transcode-on-the-fly so DV files play on clients without a DV pipeline.

phase 3

In progress. 3a — TV schema, scanner, TMDb enrichment, browse UI. 3c — episode playback sharing the movie streaming surface via a kind-aware SessionKey. 3d — continue-watching aggregated across movies + episodes, plus auto-play-next at episode end. Polish on top: title search across movies + series, sidecar .srt discovery, a media-chrome-based player, per-file keyframe indexing for keyframe-aligned remux HLS, a 3-step setup wizard, a Plex-style alphabet jump bar on library browse, "Recently added" home rails, hover-to-open nav dropdowns + back/forward scroll restoration, per-library Refresh-art / Stop-scan and per-series Rescan / Rematch + manual TMDb identify admin actions, and a persistent mini-bar player that survives navigation. Plus movie collections, cast & crew, per-user library visibility + sharing, multi-server pairing, and a client fleet — Qt 6 desktop, Kotlin/Compose Android phone + Google TV, Apple tvOS, and an LG webOS launcher. Music, photos, and books are the remaining sub-phases.

phase 6

Next. A Jellyfin-API-compatible shim at /jellyfin/* so existing clients (Findroid, Swiftfin, jellyfin-web) work against Mythos without changes.

Get started

A container, the source, or a native client.

docker run

The fastest way in. :latest tracks the newest tagged release (semver tags like :0.3.6 are published alongside it). The image bundles jellyfin-ffmpeg (so HW tonemap filters and the SIMD-CPU tonemapx kernel are available) and runs as PID 1 under tini. linux/amd64.

docker run -d --name mythos \
  -p 8080:8080 \
  -v mythos-data:/data \
  -v /path/to/media:/media:ro \
  darkspar/mythos-server:latest

cargo run

Build from main. One command builds the SPA (via pnpm build) and the Rust binary, then boots the server on 0.0.0.0:8080 — reachable from any device on your LAN.

git clone https://gitlab.mattmoore.io/darkspar/mythos
cd mythos
cargo run --release --bin mythos-server

prerequisites

The from-source build needs a working Rust toolchain, Node + pnpm for the SPA, and ffmpeg/ffprobe on PATH for scans and transcodes.

rustup 1.95+
node 22+
pnpm 10+
ffmpeg / ffprobe

configure

Defaults work out of the box. Override via ./mythos.toml or any MYTHOS_* env var — env wins.

listen     = "0.0.0.0:8080"
data_dir   = "/var/lib/mythos"
log_filter = "info,mythos=debug"

native clients

A Qt 6 + cxx-qt + libmpv desktop app builds straight from the workspace. Beyond it, native Android (phone + Google TV), Apple tvOS, and LG webOS clients live under apps/ and build with their own toolchains. All pair with multiple servers at once; the Qt app is an early-but-usable scaffold.

git clone https://gitlab.mattmoore.io/darkspar/mythos
cd mythos
cargo run -p mythos-qt --release

Early, but real.

Mythos streams movies and TV with hardware-accelerated transcoding and HDR tonemapping today, to the browser and a fleet of native clients. The roadmap is public, the source is MIT, and you're one docker pull — or one cargo build — away.