diff --git a/.env.example b/.env.example index 38bbe0b..267a27f 100644 --- a/.env.example +++ b/.env.example @@ -27,10 +27,18 @@ AdminSeed__Password=change-me-strong-admin-password # и volumes в docker-compose.yml). Не меняй RootPath без синхронного изменения тома. Storage__RootPath=/media Storage__SegmentSeconds=2 +# Сколько сегментов держать в скользящем окне live-плейлиста. +Storage__LiveWindowSegments=10 Storage__KeepOriginals=false # Порог свободного места, ниже которого загрузка отклоняется (10 ГБ). Storage__MinFreeSpaceBytes=10737418240 +# ── Планировщик эфира ────────────────────────────────────────────────────── +# На сколько дней вперёд держать расписание; сколько часов прошлого хранить; период тика. +Scheduler__HorizonDays=3 +Scheduler__RetentionHours=24 +Scheduler__TickMinutes=30 + # ── Обработка медиа (ffmpeg) ─────────────────────────────────────────────── Media__FfmpegPath=/usr/bin/ffmpeg Media__FfprobePath=/usr/bin/ffprobe diff --git a/backend/src/TeleWave.Api/Endpoints/StreamingEndpoints.cs b/backend/src/TeleWave.Api/Endpoints/StreamingEndpoints.cs new file mode 100644 index 0000000..c9dcb01 --- /dev/null +++ b/backend/src/TeleWave.Api/Endpoints/StreamingEndpoints.cs @@ -0,0 +1,164 @@ +using System.Globalization; +using System.Text; +using System.Text.RegularExpressions; +using LiteCqrs; +using TeleWave.Api.Common; +using TeleWave.Application.Common.Interfaces; +using TeleWave.Application.Streaming; +using TeleWave.Application.Streaming.GetLivePlaylist; +using TeleWave.Application.Streaming.GetPublicEpg; +using TeleWave.Application.Streaming.ListPublicChannels; +using TeleWave.Infrastructure.Media; +using TeleWave.Infrastructure.Streaming; + +namespace TeleWave.Api.Endpoints; + +public static class StreamingEndpoints +{ + private const string StreamCookieName = "tw_stream"; + private static readonly Regex SegmentFileName = new(@"^seg\d{1,6}\.ts$", RegexOptions.Compiled); + + public static IEndpointRouteBuilder MapStreamingEndpoints(this IEndpointRouteBuilder app) + { + // Публичный API канала (Bearer): список, EPG, выдача stream-cookie. + var channels = app.MapGroup("/api/channels").WithTags("Channels").RequireAuthorization(); + channels.MapGet("", ListChannels).Produces>(); + channels.MapPost("/{slug}/watch", Watch).Produces(StatusCodes.Status204NoContent); + channels.MapGet("/{slug}/epg", Epg); + + // Раздача эфира (cookie tw_stream): плейлист и сегменты — их грузит