# StreamHall **Self-hosted live stream hall - public list, player, admin panel, analytics & push notifications** **English** · [简体中文](./README.zh-CN.md) [![][license-shield]][license-link] [![][python-shield]][python-link] [![][docker-shield]][docker-link] [![][postgres-shield]][postgres-link]
--- - [✨ Features](#-features) - [🚀 Quick Start](#-quick-start) - [💻 Local Development](#-local-development) - [⚙️ Configuration](#️-configuration) - [🐳 Services](#-services) - [🔌 Stream Push](#-stream-push) - [📡 API](#-api) - [🤝 Contributing](#-contributing) - [📝 License](#-license) ## ✨ Features - **Public stream list** - Live and archive tabs, password-protected streams, custom site branding, bilingual UI (Chinese / English) with per-language site description - **Player** - HLS, FLV, MPEG-DASH playback via ArtPlayer; AES-128 key override and DASH ClearKey support - **Admin panel** - Add, edit, reorder, enable/disable streams; manage sources; drag-and-drop ordering - **Viewer analytics** - Session tracking, unique visitors, peak concurrent viewers, average watch duration, device / browser / OS / geography breakdown, real-time dashboard, CSV export - **Telegram notifications** - Per-stream push messages on stream start and stop - **Stream push** - SRS RTMP publishing helpers, hidden HLS route proxy so real stream keys are never exposed publicly - **HLS proxy** - Signed `/proxy/hls/` routes for cross-origin HLS playback - **API key auth** - Generate per-key tokens in the admin panel for programmatic access to all admin and analytics endpoints
[![][back-to-top]](#readme-top)
## 🚀 Quick Start **1. Download and configure** ```bash curl -LO https://git.stdm.moe/Stardream/StreamHall/raw/branch/main/docker-compose.yml curl -LO https://git.stdm.moe/Stardream/StreamHall/raw/branch/main/nginx-hls.conf ``` > [!IMPORTANT] > Open `docker-compose.yml` and change `SECRET_KEY` and `POSTGRES_PASSWORD` to strong random values before starting. **2. Start** ```bash docker compose up -d ``` **3. Find the initial admin password** ```bash docker logs streamhall ``` Look for: ``` StreamHall initial admin password: ``` **4. Access** | URL | Description | |---|---| | `http://HOST:8085/` | Public stream list | | `http://HOST:8085/admin` | Admin panel | | `http://HOST:18088/` | SRS HTTP playback | | `http://HOST:8889/` | Nginx HLS proxy | > [!TIP] > After first login, change your password under **Site Settings → Security**. The initial password is printed once and not stored in plaintext. **Updating to a newer version** ```bash docker compose pull && docker compose up -d ```
[![][back-to-top]](#readme-top)
## 💻 Local Development **Prerequisites:** Python 3.12+, PostgreSQL 14+ ```bash # 1. Clone the repo git clone https://git.stdm.moe/Stardream/StreamHall.git cd StreamHall # 2. Install the single runtime dependency pip install -r requirements.txt # 3. Export required environment variables export SECRET_KEY=dev-secret export DATABASE_URL=postgresql://user:pass@localhost:5432/streamhall # 4. Start the server python server.py ``` The app listens on `http://localhost:8080` by default. On first startup it creates the database schema and prints a one-time admin password to stdout.
[![][back-to-top]](#readme-top)
## ⚙️ Configuration Set these environment variables in `docker-compose.yml`: | Variable | Default | Required | Description | |---|---|---|---| | `SECRET_KEY` | `change-this-secret` | **Yes** | HMAC signing key for sessions and stream routes | | `DATABASE_URL` | see compose file | **Yes** | PostgreSQL connection string | | `POSTGRES_PASSWORD` | see compose file | **Yes** | PostgreSQL password | | `TZ` | `UTC` | No | Container timezone, e.g. `Asia/Shanghai` | | `SRS_HTTP_ORIGIN` | `http://srs:8080` | No | SRS HTTP playback base URL | | `STREAM_PROBE_TIMEOUT` | `4` | No | Seconds before aborting a stream URL probe | | `STREAM_MONITOR_INTERVAL` | `10` | No | Seconds between stream liveness checks | | `TELEGRAM_TIMEOUT` | `6` | No | Seconds before aborting a Telegram API call | > [!WARNING] > Always change `SECRET_KEY` and `POSTGRES_PASSWORD` before exposing StreamHall to a network. The defaults are intentionally weak placeholders.
[![][back-to-top]](#readme-top)
## 🐳 Services The default compose stack starts four containers: | Container | Image | Port(s) | Purpose | |---|---|---|---| | `streamhall` | local build | `8085→8080` | Python app + static frontend | | `streamhall-postgres` | `postgres:16-alpine` | - | PostgreSQL persistent database | | `streamhall-srs` | `ossrs/srs:6` | `1935`, `18088→8080` | RTMP publishing + HTTP playback | | `streamhall-nginx-hls` | `nginx:alpine` | `8889→80` | Clean public HLS route proxy | Persistent data is stored in `./postgres-data/`.
[![][back-to-top]](#readme-top)
## 🔌 Stream Push SRS handles RTMP publishing on port `1935`. Configure your encoder as follows: ``` RTMP server: rtmp://HOST:1935/live Stream key: your-stream-key ``` The admin panel's **Stream Setup** section generates a hidden public HLS URL (`/h//...`) that routes through nginx on port `8889`, keeping the real stream key out of the public URL. > [!NOTE] > The RTMP host field accepts an optional port, e.g. `live.example.com:1935`. Do not hard-code `:1935` if you use a non-standard port.
[![][back-to-top]](#readme-top)
## 📡 API ### Authentication - **Browser session** - cookie set by `POST /api?action=login` - **API key** - send `Authorization: Bearer ` header, or append `?api_key=` to any admin endpoint. Keys are managed in the admin panel under **Site Settings → API Keys**. ### Public Endpoints | Method | Endpoint | Description | |---|---|---| | `GET` | `/api?action=public_list` | Stream list for the public homepage | | `GET` | `/api?action=site_settings` | Site title, description, branding | | `GET` | `/api?action=get_player_data&id=` | Player sources and metadata | | `POST` | `/api?action=verify_password` | Verify a stream password | ### Admin Endpoints | Method | Endpoint | Description | |---|---|---| | `POST` | `/api?action=login` | Authenticate and start a session | | `GET` | `/api?action=logout` | End the current session | | `GET` | `/api?action=list_admin` | Full stream list | | `POST` | `/api?action=add` | Add a stream | | `POST` | `/api?action=update` | Update a stream | | `POST` | `/api?action=delete` | Delete a stream | | `POST` | `/api?action=set_stream_enabled` | Toggle stream visibility | | `POST` | `/api?action=reorder_streams` | Reorder within a label group | | `POST` | `/api?action=update_site_settings` | Save site settings | | `GET` | `/api?action=telegram_settings` | Read Telegram bot config | | `POST` | `/api?action=update_telegram_settings` | Save Telegram bot config | | `POST` | `/api?action=update_admin_password` | Change admin password | | `GET` | `/api?action=list_api_keys` | List API keys (tokens not returned) | | `POST` | `/api?action=create_api_key` | Create a key - token returned once | | `POST` | `/api?action=delete_api_key` | Revoke a key by `id` | ### Analytics Endpoints | Method | Endpoint | Description | |---|---|---| | `GET` | `/api?action=stats_overview` | Aggregated totals | | `GET` | `/api?action=stats_streams` | Per-stream stats table | | `GET` | `/api?action=stats_timeseries` | Bucketed view counts | | `GET` | `/api?action=stats_geo` | Country-level visitor counts | | `GET` | `/api?action=stats_stream_detail&id=` | Single-stream detail | | `GET` | `/api?action=stats_sessions_page&id=` | Paginated session list | | `GET` | `/api?action=stats_export_csv` | Export sessions as CSV |
[![][back-to-top]](#readme-top)
## 💡 Acknowledgements StreamHall was inspired by [AniLive](https://anilive.nekoss.cn/), a live stream listing site that is not open-source. This project is an independent reimplementation built from scratch, sharing no code with the original site.
[![][back-to-top]](#readme-top)
## 🤝 Contributing Issues and pull requests are welcome. Please open an issue first for major changes so the direction can be discussed.
[![][back-to-top]](#readme-top)
## 📝 License Copyright © 2026 [Stardream](https://git.stdm.moe/Stardream). This project is licensed under the [GNU Affero General Public License v3.0](./LICENSE). **Permissions** | | | |---|---| | ✅ | Commercial use | | ✅ | Modification | | ✅ | Distribution | | ✅ | Private use | **Conditions** | | | |---|---| | ⚠️ | Disclose source - modified versions must also be open-source | | ⚠️ | Same license - derivative works must use AGPL-3.0 | | ⚠️ | Network use = distribution - if you run a modified version as a network service, you must make the source available to users | | ⚠️ | State changes - modifications must be documented | In short: you are free to use, modify, and self-host StreamHall. If you distribute or offer a modified version as a hosted service, you must publish the full source under AGPL-3.0. --- [back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-black?style=flat-square [license-shield]: https://img.shields.io/badge/license-AGPL--3.0-white?labelColor=black&style=flat-square [license-link]: ./LICENSE [python-shield]: https://img.shields.io/badge/python-3.12-blue?labelColor=black&logo=python&logoColor=white&style=flat-square [python-link]: https://www.python.org/ [docker-shield]: https://img.shields.io/badge/docker-compose-2496ED?labelColor=black&logo=docker&logoColor=white&style=flat-square [docker-link]: https://docs.docker.com/compose/ [postgres-shield]: https://img.shields.io/badge/postgres-16-336791?labelColor=black&logo=postgresql&logoColor=white&style=flat-square [postgres-link]: https://www.postgresql.org/