# QMediaSync: STRM generation and 302 playback for Emby

> QMediaSync is a Go service that talks to a cloud drive open platform to generate STRM files, sync metadata, resolve direct links and serve 302 redirects for playback, and it hooks into Emby to delete files, refresh the library and announce new imports.

**qicfan/qmediasync** — 基于 网盘 开放平台接口来同步生成 STRM、元数据下载、元数据上传，直链解析播放和外网302播放，Emby联动删除网盘文件、刷新媒体库、入库通知等

- Repository: https://github.com/qicfan/qmediasync
- Stars: 636 · Forks: 88
- Language: Go
- License: GPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/qicfan-qmediasync

## What the service does for an Emby library

The project description lists the jobs in one breath, and they are worth separating. On the media side it uses the cloud drive open platform interface to synchronise and generate STRM files, which are the small pointer files Emby reads as if a video were local, alongside downloading and uploading metadata. On the playback side it resolves direct links and serves 302 redirects so the stream comes from the drive without being copied to disk. On the library side it integrates with Emby to delete files on the drive, refresh the media library and notify on new imports. The audience is therefore a self-hosted Emby user whose media sits on a drive rather than on a local disk, and who wants the library to behave like a normal one while the bytes stay remote. The frontend is a separate project, QMediaSync-Frontend, so the web interface and the Go service are developed apart.

## Default credentials and four listening ports

The service ships with defaults you should change immediately. The web interface uses the username admin and the password admin123, and it listens on http port 12333 and https port 12332. Separately, the Emby proxy listens on http port 8095 and https port 8094, which is what lets Emby treat a drive link as a playable stream. The four ports are the first thing to check when something does not come up, because the web UI and the Emby proxy are separate listeners and a failure in one looks like a failure in the other. Anything beyond these defaults, the configuration options and the setup notes, lives in the project wiki rather than in the README, so the wiki is part of the installation rather than optional reading.

## Running it from source during development

The debugging entry point is deliberately plain. With the Go toolchain and the source in place, the whole service starts with:
```bash
go run .
```
The module is declared in go.mod as Q115-STRM and targets Go 1.25, so a machine with an older Go toolchain will not build it. The dependency list explains a lot about the shape of the service: gin and gorilla/websocket for the HTTP and websocket layer, gorm with the PostgreSQL driver for storage alongside a pure-Go sqlite driver, robfig/cron for scheduled jobs, golang-jwt for tokens, swaggo for API documentation, telegram-bot-api for notifications, a Telegram integration that pairs with the project's chat channels, pongo2 for templating, id3v2 for tag handling, an Alibaba Cloud OSS client, gopsutil for host metrics and lumberjack for log rotation. Stopping it is also simple: ctrl + c on Linux, and on Windows the tray icon offers an exit.

## Building and publishing with build_and_release.sh

Releases are produced by a script rather than by hand, and the README shows the two commands:
```bash
cd build_scripts
sudo ./build_and_release.sh -v vx.xx.xx
```
The script compiles binaries for every platform, produces a release, publishes it to the GitHub releases page and pushes a container image to Docker Hub. Two prerequisites are named. The build needs the GitHub command line tool with gh permissions and an existing login, and pushing an image needs you to be logged in to Docker Hub beforehand. If you want to push to your own registry, the note is that you change the user name and repository name inside the build script. The version argument is the tag you want, so the release naming and the container tag stay in step by construction.

## Postgres is not included, and the database settings are environment variables

The open source version does not ship the Postgres binaries. You install the database yourself, the README suggests version 15.x, and then you point the service at it through environment variables. The container image shows the expected names, and the list is the same one you would set by hand for a binary install:
```dockerfile
ENV DB_HOST=localhost
ENV DB_PORT=5432
ENV DB_USER=qms
ENV DB_PASSWORD=qms123456
ENV DB_NAME=qms
ENV DB_SSLMODE=disable
```
The defaults are for local development, where the password is a literal string in the image. A deployment on a real network should change the host, the user and the password rather than rely on these values. The repository keeps a postgres/ directory for the assets that go with the database, and the wiki carries the install instructions for Linux, so the database is the piece you plan for separately from the application.

## The four credentials you have to bring yourself

The service cannot run on defaults, because the media and metadata sources all need keys. The cloud drive side needs an AppID from the 115 open platform, and the README notes that this has moved to OAuth authorisation: a developer has to implement an OAuth server to talk to the platform, following the code, or switch to a QR code scan login. That is the hardest of the four to arrange, because it is server-side work rather than a form to fill in. The metadata side needs a TMDB API key and a Fanart.tv API key, both of which can be set in the web interface, and the AI features need an OpenAI-compatible API key, also set in the web interface. All of them are set as variables at the top of main.go, and they can alternatively be injected at compile time through ldflags, which is what the container build does.

## The container image: build arguments and the three exposed ports

The Dockerfile is a two-stage build. The builder starts from a project base image, sets the timezone, points the Go proxy at a domestic mirror with GOSUMDB turned off and CGO disabled, runs go mod tidy, and then compiles with ldflags that inject the version, the publish date and several keys at build time, among them FANART_API_KEY, DEFAULT_TMDB_ACCESS_TOKEN, DEFAULT_TMDB_API_KEY, DEFAULT_SC_API_KEY and ENCRYPTION_KEY. The runtime stage keeps the same base, creates a non-root user with uid 12331, and sets up passwordless sudo for that user, which is worth knowing when you harden a deployment. Two volumes are declared, /app/config and /media, and three ports are published:
```dockerfile
EXPOSE 12333
EXPOSE 8095
EXPOSE 8094
```
So the web interface and both Emby proxy listeners are reachable from the container host, while the configuration directory and the media path are meant to be mounted from outside.

## Where QMediaSync is the wrong tool

Two things push a reader away, and both are stated in the project rather than hidden. The first is the credential requirement: the open source version does not include a 115 open platform account, and the OAuth flow expects you to implement a server of your own or use the QR code login path. An Emby user who simply wants their drive mounted by a plugin or a small script that lists files and writes STRM pointers is better served by that script, since QMediaSync adds a service to run, a database to maintain, a proxy in front of Emby and several keys to rotate, in exchange for the metadata matching, the library hooks and the automatic delete and refresh behaviour. The second is the maintenance picture. The author states that they are too busy and have paused updates, that the verification service stays available, and that new features should be vibed or forked. The last push to the repository was on 2026-09-14 and the newest release is v0.14.23 from 2026-04-09, so the code moves while the feature work does not. The project also states that it accepts pull requests for everything except the resource features, which cover search, subscription and download, and the reverse-engineered interfaces.

## Conclusion

QMediaSync fits Emby users whose library lives on a cloud drive and who want local STRM entries, remote metadata matching and library hooks managed in one place, and who are prepared to run PostgreSQL, obtain platform credentials and build the binary or the container themselves. It does not fit anyone unwilling to hold a 115 platform account, anyone who expects upstream feature work on a schedule, or a setup where the cloud drive must never see the media client. Before adopting it, read the wiki installation page, confirm your PostgreSQL is on version 15 or newer and reachable through the DB_ environment variables, and note that the author has paused feature updates, with the last push on 2026-09-14 and the last release v0.14.23 from 2026-04-09.

## FAQ

### What does QMediaSync actually do?

It uses the cloud drive open platform interface to synchronise and generate STRM files, download and upload metadata, resolve direct links and serve 302 playback, and it integrates with Emby to delete files on the drive, refresh the media library and send notifications when something is imported.

### What are the default login and ports for QMediaSync?

The web interface uses the username admin and the password admin123, on http port 12333 and https port 12332. The Emby proxy listens separately on http port 8095 and https port 8094.

### What do I need to supply to run QMediaSync myself?

Your own PostgreSQL, recommended at version 15.x and configured through the DB_ environment variables, plus a 115 open platform AppID with OAuth authorisation or QR code login, a TMDB API key, a Fanart.tv API key and an OpenAI-compatible API key.

### How is the QMediaSync container configured?

The image declares volumes for /app/config and /media, publishes 12333 for the web interface and 8095 and 8094 for the Emby proxy, and takes its database connection from DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME and DB_SSLMODE. Build arguments inject the version, publish date and API keys through ldflags.

### Is QMediaSync still receiving feature updates?

The author says updates are paused because of other work, that the verification service stays available, and that new features can be vibed or forked. The last push to the repository was on 2026-09-14 and the most recent release is v0.14.23 from 2026-04-09.

## Sources

- [Issues](https://github.com/qicfan/qmediasync/issues)
- [License: GPL-3.0](https://github.com/qicfan/qmediasync/blob/main/LICENSE)
- [qicfan/qmediasync on GitHub](https://github.com/qicfan/qmediasync)
- [README](https://github.com/qicfan/qmediasync/blob/main/README.md)
- [Releases](https://github.com/qicfan/qmediasync/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/qicfan-qmediasync
