truewhile 67b85840dc perf(strm): 优化 OpenList 元数据下载速度 (#15)
* Add favourite buttons to library list and series detail pages

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* Fix favourites list for remote Emby mounted media

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* Route favourites to library series detail when appropriate

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* Fix favourites link to library series for remote anime paths

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* Fix remote Emby playback history and continue watching

- Preserve duration_ms when web player reports duration=0
- Add GET /playback/:id/resume for reliable per-item resume
- Switch home continue watching to /watch-history/continue API
- Set library_id on remote media for play-profile visibility
- Keep continue-watching rows when remote metadata hydration fails

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* Fix mobile sort dropdown overflowing off-screen

Align dropdown to button left edge on small screens and cap width
to viewport so sort options stay fully visible on mobile.

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* Remove stale Windows binary backup files

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* Fix STRM account edit form not echoing saved config

Return config_preview from account API for server/url/username and
secret flags. Merge partial config updates so empty password/token
fields do not wipe stored credentials.

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* perf(strm): speed up OpenList metadata downloads with provider-aware concurrency

- Split download semaphore: 115 stays capped at 3 for WAF safety; OpenList/CloudDrive2
  WebDAV metadata uses strm.download_threads (default raised to 6, max 16)
- Scope 115 WAF cooldown to 115 tasks only so OpenList downloads are not paused
- Requeue claimed tasks back to pending when slot acquisition fails or 115 is cooling
- Add tests for separate semaphores and requeue behavior

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
2026-09-02 15:15:49 +08:00
2026-08-24 17:40:43 +08:00
2026-08-24 17:40:43 +08:00
2026-08-24 17:40:43 +08:00
2026-08-24 17:40:43 +08:00
2026-08-24 17:40:43 +08:00
2026-08-29 22:16:21 +08:00
2026-08-29 22:16:21 +08:00

MMTL (My Movie and TV Library)

MMTL Logo

A self-hosted media center for NAS and home theater

Libraries · Metadata · Cloud STRM · Emby protocol · Remote Emby mounts · Multi-user · Docker-first

中文 · Overview · Quick Start · Deployment · Acknowledgements · Development

Go React Docker License


Overview

MMTL is a self-hosted private media management system for NAS, mini PCs, family sharing, and multi-device playback. This repository is a maintained fork of MediaStationGo, extended with stronger cloud playback, task queues, remote mounts, and permission controls.

In practice, MMTL gives you:

  • A modern web media library
  • An Emby/Jellyfin-compatible protocol gateway for third-party players
  • A single panel for local disks, download folders, and cloud storage

Key capabilities

Area Highlights
Libraries Movies, TV, anime, variety, music, custom libraries; multi-root scanning; poster wall; continue watching
Metadata TMDb, Bangumi, Douban, TheTVDB, Fanart, NFO import, manual matching, scrape queue
Playback Web player, HLS transcoding, danmaku, subtitles, play profiles, history and favourites
Emby protocol Add MMTL in Infuse, SenPlayer, Fileball, etc. and sign in with MMTL accounts
Remote Emby mounts Browse remote Emby libraries inside MMTL without a separate Emby client
Cloud & STRM OpenList, CloudDrive2, 115, WebDAV; STRM sync; upload/download queues; direct or 302 playback
Downloads & organize qBittorrent, site search/subscriptions, post-download organization, file manager
Users & permissions Admin/regular users, expiry, NSFW toggle, play-profile PIN, granular permissions
Operations Unified task queue, recycle bin, storage stats, DLNA casting, settings and logs

Tech stack

  • Backend: Go, Gin, GORM, SQLite or PostgreSQL, optional Redis and OpenSearch
  • Frontend: React 18, Vite, TypeScript, Tailwind CSS, Zustand
  • Deployment: Standalone Docker Compose templates, amd64/arm64 images, single-binary releases

Quick Start

Docker Compose is the recommended path. The repo ships four standalone templates; no .env is required.

mkdir -p MMTL && cd MMTL

# Simplest: one container with built-in SQLite
curl -fsSL https://raw.githubusercontent.com/truewhile/MMTL/main/docker-compose.simple.yml -o docker-compose.yml

# Or PostgreSQL tier for multi-user setups
# curl -fsSL https://raw.githubusercontent.com/truewhile/MMTL/main/docker-compose.yml -o docker-compose.yml

docker compose up -d

Open:

http://SERVER_IP:18080

Default login: admin / admin123 — change the password immediately.

Image:

ghcr.io/truewhile/mmtl:latest

Deployment tiers

Pick one compose file. Do not stack multiple -f files.

Tier File Stack Best for
Single image docker-compose.simple.yml MMTL + SQLite Beginners, single-user, low-resource NAS
Tier 1 docker-compose.yml MMTL + PostgreSQL Most home NAS deployments
Tier 2 docker-compose.standard.yml + Redis Multi-user, frequent Emby client refreshes
Tier 3 docker-compose.search.yml + OpenSearch Very large libraries, advanced full-text search

Single-image notes

  • Only one MMTL container; database lives in ./data/mmtl.db
  • Do not set MMTL_DATABASE_DSN or it switches to PostgreSQL
  • Back up ./data; ./cache can be rebuilt

PostgreSQL notes

  • Primary DB: ./postgres; secrets and runtime files: ./data
  • Existing ./data/mmtl.db migrates automatically on first start
  • After migration, point MMTL_DATABASE_DB_PATH at a non-existent file to disable re-checks

Backup

Path Notes
./data JWT secret, config, SQLite DB or migration source
./postgres PostgreSQL primary DB
./cache, ./redis, ./opensearch Rebuildable

Update

docker compose pull mmtl
docker compose up -d --no-deps mmtl

Path mapping

The most common Docker mistake is mixing host paths with container paths.

  • Left side of volumes = real host/NAS path
  • Right side = container path; use /media/... in the web UI
  • Keep MMTL_MEDIA_DIR / MMTL_DOWNLOAD_DIR aligned with mounts when organizing or ingesting downloads

Example:

volumes:
  - /vol1/1000/Media:/media
  - /vol1/1000/Downloads:/downloads
environment:
  MMTL_MEDIA_DIR: /vol1/1000/Media
  MMTL_MEDIA_CONTAINER_DIR: /media
  MMTL_DOWNLOAD_DIR: /vol1/1000/Downloads
  MMTL_DOWNLOAD_CONTAINER_DIR: /downloads

First-time setup

  1. Create a library with a container path such as /media/Movies, then scan
  2. Add metadata providers (TMDb, Bangumi, etc.) in system settings
  3. Optionally connect qBittorrent (http://host.docker.internal:8085 when qB runs on the host)
  4. Optionally configure cloud accounts under STRM management
  5. Add the server in Emby-compatible players at http://SERVER_IP:18080 using MMTL credentials

FAQ

Library scan is slow
Check path mapping and DB tier. Cloud scans also depend on API limits and folder size.

qBittorrent downloads are not organized
Ensure the download directory is mounted into the container and env vars match.

Hardlink fails with cross-device link
Hardlinks require the same filesystem/subvolume; use copy or symlink across disks or cloud mounts.

External player cannot connect
Use http://IP:18080 and a MMTL user account; reverse proxies need correct external URL and HTTPS headers.


Development

The backend embeds web/dist via go:embed. Build the frontend first.

npm --prefix web ci
npm --prefix web run build

go test ./...
go run ./cmd/server
npm --prefix web run dev

Release builds ship single-file binaries for Windows, Linux, and macOS on amd64 and arm64.


Acknowledgements

MMTL is forked from and continues to evolve MediaStationGo. Thank you to the upstream project for the media-library architecture, Emby-protocol compatibility, and self-hosted foundation.

Many cloud sync, STRM, and media-organization ideas in this project were also informed by qmediasync. Thank you for the reference implementation and design patterns.


Contributing

See CONTRIBUTING.md and SECURITY.md before opening issues or pull requests.


Star History

Star History Chart

License

This project is licensed under GPL-3.0.

S
Description
No description provided
Readme 76 MiB
Languages
Go 74.3%
TypeScript 25.6%