Marathon is a media streaming service designed to binge watch all your stuff in a single session. A dream of a Whovian or just an everyday nerd that has time for a new short series.
- True Marathon Playback: Treats an entire series as a single, continuous stream, splicing episodes together on-the-fly for seamless, back-to-back viewing without loading screens.
- Visual Interval Editor: A built-in editor to precisely mark custom time segments in any episode. Define openings, endings, recaps, or bonus content.
- Automatic Content Splicing: Dynamically removes the HLS segments corresponding to your marked intervals during playback, so you see the first opening and then just the story.
- Audio Fingerprinting: (broken) Mark an opening once, and Marathon will automatically detect and skip it in all other episodes. Uses acoustic fingerprinting (chromaprint) to find matches even with slight variations.
- Hardware-Accelerated Transcoding: Auto-detects NVIDIA (NVENC) or Intel/AMD (VAAPI) GPUs and uses them for encoding. Falls back to CPU gracefully. Your GPU finally does something useful.
- High-Performance Streaming: Powered by HTTP/2 multiplexing and parallel media indexing, ensuring instant seek times and fast library scans.
- Import / Export Intervals: Save all of a series' interval data to a single JSON file. Share your timings with friends or back them up.
- Keyboard-First Navigation: Designed for the "10-foot UI" experience. Features spatial navigation for all controls and advanced playback shortcuts.
- Variable-Speed Scrubbing: Hold down the seek keys to fast-forward or "rewind" at an accelerating speed, from 2x up to 64x.
- Persistent Watch History: Remembers your exact timestamp within the entire series marathon, not just a single file.
- Simple File-Based Library: Just point it at your media folder. No complex metadata agents or forced naming schemes.
- Set the
MEDIA_ROOTenvironment variable to point to your media library (e.g.,export MEDIA_ROOT=./media). - Run
make run(orcargo run --release -p marathon-server). - Navigate to
https://localhost:3000.
⚠️ Security Warning: To support HTTP/2 (which dramatically improves streaming performance), Marathon runs over HTTPS by default.On first run, it generates a self-signed certificate. Your browser will warn you that the connection is not private. Click "Advanced" -> "Proceed to localhost (unsafe)" to continue.
Marathon is configured via environment variables:
| Variable | Description | Default |
|---|---|---|
MEDIA_ROOT |
Path to the directory containing your video files. | ./media |
TLS_CERT |
Path to a custom TLS certificate file (.pem or .crt). |
(Auto-generated) |
TLS_KEY |
Path to the corresponding private key file (.pem or .key). |
(Auto-generated) |
RUST_LOG |
Logging verbosity levels. | info,marathon_server=debug |
All transcoding options are prefixed with MARATHON_. Most defaults are sane, but feel free to tweak:
| Variable | Description | Default |
|---|---|---|
MARATHON_CACHE_DIR |
Where to store transcoded segments. | ./cache |
MARATHON_MAX_CONCURRENT_TRANSCODES |
Max parallel FFmpeg jobs. | 4 |
MARATHON_SEGMENT_READY_TIMEOUT_SECS |
How long to wait for a segment. | 120 |
MARATHON_SKIP_PREVIEW |
Skip fast preview, go straight to native. | false |
MARATHON_FAST_HEIGHT |
Resolution for preview quality. | 720 |
MARATHON_FAST_CRF |
Quality for preview (higher = smaller). | 28 |
MARATHON_NATIVE_CRF |
Quality for native (lower = better). | 23 |
Set MARATHON_SKIP_PREVIEW=true if you have a fast GPU - native quality is often faster than the two-stage preview -> native approach.
Hardware acceleration is auto-detected. If you have an NVIDIA GPU with NVENC support, it'll just work. Check the logs for [NVENC] or [VAAPI] to confirm.
If you want to get rid of the browser warning, you can provide your own trusted certificates (e.g., via mkcert):
export TLS_CERT=./certs/localhost.pem
export TLS_KEY=./certs/localhost-key.pem
make runWhy?
I was mildly annoyed by my cheap projector's controls and the general clumsiness of streaming from various sites. I wanted to watch the whole story without the repetitive openings and endings, and manual labor (clicking "next episode") - just a never-ending stream of the show. That can't be too hard.
Why bother with playback controls for a potentially 1000-hour stream? Skipping a few seconds seems unbearable.
Big number go up hehe.
Seriously, it was a fun technical challenge. The player builds a virtual timeline of the entire series, so seeking from Episode 1 to Episode 50 is instantaneous.
Clumsy controls??
They were customized specifically for my workflow. Feel free to change the keybinds or even open a PR with a keybind configuration feature (I'll be very happy to take a look).
Why ffmpeg, and HLS instead of X and Y?
Idk, FFmpeg is cool and ancient, and HLS is a neat standard, so why not use them all at the same time? Also, if you do care enough - all components of the backend pipeline are replaceable in a Ports and Adapters manner. Feel free to create and share your alternative adapters for the pipeline components.
How do I know if hardware acceleration is working?
Check the server logs on startup. You'll see either:
NVIDIA NVENC hardware acceleration available- you're goldenVAAPI hardware acceleration available- Intel/AMD GPU is being usedNo hardware acceleration available, using CPU encoding- software fallback
During playback, transcode logs will show [NVENC] or [VAAPI] if HW accel is active.
Testing data?
Demo scripts in the root can generate some placeholder files. The system can handle timelines for over 1000 hours of video files just fine - well, at least my system can :p
Also, if it counts for anything, it was battle-tested on all of SPY x FAMILY (all episodes and the movie) and both seasons of Saiki K. All went fine.
Something is broken/doesn't work well
As said before - works on my machine. Open an issue, I'll be happy to look at it in my free time :)
This project is licensed under the GNU General Public License v3.0.
See the LICENSE file for details.