Implement media storage and processing features: update configuration in .env.example and appsettings files, enhance Docker setup for media storage, and add media-related services and database entities. Include ffmpeg for media handling and adjust Kestrel settings for large file uploads.

This commit is contained in:
Leonid Pershin
2026-07-24 08:33:11 +03:00
parent 1dd6991174
commit e15ecbdb29
47 changed files with 2599 additions and 1 deletions
@@ -1,11 +1,13 @@
using Microsoft.EntityFrameworkCore;
using TeleWave.Domain.Auth;
using TeleWave.Domain.Media;
namespace TeleWave.Application.Common.Interfaces;
public interface IAppDbContext
{
DbSet<RefreshToken> RefreshTokens { get; }
DbSet<MediaAsset> MediaAssets { get; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
@@ -0,0 +1,12 @@
namespace TeleWave.Application.Common.Interfaces;
/// <summary>
/// Очередь фоновой обработки ассетов. Продюсеры (endpoint загрузки, inbox-сканер) ставят id ассета,
/// единственный фоновый потребитель обрабатывает по одному за раз.
/// </summary>
public interface IMediaProcessingQueue
{
void Enqueue(Guid assetId);
IAsyncEnumerable<Guid> DequeueAllAsync(CancellationToken cancellationToken);
}
@@ -0,0 +1,29 @@
using TeleWave.Domain.Media;
namespace TeleWave.Application.Common.Interfaces;
/// <summary>Итог нормализации и нарезки исходника в HLS-сегменты.</summary>
public sealed record MediaProcessingResult(
TimeSpan Duration,
int SegmentSeconds,
int SegmentCount,
int Width,
int Height,
string VideoCodec,
string AudioCodec,
string RelativePath
);
/// <summary>
/// Порт обработки медиа (ffprobe + ffmpeg). Реализация читает исходник по <paramref name="assetId"/>
/// и <paramref name="extension"/> из хранилища, нормализует в H.264/AAC и режет на сегменты
/// фиксированной длины, добивая длительность до кратности сегменту.
/// </summary>
public interface IMediaProcessor
{
Task<MediaProcessingResult> ProcessAsync(
Guid assetId,
string extension,
CancellationToken cancellationToken
);
}
@@ -0,0 +1,37 @@
using TeleWave.Domain.Media;
namespace TeleWave.Application.Common.Interfaces;
/// <summary>
/// Порт файлового хранилища медиа. Все относительные пути резолвятся строго внутри корня
/// (<c>Storage:RootPath</c>) — защита от path traversal лежит на реализации.
/// </summary>
public interface IMediaStorage
{
/// <summary>Свободное место на томе хранилища, байт.</summary>
long GetAvailableFreeSpaceBytes();
/// <summary>
/// Стримит загружаемый контент во временный файл в <c>uploads/</c> без буферизации в память.
/// Возвращает непрозрачный токен (имя временного файла) для последующего <see cref="PromoteToOriginalAsync"/>.
/// </summary>
Task<string> SaveUploadAsync(Stream content, string extension, CancellationToken cancellationToken);
/// <summary>Удаляет временный файл загрузки (откат при ошибке до регистрации ассета).</summary>
void DeleteUpload(string uploadToken);
/// <summary>
/// Переносит исходник из источника (<c>uploads/</c> для <see cref="MediaSource.Upload"/> либо
/// <c>inbox/</c> для <see cref="MediaSource.Inbox"/>) в <c>originals/{assetId}{ext}</c>.
/// </summary>
Task PromoteToOriginalAsync(
MediaSource source,
string sourceToken,
Guid assetId,
string extension,
CancellationToken cancellationToken
);
/// <summary>Удаляет все артефакты ассета: исходник в <c>originals/</c> и каталог сегментов <c>assets/{id}/</c>.</summary>
void DeleteAssetArtifacts(Guid assetId, string extension);
}