Self-hosted watch parties with synchronized playback, built-in chat, WebRTC calls, invite links, and an admin panel.
SynCinema is for small private groups who want a single app to:
- watch local media in sync
- talk in chat while watching
- jump into video or audio calls beside player
- manage invites, users, and media from one admin UI
Synchronized playback: play, pause, seek, and switch movies for everyone in room.Real-time chat: persistent chat history with reactions and spoiler messages.WebRTC calls: peer-to-peer video and audio calls built into viewing layout.Invite links: create expiring or limited-use sign-up links from admin panel.Admin tools: manage users, movies, downloads, server stats, and broadcasts.SQLite storage: simple self-hosted setup with local databases ininstance/.Optional Cloudflare tunnel: share session without router setup.Health endpoint:GET /api/healthfor smoke checks and container health probes.
Choose one path:
Docker Quick Startfor fastest self-hosted setup.Local Devif you want to run SynCinema directly with Python.
First run is built in:
- Start SynCinema.
- Open
/login. - If no users exist yet, SynCinema shows a first-run setup form.
- Create first account. It becomes admin immediately.
- Add media to
movies/, then invite everyone else from Admin panel.
Requirements:
- Docker
- Docker Compose plugin
Commands:
cp .env.example .env
docker compose up --buildThen open:
http://127.0.0.1:17701/login
Persistent data lives in mounted project folders:
movies/: movie files and.vttsubtitlespfp/: uploaded avatarsinstance/: SQLite databases and generated TLS certs
Useful Docker commands:
docker compose up --build
docker compose down
docker compose logs -fRequirements:
- Python 3.11+ recommended
pip
Commands:
cp .env.example .env
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python app.pyThen open:
http://127.0.0.1:17701/login
Quick smoke check:
python -m unittest discover -s tests -p "test_*.py"
curl http://127.0.0.1:17701/api/healthWindows PowerShell activation:
.venv\Scripts\Activate.ps1SynCinema reads configuration from .env in project root. Start from .env.example.
Important settings:
| Variable | Default | What it does |
|---|---|---|
SECRET_KEY |
temporary local fallback | Flask session secret. Set this for persistent or shared deployments. |
HOST |
127.0.0.1 |
Bind address for local runs. Docker overrides to 0.0.0.0. |
PORT |
17701 |
HTTP port. |
INSTANCE_FOLDER |
instance |
Stores SQLite databases and generated certs. |
MOVIE_FOLDER |
movies |
Media library path. |
AVATAR_FOLDER |
pfp |
Uploaded avatar storage. |
USE_HTTPS |
False |
Generates self-signed certs for LAN/WebRTC use. |
USE_CLOUDFLARE_TUNNEL |
False |
Starts Cloudflare Quick Tunnel for remote access. |
ADMIN_USER |
empty | Optional username to auto-promote to admin after registration. |
MAX_CHAT_MESSAGES |
100 |
Chat history restored on startup. |
Notes:
- If
SECRET_KEYis left unset, SynCinema uses a temporary in-memory key for local runs. - If
USE_CLOUDFLARE_TUNNEL=True, SynCinema requires a realSECRET_KEYat startup. - Runtime folders are created automatically if missing.
Place media files in movies/.
Supported flow:
- video files:
.mp4,.mkv,.webm,.mov, and other common formats - subtitles:
.vttfiles beside movie file with matching base name - avatars: uploaded automatically into
pfp/
Example:
movies/
BladeRunner2049.mkv
BladeRunner2049.en.vtt
BladeRunner2049.it.vtt
Fresh installs no longer require a manual bootstrap hack.
When SynCinema has zero users:
- Open
/login - Create first account
- That account becomes admin
- Open Admin panel
- Generate invite links for everyone else
This keeps public registration closed while still giving new self-hosted installs a clean starting path.
USE_HTTPS=Trueis useful on LAN when browsers need secure context for camera and microphone access.- Self-signed HTTPS will trigger a browser warning until you trust cert once.
- Cloudflare Quick Tunnel is optional and best for lightweight remote access.
- For any shared deployment, set a real
SECRET_KEYin.env.
app.py Flask entrypoint and startup flow
src/config.py environment parsing and runtime defaults
src/routes/ auth, media, invites, admin, health, main pages
src/modules/ Socket.IO event handlers for playback, chat, calls
src/models.py SQLAlchemy models
templates/ Jinja templates
static/ CSS, JS, images
.github/workflows/ GitHub Actions workflows
tests/ minimal smoke and startup tests
SynCinema includes a GitHub Actions workflow for temporary cloud-hosted sessions.
High-level flow:
- Fork repository
- Open
Actions - Run
🎬 Run SynCinema - Register admin account with provided username
- Share generated invite link
Use this for temporary sessions, not durable hosting. Runner storage is ephemeral.
Local checks used in this repo:
python -m compileall app.py src tests
python -m unittest discover -s tests -p "test_*.py"
curl http://127.0.0.1:17701/api/healthExpected health response looks like:
{"cloudflare_tunnel":false,"current_movie":null,"movies":0,"status":"ok","users":0}MIT. See LICENSE.