3 из 61 мин

Как это работает внутри: индексатор → плейлист → стрим

Проект устроен как конвейер: Telegram-канал → каталог → эфир.

1) Индексатор пробегает канал, находит аудио и GIF/MP4, читает теги и формирует playlist.json.

2) /playlist?mix=&energy= отдаёт JSON с треками и визуалами уже в нужном порядке под текущие ручки.

3) /audio/{id} и /gif/{id} запрашивают медиа в Telegram и отдают его в браузер.

Ключевой принцип: аудио не сохраняется на диск. Сервер отдаёт данные потоково (chunked) по мере получения.

Визуалы кэшируются на диск, потому что они короткие и повторяются, а кэш заметно ускоряет переключения.

Самая важная часть (то, что превращает канал в эфир):

@app.get("/audio/{message_id}")
async def audio(message_id: int):
    async def gen():
        async for chunk in telethon_stream_bytes(message_id):
            yield chunk  

    return StreamingResponse(
        gen(),
        media_type="audio/mpeg",
        headers={"Cache-Control": "no-store", "Accept-Ranges": "none"},
    )

— @app.get(“/audio/{message_id}”)
Маршрут: GET /audio/12345 попадает сюда, {message_id} это ID сообщения с треком в Telegram.

— async def audio(message_id: int):
Асинхронный обработчик, чтобы сервер не блокировался во время загрузки/отдачи. int фиксирует тип параметра.

— async def gen(): … yield chunk
Асинхронный генератор: читает трек из Telegram порциями (async for) и сразу отдаёт каждый кусок (yield).

— StreamingResponse(gen(), …)
Оборачивает поток в корректный HTTP-стрим: воспроизведение может начаться до полной загрузки файла.

— media_type=“audio/mpeg”
Явно задаёт Content-Type, чтобы браузер правильно воспроизводил аудио.

— headers
no-store — не кэшировать аудио. Accept-Ranges: none — без Range-запросов (перемотка/дозагрузка “с середины” не предусмотрены).

Оглавление серии
  1. Радио из Telegram в один клик
  2. Две ручки настроения: стиль и энергия
  3. Как это работает внутри: индексатор → плейлист → стрим
  4. Инженерная реальность: плеер, фон и PWA
  5. Проект развивается медленно
  6. Without Streaming перестал быть плеером и стал радиостанцией