Backend plumbing for the SPA transcoding editors (#143 blocker): - FFmpeg profile response DTO round-trip: add NormalizeAudio, NormalizeVideo, PadMode, TargetLoudness, NormalizeColors, ResolutionId (keep Resolution name for compat); DeinterlaceVideo now bool (was bool?). #nullable enable on the DTO. - New GET /api/ffmpeg/hardware-acceleration-kinds wrapping GetSupportedHardwareAccelerationKinds (returns enum names as strings). - Filler preset CRUD: GET-by-id/POST/PUT/DELETE on FillerPresetController with full request/response DTOs; new FillerPresetFullResponseModel + GetFillerPresetByIdForApi. CreateFillerPreset now returns the new id (CreateFillerPresetResult) to match sibling Create commands and enable a 201+Location; updated the one Blazor call site. - Watermark CRUD: GET-by-id/POST/PUT/DELETE on WatermarkController with full DTOs (path+contentType, all 15 fields); new WatermarkFullResponseModel + GetWatermarkByIdForApi. - Startup: register WatermarkLocation/WatermarkSize as OpenAPI string enums (they live in ErsatzTV.FFmpeg.State and were documented as ints, mismatching the Newtonsoft StringEnumConverter runtime serialization). - Tests: full CRUD controller tests for filler + watermark; contract-test entries (404/401/422) for the new mutating endpoints; regenerated v1.json. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
85 lines
3.2 KiB
C#
85 lines
3.2 KiB
C#
using ErsatzTV.Core.Api.FFmpegProfiles;
|
|
using ErsatzTV.Core.Domain;
|
|
|
|
namespace ErsatzTV.Application.FFmpegProfiles;
|
|
|
|
internal static class Mapper
|
|
{
|
|
internal static FFmpegProfileViewModel ProjectToViewModel(FFmpegProfile profile) =>
|
|
new(
|
|
profile.Id,
|
|
profile.Name,
|
|
profile.ThreadCount,
|
|
profile.NormalizeAudio,
|
|
profile.NormalizeVideo,
|
|
profile.HardwareAcceleration,
|
|
profile.VaapiDisplay ?? "drm",
|
|
profile.VaapiDriver,
|
|
profile.VaapiDevice,
|
|
profile.QsvExtraHardwareFrames,
|
|
Resolutions.Mapper.ProjectToViewModel(profile.Resolution),
|
|
profile.ScalingBehavior,
|
|
profile.PadMode,
|
|
profile.VideoFormat,
|
|
profile.VideoProfile,
|
|
profile.VideoPreset ?? string.Empty,
|
|
profile.AllowBFrames,
|
|
profile.BitDepth,
|
|
profile.VideoBitrate,
|
|
profile.VideoBufferSize,
|
|
profile.TonemapAlgorithm,
|
|
profile.AudioFormat,
|
|
profile.AudioBitrate,
|
|
profile.AudioBufferSize,
|
|
profile.NormalizeLoudnessMode,
|
|
profile.TargetLoudness,
|
|
profile.AudioChannels,
|
|
profile.AudioSampleRate,
|
|
profile.NormalizeFramerate,
|
|
profile.NormalizeColors,
|
|
profile.DeinterlaceVideo == true);
|
|
|
|
internal static FFmpegProfileResponseModel ProjectToResponseModel(FFmpegProfile ffmpegProfile) =>
|
|
new(
|
|
ffmpegProfile.Id,
|
|
ffmpegProfile.Name,
|
|
$"{ffmpegProfile.Resolution.Width}x{ffmpegProfile.Resolution.Height}",
|
|
ffmpegProfile.VideoFormat.ToString().ToLowerInvariant(),
|
|
ffmpegProfile.AudioFormat.ToString().ToLowerInvariant());
|
|
|
|
internal static FFmpegFullProfileResponseModel ProjectToFullResponseModel(FFmpegProfile ffmpegProfile) =>
|
|
new(
|
|
ffmpegProfile.Id,
|
|
ffmpegProfile.Name,
|
|
ffmpegProfile.ThreadCount,
|
|
ffmpegProfile.NormalizeAudio,
|
|
ffmpegProfile.NormalizeVideo,
|
|
ffmpegProfile.HardwareAcceleration,
|
|
ffmpegProfile.VaapiDisplay,
|
|
ffmpegProfile.VaapiDriver,
|
|
ffmpegProfile.VaapiDevice,
|
|
ffmpegProfile.QsvExtraHardwareFrames,
|
|
ffmpegProfile.ResolutionId,
|
|
ffmpegProfile.Resolution.Name,
|
|
ffmpegProfile.ScalingBehavior,
|
|
ffmpegProfile.PadMode,
|
|
ffmpegProfile.VideoFormat,
|
|
ffmpegProfile.VideoProfile,
|
|
ffmpegProfile.VideoPreset,
|
|
ffmpegProfile.AllowBFrames,
|
|
ffmpegProfile.BitDepth,
|
|
ffmpegProfile.VideoBitrate,
|
|
ffmpegProfile.VideoBufferSize,
|
|
ffmpegProfile.TonemapAlgorithm,
|
|
ffmpegProfile.AudioFormat,
|
|
ffmpegProfile.AudioBitrate,
|
|
ffmpegProfile.AudioBufferSize,
|
|
ffmpegProfile.NormalizeLoudnessMode,
|
|
ffmpegProfile.TargetLoudness,
|
|
ffmpegProfile.AudioChannels,
|
|
ffmpegProfile.AudioSampleRate,
|
|
ffmpegProfile.NormalizeFramerate,
|
|
ffmpegProfile.NormalizeColors,
|
|
ffmpegProfile.DeinterlaceVideo == true);
|
|
}
|