Add initial Restreamer implementation for YouTube-to-Jellyfin live restreaming

This commit is contained in:
2026-09-27 11:19:19 +02:00
parent 70f2d191dc
commit a0b38c48e2
29 changed files with 2927 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
import asyncio
import signal
from aiohttp import web
from loguru import logger
from restreamer.broadcaster import ChannelBroadcaster
from restreamer.channel_worker import ChannelWorker
from restreamer.config import ChannelConfig, Settings
from restreamer.http_server import create_app
from restreamer.resolver import StreamResolver
class RestreamerManager:
def __init__(self, settings: Settings, channels: list[ChannelConfig], resolver: StreamResolver) -> None:
self._settings = settings
self._channels = channels
self._resolver = resolver
self._broadcasters = {channel.id: ChannelBroadcaster(channel.id) for channel in channels}
self._workers = [
ChannelWorker(channel, resolver, self._broadcasters[channel.id]) for channel in channels
]
async def run(self) -> None:
base_url = self._settings.public_base_url or f"http://{self._settings.http_host}:{self._settings.http_port}"
app = create_app(self._channels, self._broadcasters, base_url)
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, self._settings.http_host, self._settings.http_port)
await site.start()
logger.info("HTTP server listening on {}:{}", self._settings.http_host, self._settings.http_port)
logger.info("Playlist available at {}/playlist.m3u", base_url)
worker_tasks = [asyncio.create_task(worker.run()) for worker in self._workers]
stop_event = asyncio.Event()
loop = asyncio.get_running_loop()
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, stop_event.set)
await stop_event.wait()
logger.info("Shutting down")
for worker in self._workers:
worker.stop()
await asyncio.gather(*worker_tasks, return_exceptions=True)
await runner.cleanup()