Streams an entire series as a single continuous video, splicing episodes together and skipping marked intervals (openings, endings, recaps).
API Reference - Architecture Guide
- Treats a series as one stream, no loading between episodes
- Visual editor to mark intervals (openings, endings, recaps, etc.)
- Marked intervals are removed during playback
- Hardware-accelerated transcoding (NVENC, VAAPI) with CPU fallback
- H.264, H.265, or AV1 encoding
- HTTP/2 and parallel media indexing
- Import/export interval data as JSON
- Keyboard navigation and spatial controls
- Phone remote via WebSocket (
#remote) - Variable-speed scrubbing (2x-64x)
- Watch history across entire series
- File-based library, just point at a folder
- Watch party, synced playback across viewers
- Shaka Player for HLS streaming
- Continue watching with progress bars
- Watch statistics
- Dark/light theme
- Prometheus metrics at
/metrics .strmfile generation for Kodi/VLC
export MEDIA_ROOT=./media
make runOpen http://localhost:3000.
Environment variables:
| Variable | Description | Default |
|---|---|---|
MEDIA_ROOT |
Path to the directory containing your video files. | ./media |
DATABASE_URL |
SQLite connection string. | sqlite:marathon.db |
PORT |
HTTP server listen port. | 3000 |
MARATHON_LOG_FORMAT |
Set to json for structured JSON logging. |
(text) |
MARATHON_HTTP2 |
Enable HTTP/2 over HTTPS. Requires TLS certificates. | false |
TLS_CERT |
Path to a custom TLS certificate file (.pem or .crt). Only used when MARATHON_HTTP2=true. |
(Auto-generated) |
TLS_KEY |
Path to the corresponding private key file (.pem or .key). Only used when MARATHON_HTTP2=true. |
(Auto-generated) |
MARATHON_FRONTEND_DIR |
Path to the frontend build output. | frontend/dist |
MARATHON_CORS_ORIGINS |
Comma-separated allowed CORS origins (overrides default localhost). | (localhost only) |
MARATHON_CERTS_DIR |
Directory for auto-generated TLS certificates. | certs |
RUST_LOG |
Logging verbosity levels. | info,marathon_server=debug |
export MARATHON_HTTP2=true
make runNavigate to https://localhost:3000.
On first run, a self-signed certificate is generated. Your browser will show a warning; click "Advanced" -> "Proceed to localhost (unsafe)" to continue, or provide your own certificates.
All transcoding options are prefixed with MARATHON_:
| Variable | Description | Default |
|---|---|---|
MARATHON_CODEC |
Video codec: h264, h265, or av1. |
h264 |
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. | true |
MARATHON_FAST_HEIGHT |
Resolution for preview quality. | 720 |
MARATHON_FAST_FPS |
Frame rate for preview quality. | 25 |
MARATHON_FAST_CRF |
Quality for preview (higher = smaller). | 28 |
MARATHON_FAST_ENCODER_PRESET |
Encoder speed preset for preview. | ultrafast |
MARATHON_NATIVE_CRF |
Quality for native (lower = better). | 23 |
MARATHON_NATIVE_ENCODER_PRESET |
Encoder speed preset for native. | veryfast |
Codec Selection:
h264- Best compatibility. Safari 6+, Chrome 23+, Firefox 21+.h265- ~40% smaller. Safari 11+, Chrome 107+, Edge 18+.av1- ~50% smaller. Chrome 70+, Firefox 67+, Safari 17+. Uses fMP4 container.
Encoder auto-selected based on hardware: NVENC for NVIDIA, VAAPI for Intel/AMD, software fallback (libx264/libx265/libsvtav1).
Set MARATHON_SKIP_PREVIEW=true to skip preview quality and go straight to native.
- Start playing on your main screen
- Click the phone icon in the player
- Note the 6-character session code (e.g.,
ABC123) - On your phone, go to
https://your-server:3000/#remote - Enter the code and connect
Controls: play/pause, seek, volume, episode navigation, playback speed. Syncs via WebSocket.
To avoid browser warnings with HTTP/2:
export MARATHON_HTTP2=true
export TLS_CERT=./certs/localhost.pem
export TLS_KEY=./certs/localhost-key.pem
make run- Rust 1.85+ (edition 2024)
- FFmpeg 6+ (with development headers for hardware acceleration)
- Bun (for the frontend)
# Backend
cargo build --workspace
# Frontend
cd frontend && bun install && bun run build
# Both (production)
make runmake run-backend # Backend with debug logging
make watch-frontend # Frontend auto-rebuildcargo clippy --workspace -- -D warnings
cargo test --workspace
cd frontend && bunx tsc --noEmitHow do I know if hardware acceleration is working?
Check the server logs on startup:
NVIDIA NVENC hardware acceleration availableVAAPI hardware acceleration availableNo hardware acceleration available, using CPU encoding
During playback, transcode logs show [NVENC] or [VAAPI] if active.
Why FFmpeg and HLS?
All components of the backend pipeline are replaceable via Ports and Adapters. Alternative adapters can be created for the pipeline components.
GPLv3. See LICENSE.