SyncTV: self-hosted synchronized video rooms in Rust
Synchronized viewing, theater, live streaming, video
At a glance
- What is it?
- SyncTV is a Rust workspace that keeps playback state aligned across viewers while pulling media from providers like Emby, Jellyfin and Bilibili. Here is what the repository shows, how to start it with Docker Compose, and where the design gets thin.
- Who is it for?
- Adopt SyncTV if you already run PostgreSQL and Redis and you want one binary that does room synchronization, provider pulls and WHIP/RTMP ingest instead of stitching three services together. Do not adopt it if you need a documented rollback path for migrations, or if you expect the README to walk you through production sizing; the README defers to docs.syncs.tv for that.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem SyncTV solves, and who it is actually for
Watching a file together over a chat call means one person holds the play button and everyone else drifts. SyncTV's answer is a server that owns playback state and broadcasts it. The README describes it as "a Rust implementation of a real-time synchronized video watching platform with media provider integration, livestreaming, HTTP/gRPC APIs, and Kubernetes-ready horizontal scaling." That sentence is the whole product brief.
The audience is narrower than the tagline suggests. You need PostgreSQL, and the compose file also expects Redis, so this is a service you operate, not a desktop app you double-click. The provider list is the real draw: Bilibili, Twitch, YouTube, Douyin, TikTok, Huya, Douyu, AcFun, CCTV, Alist, Cloudreve, Emby/Jellyfin, FNOS, QNAP, Synology, Nextcloud, Seafile, TrueNAS, direct URLs and livestream sources. If your library lives in Jellyfin or Emby, SyncTV pulls from it rather than asking you to re-upload anything. If you only ever watch files sitting on your own disk, a plain shared player is less work.
One thing the README does not do is explain the room model, permissions, or what a "theater" is beyond the repository description. Those details live on docs.syncs.tv, which the README links as the complete documentation. Treat the README as an index, not a manual.
How synchronization and the provider layer fit together
The workspace layout is the clearest description of the architecture. Cargo.toml lists the members, and they separate cleanly: synctv-core holds the domain logic, synctv-api-http and synctv-api-grpc are two front ends over the same service, synctv-realtime handles live state, synctv-media-providers holds the provider integrations, synctv-livestream covers ingest and playback, synctv-cluster handles multi-node coordination, and synctv-web-ui is the browser client.
That split tells you the data flow. A client talks to the HTTP REST API or the public gRPC API; room state changes go out over WebSocket, which the README lists among the runtime surfaces. PostgreSQL is the durable store, and the README calls Redis "optional shared state, cache, rate limiting, and cluster coordination." Optional is the operative word: a single node can run without it, but the compose file wires Redis in anyway, and synctv-cluster exists precisely because more than one node needs a shared view of which room lives where.
The livestream side is a separate path. The README lists WHIP and RTMP publishing with WHEP, HLS and HTTP-FLV playback, plus external WHEP, RTSP, RTMP and HTTP-FLV pull with cross-node live relay. In practice that means SyncTV can ingest a stream, relay it between nodes, and hand it to viewers in whichever of those four protocols their player speaks. The Dockerfile hints at the cost: it installs nasm, cmake and perl for "vendored builds (xiu/opus dependencies)", so the media stack is compiled in rather than called out to a system ffmpeg.
Installing SyncTV with Docker Compose
The repository ships docker-compose.yml with three services: postgres on image postgres:18, redis on redis:8, and synctv on synctvorg/synctv. Each service reads its own env file, and all three are marked required, so the stack will refuse to start until you create them. The Makefile names them explicitly: .env.postgres, .env.redis and .env.synctv. The repository provides .env.postgres.example, .env.redis.example and .env.synctv.example as starting points, so copy each one to its non-example name before the first run.
cp .env.postgres.example .env.postgres
cp .env.redis.example .env.redis
cp .env.synctv.example .env.synctv
docker compose up -dThe synctv service publishes two ports: 8080 for the HTTP surface and 1935 for RTMP ingest. It depends on postgres and redis reaching their health checks, so the app container will not start until both report healthy. Application data goes to the named volume synctv_data, mounted at /data, which the compose file sets through SYNCTV_DATA_DIR.
environment:
SYNCTV_DATA_DIR: /data
ports:
- "8080:8080"
- "1935:1935"The container health check is not on port 8080. It polls http://localhost:8081/health/ready inside the container, so if you put SyncTV behind a reverse proxy, that is the path to point your orchestrator at. The image tag is parameterized as synctvorg/synctv:${SYNCTV_IMAGE_TAG:-latest}; pinning SYNCTV_IMAGE_TAG to a released version such as v1.0.4 avoids surprise upgrades on restart. For Kubernetes, the repository carries a helm/ directory, and the Dockerfile builds with the k8s feature enabled by default alongside mimalloc and openapi.
One gap worth naming: the README says native clients are downloaded from the client downloads guide on docs.syncs.tv or from the separate SyncTV App releases repository, and that store builds go through supported app stores. The README gives no command for installing a desktop or mobile client.
Where SyncTV gets awkward: migrations, clusters and provider drift
The migrations/ directory at the repository root holds versioned SQL, and the Dockerfile sets SQLX_OFFLINE=true so query macros compile against checked-in .sqlx metadata instead of a live database. That is a sound build choice, but it means schema changes ship inside the binary. The README does not document rollback, and neither does the compose file: there is no downgrade command, no migration version pin, and no stated policy for what happens when you run an older image against a newer schema. If you upgrade across releases and something breaks, the recovery path is your own database backup, not a documented procedure.
Cluster mode has a similar shape. synctv-cluster and the Redis-backed coordination are listed as capabilities, but the README does not describe how nodes discover each other, what happens to a room when its owning node dies, or whether live relay survives a node restart. The Helm chart exists, which implies Kubernetes is a supported target, yet nothing in the README states the minimum replica count or the failure semantics.
Provider integrations are the third soft spot. The list is long, and several entries are network appliances or cloud storage (QNAP, Synology, TrueNAS, Nextcloud, Seafile, FNOS). Each depends on that product's own API staying stable. The README does not say whether providers are maintained as first-class modules or best-effort adapters, and synctv-media-providers is a single crate, so a breaking change in one upstream API is a change in shared code. If a provider you depend on is a small part of that crate, assume it gets less attention than the popular ones.
How SyncTV differs from Jellyfin and from a plain sync extension
Jellyfin is the obvious comparison because SyncTV lists Emby/Jellyfin as a provider, which means the two are not competitors in the way it first appears. Jellyfin is a media server: it catalogs your library, transcodes, and serves it. SyncTV has no catalog and no library management in the README; it connects to Jellyfin and drives playback in a shared room. Running both is a normal arrangement.
The real alternative is browser-extension synchronization, where each viewer installs a plugin that watches the player's DOM and reports position changes. That approach needs no server, no PostgreSQL and no Redis, and it works on sites you cannot self-host. Its failure mode is exactly what SyncTV is built to avoid: extensions cannot synchronize a stream that is not playing in a browser tab, they cannot relay RTMP or RTSP, and they break whenever a site changes its player markup. SyncTV's server-side room state does not care what the client renders, and its livestream path handles sources no extension can reach.
The trade is operational. An extension costs a browser install. SyncTV costs a PostgreSQL instance, a Redis instance, a container with a health endpoint on 8081, and an upgrade process whose rollback story is undocumented.
Maintenance, licensing and what an upgrade actually costs you
The repository is not archived, and the last push was on 2026-09-28. Releases have been frequent and close together: v1.0.2 on 2026-08-12, v1.0.3 on 2026-08-21, v1.0.4 on 2026-08-31. The workspace version in Cargo.toml is 1.0.4, matching the newest release tag. That cadence means you should expect to move the image tag rather than sit on one build for a year.
Upgrade cost is dominated by the database, not the binary. Because SQLx migrations are embedded and the README documents no rollback, the cheap insurance is a dump before you bump SYNCTV_IMAGE_TAG. The Makefile also exposes build-time knobs, with SYNCTV_BUILD_FEATURES defaulting to k8s,mimalloc,openapi in the Dockerfile, so a custom image can drop features you do not use and shrink the build.
The licence is MIT, stated in the README, the Cargo.toml workspace metadata and the LICENSE file. MIT is permissive: you can run it commercially and modify it, and the main obligation is preserving the copyright notice and licence text in distributed copies. That is a description of the licence terms, not legal advice; if you redistribute SyncTV inside a product, have counsel read the LICENSE file rather than this paragraph.
Editorial conclusion
Adopt SyncTV if you already run PostgreSQL and Redis and you want one binary that does room synchronization, provider pulls and WHIP/RTMP ingest instead of stitching three services together. Do not adopt it if you need a documented rollback path for migrations, or if you expect the README to walk you through production sizing; the README defers to docs.syncs.tv for that. Before you commit, read migrations/ to see what a downgrade would cost, and check whether your media source is in the provider list, since the room is only as useful as the sources it can pull from.
Frequently asked questions
What is SyncTV?
SyncTV is a self-hosted server for synchronized video watching, written in Rust. The README describes it as a real-time synchronized video watching platform with media provider integration, livestreaming, HTTP/gRPC APIs and Kubernetes-ready horizontal scaling, and it supports providers such as Emby, Jellyfin, Bilibili and YouTube.
How do I install SyncTV with Docker?
The repository ships a docker-compose.yml with postgres, redis and synctv services, and each service requires its own env file: .env.postgres, .env.redis and .env.synctv. Example files are provided for all three, so copy each example to its real name and then run docker compose up -d.
Which ports does SyncTV use?
The compose file publishes 8080 for the HTTP surface and 1935 for RTMP ingest. The container health check polls http://localhost:8081/health/ready inside the container, so that is the readiness path to use behind a proxy.
Does SyncTV need PostgreSQL and Redis?
PostgreSQL is the durable store and the compose file marks its env file as required. Redis is described in the README as optional shared state, cache, rate limiting and cluster coordination, but the shipped compose file still wires it in as a dependency.
Where do I download the SyncTV client?
The README points to the client downloads guide on docs.syncs.tv and to the separate SyncTV App releases repository, and it notes that store builds are distributed through supported app stores. It does not give an install command for any client.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/synctv-org-synctv)