🎬 MediaStationGo

A Go rewrite of MediaStation β€” your private home media center.

δΈ­ζ–‡

Go React TypeScript SQLite Docker License

--- ## Why a rewrite? The original MediaStation is a Python/FastAPI + Vue project. **MediaStationGo** is a from-scratch reimplementation that adopts a lighter, single-binary deployment model: - **Backend**: Go 1.25 + Gin + GORM + SQLite (WAL mode). - **Frontend**: React 18 + Vite + Tailwind CSS + Zustand. - **Distribution**: ~30 MB static binary (CGO disabled), or a multi-arch Alpine Docker image. The goal is to keep the user-facing feature surface familiar (libraries, scanning, scraping, direct play/HLS, multi-user, downloads, RSS) while making deployment painless on NAS hardware. --- ## Features ### Authentication & Users - βœ… JWT auth with admin/user roles - βœ… First-run admin seeding (`admin / admin123`, override via `ADMIN_INITIAL_PASSWORD`) - βœ… Profile page (email / avatar / change password) - βœ… Admin user table with role promotion / demotion - βœ… Audit log for sensitive actions (login, library CRUD, downloads, etc.) ### Library Management - βœ… Library CRUD + recursive filesystem scan - βœ… ffprobe metadata extraction (duration / resolution / codecs / container) - βœ… Smart filename cleaning with year + season/episode parsing - βœ… Multi-provider scrape chain by library type: - movie β†’ TMDb (with optional Fanart.tv high-res poster upgrade) - tv β†’ TheTVDB (fallback TMDb) - anime β†’ Bangumi (fallback TMDb) - βœ… Image proxy with disk cache (TMDb / Bangumi / Douban / Fanart / TheTVDB) - βœ… TV / anime libraries grouped by season with episode listing - βœ… fsnotify-based filesystem watcher with 5 s coalescing debouncer ### Playback - βœ… Direct-play streaming with HTTP `Range` support - βœ… HLS on-demand transcoding (single ffmpeg job per media) - βœ… External subtitle discovery (.srt / .vtt / .ass / .ssa) with on-the-fly WebVTT conversion - βœ… Resume position written every 10 s + Continue Watching row on home - βœ… Favourites (toggle) + ordered Playlists (CRUD) ### PT Site Management - βœ… Site configuration CRUD - βœ… 6 PT site types: nexusphp / gazelle / unit3d / mteam / discuz / custom_rss - βœ… 3 auth methods: Cookie / API Key / Auth Header - βœ… Site connection testing - βœ… Cross-site torrent search - βœ… Extended config via Extra JSON (User-Agent / RSS URL / timeout / priority / proxy / downloader) ### Automation - βœ… qBittorrent download integration (add / list / delete via Web UI API) - βœ… RSS subscriptions with regex filters, GUID dedup and 10-minute polling - βœ… Automatic media file organization (move / copy / hardlink / symlink) ### Operations - βœ… Real-time scan / scrape / transcode / download / subscription events over WebSocket - βœ… Dashboard at `/stats` (CPU / memory / disk / library counts / Goroutines) - βœ… Real-time tasks panel at `/tasks` (active ffmpeg jobs + qBittorrent torrents) - βœ… NFO export (Kodi / Jellyfin compatibility) β€” single media or whole library - βœ… Hardware-accel encoder profiles: Software / NVENC / Intel QSV / VAAPI - βœ… Single-binary build, multi-arch Docker image, GitHub Actions CI + GHCR publish ### Discovery & AI - βœ… TMDb Discover β€” trending + popular rails on homepage - βœ… AI smart search (OpenAI-compatible) β€” natural-language queries β†’ structured intent - βœ… AI recommendations seeded from your watch history (`GET /api/ai/recommend`) ### Frontend - βœ… React SPA with code-splitting: Login / Home / Library / Search / Favourites / Playlists / Media detail / Player (HLS + direct + subtitles) / Profile / Downloads / Subscriptions / Stats / Admin / Site Management / API Config - βœ… Global toast notifications driven by the WebSocket hub - βœ… Initial bundle ~250 KB / 83 KB gzipped (hls.js loaded only on first HLS playback) ### Roadmap | Feature | Status | |---------|--------| | Bidirectional Jellyfin / Emby compatibility layer | ⏳ | | DLNA / Chromecast | ⏳ | | Online subtitle search providers | ⏳ | | Multi-bitrate ABR transcode profiles | ⏳ | --- ## Quick Start ### Docker ```bash git clone https://github.com/ShukeBta/MediaStationGo.git cd MediaStationGo # (optional) edit docker-compose.yml to mount your media root at /media docker compose up -d ``` Open and log in with `admin / admin123`. ### Bare Metal ```bash # requirements: Go 1.25+, Node 20+, ffmpeg make build # produces bin/mediastation-go and web/dist ./bin/mediastation-go ``` ### Local Development ```bash make dev # backend on :8080, MEDIASTATION_APP_DEBUG=true make dev-web # vite dev server on :3000, proxies /api -> :8080 ``` --- ## Configuration Configuration is layered β€” defaults < `config.yaml` < `config/*.yaml` < environment variables prefixed with `MEDIASTATION_`. ### Most-Used Keys | Key | Default | Purpose | |-----|---------|---------| | `MEDIASTATION_APP_PORT` | `8080` | HTTP listen port | | `MEDIASTATION_APP_DATA_DIR` | `./data` | DB / cache / JWT secret root | | `MEDIASTATION_APP_WEB_DIR` | `./web/dist` | SPA bundle to serve | | `MEDIASTATION_DATABASE_DB_PATH` | `./data/mediastation.db` | SQLite file | | `MEDIASTATION_SECRETS_JWT_SECRET` | *(auto)* | JWT signing key | | `MEDIASTATION_SECRETS_TMDB_API_KEY` | *(empty)* | Enables movie scraping | | `MEDIASTATION_SECRETS_BANGUMI_ACCESS_TOKEN` | *(empty)* | Optional, raises Bangumi rate limit | | `MEDIASTATION_APP_CORS_ORIGINS` | *(empty)* | Allow-list, JSON array | | `ADMIN_INITIAL_PASSWORD` | `admin123` | Bootstrap admin password | ### Runtime Settings (Admin β†’ Settings) These live in the `settings` table and can be edited from the admin UI: | Key | Purpose | |-----|---------| | `qbittorrent.url` | qBittorrent Web UI base URL | | `qbittorrent.username` | qBittorrent user | | `qbittorrent.password` | qBittorrent password | | `qbittorrent.savepath` | Optional default save path for new torrents | After editing, hit **Downloads β†’ Reload Config** (or `POST /api/downloads/reload`) so the qBittorrent client picks up the new credentials. See [`config.example.yaml`](config.example.yaml) for the full surface. --- ## Project Layout ``` MediaStationGo/ β”œβ”€β”€ cmd/server/main.go Application entry point β”œβ”€β”€ internal/ β”‚ β”œβ”€β”€ config/ Viper-based config loader β”‚ β”œβ”€β”€ database/ GORM + SQLite (WAL) bootstrap β”‚ β”œβ”€β”€ model/ GORM data models + AutoMigrate registry β”‚ β”œβ”€β”€ repository/ Thin data-access layer β”‚ β”œβ”€β”€ service/ Business logic β”‚ β”‚ β”œβ”€β”€ auth.go login / register / JWT / seed admin β”‚ β”‚ β”œβ”€β”€ media.go library + media CRUD β”‚ β”‚ β”œβ”€β”€ scanner.go fs walker + ffprobe + scrape kick β”‚ β”‚ β”œβ”€β”€ ffprobe.go ffprobe wrapper β”‚ β”‚ β”œβ”€β”€ tmdb.go TMDb provider β”‚ β”‚ β”œβ”€β”€ bangumi.go Bangumi provider β”‚ β”‚ β”œβ”€β”€ scraper.go orchestrator + filename cleaner β”‚ β”‚ β”œβ”€β”€ site.go PT site CRUD + connection test + cross-site search β”‚ β”‚ β”œβ”€β”€ site_adapter.go 6 PT site type adapters β”‚ β”‚ β”œβ”€β”€ stream.go direct play + HLS playlist / segment β”‚ β”‚ β”œβ”€β”€ transcoder.go per-media ffmpeg HLS job manager β”‚ β”‚ β”œβ”€β”€ subtitle.go external subtitle discovery + .vtt conversion β”‚ β”‚ β”œβ”€β”€ image_proxy.go cached, allow-listed image proxy β”‚ β”‚ β”œβ”€β”€ playback.go history / favourites / playlists β”‚ β”‚ β”œβ”€β”€ watcher.go fsnotify debouncer β”‚ β”‚ β”œβ”€β”€ qbittorrent.go qBittorrent v2 API client β”‚ β”‚ β”œβ”€β”€ downloads.go download orchestrator + WS poller β”‚ β”‚ β”œβ”€β”€ subscription.go RSS poller β”‚ β”‚ β”œβ”€β”€ stats.go dashboard snapshot β”‚ β”‚ β”œβ”€β”€ profile.go non-credential user mutations β”‚ β”‚ β”œβ”€β”€ audit.go audit log writer β”‚ β”‚ β”œβ”€β”€ organizer.go media file organizer β”‚ β”‚ β”œβ”€β”€ ws_hub.go pub/sub broker for the WS β”‚ β”‚ └── walk.go / episode_parser.go helpers β”‚ β”œβ”€β”€ middleware/ Gin middleware (CORS / JWT / admin) β”‚ └── handler/ HTTP route definitions (one file per concern) β”œβ”€β”€ web/ React 18 + Vite SPA β”‚ β”œβ”€β”€ src/api/ axios helpers (one per service) β”‚ β”œβ”€β”€ src/components/ Layout, MediaCard, GlobalEvents, RequireAuth, APIConfigsPanel β”‚ β”œβ”€β”€ src/hooks/ useWebSocket, … β”‚ β”œβ”€β”€ src/pages/ Home / Library / Search / Player / Downloads / Admin / Sites β”‚ β”œβ”€β”€ src/stores/ Zustand (auth) β”‚ └── src/types/ Domain types mirrored from Go β”œβ”€β”€ Dockerfile Multi-stage, multi-arch build β”œβ”€β”€ docker-compose.yml NAS-friendly deployment β”œβ”€β”€ Makefile build / dev / docker / test β”œβ”€β”€ config.example.yaml Full configuration template └── .github/workflows/ CI + GHCR publish ``` --- ## License Released under the [GNU GPL v3.0](LICENSE).