From 39e6694bbe2e7b6a7a499829964add4c31363730 Mon Sep 17 00:00:00 2001 From: Samuele Lorefice Date: Mon, 1 Dec 2025 19:32:50 +0100 Subject: [PATCH] Initial files --- .dockerignore | 25 ++ .gitignore | 332 ++++++++++++++++++++ .idea/.idea.VidEncSrv/.idea/.gitignore | 15 + .idea/.idea.VidEncSrv/.idea/indexLayout.xml | 8 + .idea/.idea.VidEncSrv/.idea/vcs.xml | 6 + Encoder/Dockerfile | 23 ++ Encoder/Encoder.csproj | 20 ++ Encoder/Encoder.http | 6 + Encoder/Program.cs | 94 ++++++ Encoder/Properties/launchSettings.json | 23 ++ Encoder/appsettings.Development.json | 8 + Encoder/appsettings.json | 10 + VidEncSrv.slnx | 6 + compose.yaml | 7 + 14 files changed, 583 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 .idea/.idea.VidEncSrv/.idea/.gitignore create mode 100644 .idea/.idea.VidEncSrv/.idea/indexLayout.xml create mode 100644 .idea/.idea.VidEncSrv/.idea/vcs.xml create mode 100644 Encoder/Dockerfile create mode 100644 Encoder/Encoder.csproj create mode 100644 Encoder/Encoder.http create mode 100644 Encoder/Program.cs create mode 100644 Encoder/Properties/launchSettings.json create mode 100644 Encoder/appsettings.Development.json create mode 100644 Encoder/appsettings.json create mode 100644 VidEncSrv.slnx create mode 100644 compose.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e4c305 --- /dev/null +++ b/.gitignore @@ -0,0 +1,332 @@ +### ASPNETCore template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/ + +### Rider template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + diff --git a/.idea/.idea.VidEncSrv/.idea/.gitignore b/.idea/.idea.VidEncSrv/.idea/.gitignore new file mode 100644 index 0000000..3b6ad13 --- /dev/null +++ b/.idea/.idea.VidEncSrv/.idea/.gitignore @@ -0,0 +1,15 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/projectSettingsUpdater.xml +/modules.xml +/.idea.VidEncSrv.iml +/contentModel.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/.idea.VidEncSrv/.idea/indexLayout.xml b/.idea/.idea.VidEncSrv/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.VidEncSrv/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.VidEncSrv/.idea/vcs.xml b/.idea/.idea.VidEncSrv/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.VidEncSrv/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Encoder/Dockerfile b/Encoder/Dockerfile new file mode 100644 index 0000000..4a61aba --- /dev/null +++ b/Encoder/Dockerfile @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base +USER $APP_UID +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["Encoder/Encoder.csproj", "Encoder/"] +RUN dotnet restore "Encoder/Encoder.csproj" +COPY . . +WORKDIR "/src/Encoder" +RUN dotnet build "./Encoder.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./Encoder.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Encoder.dll"] diff --git a/Encoder/Encoder.csproj b/Encoder/Encoder.csproj new file mode 100644 index 0000000..3ea8f06 --- /dev/null +++ b/Encoder/Encoder.csproj @@ -0,0 +1,20 @@ + + + + net10.0 + enable + enable + Linux + + + + + + + + + .dockerignore + + + + diff --git a/Encoder/Encoder.http b/Encoder/Encoder.http new file mode 100644 index 0000000..27b6c79 --- /dev/null +++ b/Encoder/Encoder.http @@ -0,0 +1,6 @@ +@Encoder_HostAddress = http://localhost:5257 + +GET {{Encoder_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Encoder/Program.cs b/Encoder/Program.cs new file mode 100644 index 0000000..0ce2a1c --- /dev/null +++ b/Encoder/Program.cs @@ -0,0 +1,94 @@ +using System.Collections; +using Microsoft.AspNetCore.Http.HttpResults; +Queue JobQueue = new(); + +var builder = WebApplication.CreateBuilder(args); + +//Settings +string tmpFilePath = builder.Configuration.GetValue("TempFilePath") ?? Path.GetTempPath(); + +//Services +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } + +app.UseHttpsRedirection(); + +// Get a video file as multipart form data and schedule it for encoding +// Get video encoding settings from query parameters +// Returns the ID of the job handling the encoding +app.MapPost("encode", context => +{ + var request = context.Request; + if (!request.HasFormContentType) { + context.Response.StatusCode = 400; + return context.Response.WriteAsync("Invalid content type. Expected multipart/form-data."); + } + + var form = request.Form; + var file = form.Files.GetFile("video"); + + if (file == null) { + context.Response.StatusCode = 400; + return context.Response.WriteAsync("No video file provided."); + } + + var Job = new EncodingJob(Guid.NewGuid()); + JobQueue.Enqueue(Job); + + return context.Response.WriteAsJsonAsync(new { JobId = Job.Id }); +}); + +// Check the status of an encoding job by its ID +app.MapGet("status/{jobId:guid}", (Guid jobId) => +{ + var job = JobQueue.FirstOrDefault(j => j.Id == jobId); + if (job == null) { + return Results.NotFound(new { Message = "Job not found." }); + } + + return Results.Ok(new { + JobId = job.Id, + Status = job.Status.ToString(), + CreatedAt = job.CreatedAt, + CompletedAt = job.CompletedAt + }); +}); + +app.MapGet("file/{jobId:guid}", (Guid jobId) => +{ + var job = JobQueue.FirstOrDefault(j => j.Id == jobId); + if (job == null) { + return Results.NotFound(new { Message = "Job not found." }); + } + + if (job.Status != JobStatus.Completed) { + return Results.BadRequest(new { Message = "Job is not completed yet." }); + } + + var filePath = job.EncodedFilePath; + if (!File.Exists(filePath)) { + return Results.NotFound(new { Message = "Encoded file not found." }); + } + + var fileBytes = File.ReadAllBytes(filePath); + return Results.File(fileBytes, "video/mp4", Path.GetFileName(filePath), enableRangeProcessing:true); +}); + +app.Run(); + +public enum JobStatus { + Pending, + InProgress, + Completed, + Failed +} + +public record EncodingJob(Guid Id) { + public JobStatus Status { get; set; } = JobStatus.Pending; + public DateTime CreatedAt { get; init; } = DateTime.Now; + public DateTime? CompletedAt { get; set; } = null; + public string OrigFilePath { get; init; } = string.Empty; + public string EncodedFilePath { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/Encoder/Properties/launchSettings.json b/Encoder/Properties/launchSettings.json new file mode 100644 index 0000000..2e41c19 --- /dev/null +++ b/Encoder/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5257", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7134;http://localhost:5257", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Encoder/appsettings.Development.json b/Encoder/appsettings.Development.json new file mode 100644 index 0000000..3e1a225 --- /dev/null +++ b/Encoder/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Information" + } + } +} diff --git a/Encoder/appsettings.json b/Encoder/appsettings.json new file mode 100644 index 0000000..b2d2fe8 --- /dev/null +++ b/Encoder/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "TemporaryFilesPath": "./Temp" +} diff --git a/VidEncSrv.slnx b/VidEncSrv.slnx new file mode 100644 index 0000000..23b87a1 --- /dev/null +++ b/VidEncSrv.slnx @@ -0,0 +1,6 @@ + + + + + + diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..9d70ac8 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,7 @@ +services: + encoder: + image: encoder + build: + context: . + dockerfile: Encoder/Dockerfile +