Files
StreamHall/README.zh-CN.md
T
Stardream 8e1ed10ba5
Build and Push Docker Image / build (push) Successful in 10s
feat: add HLS proxy modes and improve source editor
- per-source HLS proxy mode added with auto, direct, full proxy, and manifest-only options
- manifest-only proxy route rewrites playlist media URLs to upstream absolute URLs
- HLS proxy routes reject private and local network targets
- source editor now shows aligned per-field labels instead of the old format hint
- source proxy mode is saved with each playback source and applied to DRM-specific playback URLs
- mobile source editor adds compact ordering controls for long view-angle forms
- mobile drag handling improved for stream rows and source rows
- README and README.zh-CN document HLS proxy mode tradeoffs
2026-05-25 18:22:46 +10:00

359 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center"><a name="readme-top"></a>
# StreamHall
**自托管直播站点 - 公开列表、播放器、管理后台、观看统计与推送通知**
[English](./README.md) · **简体中文**
[![][license-shield]][license-link]
[![][python-shield]][python-link]
[![][docker-shield]][docker-link]
[![][postgres-shield]][postgres-link]
</div>
---
- [✨ 功能特性](#-功能特性)
- [🚀 快速开始](#-快速开始)
- [💻 本地开发](#-本地开发)
- [⚙️ 配置项](#-配置项)
- [🐳 服务说明](#-服务说明)
- [🔌 推流配置](#-推流配置)
- [📡 API 文档](#-api-文档)
- [🤝 参与贡献](#-参与贡献)
- [📝 许可证](#-许可证)
## ✨ 功能特性
- **公开直播列表** - 直播 / 存档双 Tab,支持密码保护、自定义站点品牌,内置中英双语界面(含分语言站点简介)
- **播放器** - 基于 ArtPlayer,支持 HLS、FLV、MPEG-DASH 播放;支持 AES-128 密钥覆盖及 DASH ClearKey;通过 Shaka Player 支持 Widevine 和 FairPlay DRM 播放(每路播放源可独立配置多 DRM 方案,内置 Android Telegram WebView 检测)
- **管理后台** - 直播的增删改查、启用/禁用、拖拽排序;多播放源管理,支持逐字段标签和代理模式选择
- **观看统计** - 会话追踪、独立访客数、峰值并发、平均时长、设备 / 浏览器 / 操作系统 / 地理分布实时看板,支持 CSV 导出
- **Telegram 推送** - 可按直播单独配置,开播 / 关播自动发送通知
- **推流配置** - 内置文件浏览器,支持单文件和文件夹 RTMP 推流管理;文件夹可同时向多个推流码批量推送独立任务;推流状态内联显示于文件行,详情弹窗提供实时时长、复制地址和停止操作;同时支持远端编码器 RTMP 推流配置;隐藏 HLS 路由代理(`/h/<slug>`),真实推流码不出现在公开地址中
- **VOD 点播 / 视频服务** - 带 HMAC 签名的 `/video/` URL,支持 HTTP Range 请求(可 seek);文件浏览器中可直接将视频文件或文件夹发布为归档直播
- **HLS 代理模式** - 每个播放源可选择直连、完整代理或仅代理 Manifest,在源地址暴露、跨域兼容和服务器带宽之间自行取舍
- **API 密钥鉴权** - 在后台生成 Token,可通过 API 密钥对所有管理及统计接口进行程序化访问
- **移动端适配** - 管理后台侧边栏、视角编辑器、文件浏览器行、推流目录侧边栏均可在窄屏设备上自适应折叠
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🚀 快速开始
**1. 下载并配置**
```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]
> 启动前请打开 `docker-compose.yml`,将 `SECRET_KEY` 和 `POSTGRES_PASSWORD` 改为强随机值。
**2. 启动**
```bash
docker compose up -d
```
**3. 获取初始管理员密码**
```bash
docker logs streamhall
```
在日志中找到:
```
StreamHall initial admin password: <random-password>
```
**4. 访问地址**
| 地址 | 说明 |
|---|---|
| `http://HOST:8085/` | 公开直播列表 |
| `http://HOST:8085/admin` | 管理后台 |
| `http://HOST:18088/` | SRS HTTP 播放 |
| `http://HOST:8889/` | Nginx HLS 代理 |
> [!TIP]
> 首次登录后,请在**网站设置 → 安全设置**中修改密码。初始密码仅打印一次,不会以明文形式存储。
**更新到新版本**
```bash
docker compose pull && docker compose up -d
```
**重置忘记的管理员密码**
```bash
docker exec streamhall-postgres psql -U streamhall -d streamhall \
-c "DELETE FROM site_settings WHERE key='admin_password_hash';"
docker restart streamhall
docker logs streamhall
```
删除密码哈希后,StreamHall 在下次启动时会重新生成随机密码并打印到日志中。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 💻 本地开发
**前置要求:** Python 3.12+、PostgreSQL 14+
```bash
# 1. 克隆仓库
git clone https://git.stdm.moe/Stardream/StreamHall.git
cd StreamHall
# 2. 安装唯一的运行时依赖
pip install -r requirements.txt
# 3. 配置必要的环境变量
export SECRET_KEY=dev-secret
export DATABASE_URL=postgresql://user:pass@localhost:5432/streamhall
# 4. 启动服务
python server.py
```
服务默认监听 `http://localhost:8080`。首次启动时会自动创建数据库结构,并在终端打印一次性管理员密码。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## ⚙️ 配置项
`docker-compose.yml` 中设置以下环境变量:
| 变量 | 默认值 | 是否必填 | 说明 |
|---|---|---|---|
| `SECRET_KEY` | `REPLACE_ME` | **必填** | 会话与推流路由的 HMAC 签名密钥。可用 `openssl rand -hex 32` 生成 |
| `DATABASE_URL` | 见 compose 文件 | **必填** | PostgreSQL 连接字符串 |
| `POSTGRES_PASSWORD` | 见 compose 文件 | **必填** | PostgreSQL 数据库密码 |
| `TZ` | `UTC` | 否 | 容器时区,如 `Asia/Shanghai` |
| `SRS_HTTP_ORIGIN` | `http://srs:8080` | 否 | SRS HTTP 播放基础地址 |
| `STREAM_PROBE_TIMEOUT` | `4` | 否 | 流地址探测超时秒数 |
| `STREAM_MONITOR_INTERVAL` | `10` | 否 | 流存活检测间隔秒数 |
| `TELEGRAM_TIMEOUT` | `6` | 否 | Telegram API 请求超时秒数 |
| `RTMP_HOST` | `srs` | 否 | 本地推流任务使用的 SRS 容器主机名 |
| `VIDEOS_DIRS` | *(未设置)* | 否 | 文件浏览器暴露的目录,逗号分隔。可为每个路径加标签前缀:`label:/app/path`。多个示例:`movies:/app/movies,shows:/app/shows` |
> [!WARNING]
> 在将 StreamHall 暴露到网络前,务必修改 `SECRET_KEY` 和 `POSTGRES_PASSWORD`。默认值仅为占位符,安全性极低。
**挂载本地推流视频目录**
*方式一 - 单一基路径,多个来源作为子目录:*
将多个宿主机路径挂载到同一容器基路径的子目录下,文件浏览器中以子文件夹形式展示。
```yaml
environment:
VIDEOS_DIRS: "/app/videos"
volumes:
- ./videos:/app/videos/local
- /your/media/path:/app/videos/external
```
*方式二 - 多个带标签的顶级目录:*
每个路径在文件浏览器中作为独立的顶级条目显示。
```yaml
environment:
VIDEOS_DIRS: "/app/videos,external:/app/media/external"
volumes:
- ./videos:/app/videos
- /your/media/path:/app/media/external
```
**HLS 代理模式**
每个播放源都可以选择外部 HLS 链接如何暴露给观众:
| 模式 | 行为 | 带宽影响 |
|---|---|---|
| `自动` | 向后兼容默认行为;外部 HLS 使用完整代理 | StreamHall 承担 manifest 和分片流量 |
| `直连` | 播放器直接使用源站 URL | 观众流量走源服务器 |
| `完整代理` | manifest、分片、map、key 都通过 `/proxy/hls/` | StreamHall 承担全部 HLS 媒体流量 |
| `仅 Manifest` | 只有播放列表经过 StreamHall;分片、key、map 改写为源站绝对地址 | StreamHall 带宽较低;最终媒体 URL 仍会出现在浏览器网络请求中 |
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🐳 服务说明
默认 compose 配置启动四个容器:
| 容器名 | 镜像 | 端口 | 用途 |
|---|---|---|---|
| `streamhall` | 本地构建 | `8085→8080` | Python 应用 + 静态前端 |
| `streamhall-postgres` | `postgres:16-alpine` | - | PostgreSQL 持久化数据库 |
| `streamhall-srs` | `ossrs/srs:6` | `1935``18088→8080` | RTMP 推流 + HTTP 播放 |
| `streamhall-nginx-hls` | `nginx:alpine` | `8889→80` | HLS 公开路由代理 |
持久化数据存储在 `./postgres-data/` 目录下。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🔌 推流配置
SRS 在 `1935` 端口接收 RTMP 推流,推流端配置示例:
```
RTMP 服务器: rtmp://HOST:1935/live
推流码: your-stream-key
```
管理后台的**本地推流**页面提供媒体目录文件浏览器。选择单个视频文件可使用自定义推流码发起 RTMP 推流;选择文件夹可同时为其中所有视频分别分配独立推流码并批量启动。每个文件行内联显示推流状态,点击"编辑推流"可查看实时时长、复制推流/播放地址和停止操作。
隐藏公开 HLS 地址(`/h/<slug>/...`)通过 Nginx 在 `8889` 端口对外提供访问,真实推流码不会出现在公开 URL 中。
> [!NOTE]
> RTMP 主机字段支持填写自定义端口,如 `live.example.com:1935`。若使用非标准端口,请勿将 `:1935` 硬编码到地址中。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 📡 API 文档
### 鉴权方式
- **浏览器会话** - 通过 `POST /api?action=login` 登录后设置的 Cookie
- **API 密钥** - 在请求头携带 `Authorization: Bearer <token>`。密钥在后台**网站设置 → API 密钥**处管理。
### 公开接口
| 方法 | 接口 | 说明 |
|---|---|---|
| `GET` | `/api?action=public_list` | 首页直播列表 |
| `GET` | `/api?action=site_settings` | 站点标题、简介、品牌设置 |
| `GET` | `/api?action=get_player_data&id=<public_id>` | 播放器播放源及元数据 |
| `POST` | `/api?action=verify_password` | 验证直播访问密码 |
| `GET` | `/video/<token>/<payload>` | 签名 VOD 点播端点,支持 HTTP Range |
### 管理接口(需鉴权)
| 方法 | 接口 | 说明 |
|---|---|---|
| `POST` | `/api?action=login` | 登录并创建会话 |
| `GET` | `/api?action=logout` | 退出当前会话 |
| `GET` | `/api?action=list_admin` | 完整直播列表 |
| `POST` | `/api?action=add` | 添加直播 |
| `POST` | `/api?action=update` | 修改直播 |
| `POST` | `/api?action=delete` | 删除直播 |
| `POST` | `/api?action=set_stream_enabled` | 切换直播可见状态 |
| `POST` | `/api?action=reorder_streams` | 调整同分组内排序 |
| `POST` | `/api?action=update_site_settings` | 保存网站设置 |
| `GET` | `/api?action=telegram_settings` | 读取 Telegram Bot 配置 |
| `POST` | `/api?action=update_telegram_settings` | 保存 Telegram Bot 配置 |
| `POST` | `/api?action=update_admin_password` | 修改管理员密码 |
| `GET` | `/api?action=list_api_keys` | 列出所有 API 密钥(不返回 Token 明文) |
| `POST` | `/api?action=create_api_key` | 创建密钥(Token 仅返回一次) |
| `POST` | `/api?action=delete_api_key` | 按 `id` 撤销密钥 |
| `GET` | `/api?action=list_pushes` | 列出当前活跃推流任务 |
| `POST` | `/api?action=start_push` | 为指定文件启动 RTMP 推流任务 |
| `POST` | `/api?action=stop_push` | 按推流码停止推流任务 |
| `GET` | `/api?action=list_folder_videos` | 列出目录内可播放文件及签名 URL |
### 统计接口(需鉴权)
| 方法 | 接口 | 说明 |
|---|---|---|
| `GET` | `/api?action=stats_overview` | 汇总数据 |
| `GET` | `/api?action=stats_streams` | 各直播统计明细 |
| `GET` | `/api?action=stats_timeseries` | 分桶观看趋势 |
| `GET` | `/api?action=stats_geo` | 地理分布(国家级) |
| `GET` | `/api?action=stats_stream_detail&id=<id>` | 单场直播详情 |
| `GET` | `/api?action=stats_sessions_page&id=<id>` | 分页会话列表 |
| `GET` | `/api?action=stats_export_csv&range=<range>` | 导出会话 CSV`range``today``7d``30d`(默认)、`all` |
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 💡 致谢
StreamHall 参照 [AniLive](https://anilive.nekoss.cn/) 网站进行重构,该网站提供直播列表功能但未开源。本项目为独立重写实现,与原网站不共享任何代码。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🤝 参与贡献
欢迎提交 Issue 和 Pull Request。较大的改动请先开 Issue 讨论方向。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 📝 许可证
版权所有 © 2026 [Stardream](https://git.stdm.moe/Stardream)。本项目基于 [GNU Affero General Public License v3.0](./LICENSE) 协议开源。
**授权权限**
| | |
|---|---|
| ✅ | 商业使用 |
| ✅ | 修改源代码 |
| ✅ | 分发 |
| ✅ | 私人使用 |
**使用条件**
| | |
|---|---|
| ⚠️ | 开放源码 - 修改后的版本同样必须开源 |
| ⚠️ | 相同许可证 - 衍生作品须采用 AGPL-3.0 协议 |
| ⚠️ | 网络使用视同分发 - 若将修改版作为网络服务运行,须向用户提供完整源码 |
| ⚠️ | 说明修改内容 - 需记录对源码的修改 |
简而言之:你可以自由使用、修改和自部署 StreamHall。但若将修改版对外分发或作为托管服务提供,须以 AGPL-3.0 协议公开完整源码。
---
<!-- LINK GROUP -->
[back-to-top]: https://img.shields.io/badge/-回到顶部-black?style=flat-square
[license-shield]: https://img.shields.io/badge/许可证-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/PostgreSQL-16-336791?labelColor=black&logo=postgresql&logoColor=white&style=flat-square
[postgres-link]: https://www.postgresql.org/