42 lines
1.4 KiB
Markdown
42 lines
1.4 KiB
Markdown
# Restreamer
|
|
|
|
Restreams YouTube livestreams as continuous local streams that Jellyfin (or any player) can watch as Live TV.
|
|
|
|
## How it works
|
|
|
|
1. **yt-dlp** resolves a YouTube livestream URL to a direct, playable stream URL.
|
|
2. **ffmpeg** copies that stream (no re-encoding) into a continuous MPEG-TS byte stream.
|
|
3. A small **async HTTP server** fans that byte stream out to any number of connected clients, and publishes an M3U playlist listing every configured channel.
|
|
4. A **worker per channel** keeps the stream alive indefinitely: it proactively re-resolves the source before the underlying URL expires, and reactively restarts ffmpeg (with backoff) if it ever exits unexpectedly. This is the "session circulation" that keeps a channel from dying every few hours.
|
|
|
|
## Running
|
|
|
|
1. Copy `channels.example.yaml` to `channels.yaml` and list your channels.
|
|
2. Copy `.env.example` to `.env` and adjust as needed (in particular `PUBLIC_BASE_URL`, the address Jellyfin will use to reach this service).
|
|
3. Run with Docker Compose:
|
|
|
|
```bash
|
|
docker compose up --build
|
|
```
|
|
|
|
4. In Jellyfin, add a **Live TV M3U Tuner** pointing at `http://<host>:8000/playlist.m3u`.
|
|
|
|
### Local development
|
|
|
|
```bash
|
|
poetry install
|
|
poetry run python serve.py
|
|
```
|
|
|
|
Requires `ffmpeg` on `PATH`.
|
|
|
|
## Development
|
|
|
|
```bash
|
|
poetry run ruff check
|
|
poetry run mypy
|
|
poetry run pytest
|
|
```
|
|
|
|
See `PROJECT.md` for current status and `DESIGN_DOCUMENT_PYTHON.md` / `AGENTS.md` for project conventions.
|