// // // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: // // using ErsatzTV.Core.Next.Config; // // var channelConfig = ChannelConfig.FromJson(jsonString); namespace ErsatzTV.Core.Next.Config { using System; using System.Collections.Generic; using System.Globalization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; public partial class ChannelConfig { [JsonProperty("ffmpeg")] public Ffmpeg Ffmpeg { get; set; } [JsonProperty("normalization")] public Normalization Normalization { get; set; } [JsonProperty("playout")] public Playout Playout { get; set; } } public partial class Ffmpeg { [JsonProperty("disabled_filters", NullValueHandling = NullValueHandling.Ignore)] public List DisabledFilters { get; set; } [JsonProperty("ffmpeg_path")] public string FfmpegPath { get; set; } [JsonProperty("ffprobe_path")] public string FfprobePath { get; set; } [JsonProperty("preferred_filters", NullValueHandling = NullValueHandling.Ignore)] public List PreferredFilters { get; set; } [JsonProperty("reports_folder")] public string ReportsFolder { get; set; } } public partial class Normalization { [JsonProperty("audio")] public Audio Audio { get; set; } [JsonProperty("subtitle", NullValueHandling = NullValueHandling.Ignore)] public Subtitle Subtitle { get; set; } [JsonProperty("video")] public Video Video { get; set; } } public partial class Audio { [JsonProperty("bitrate_kbps")] public long? BitrateKbps { get; set; } [JsonProperty("buffer_kbps")] public long? BufferKbps { get; set; } [JsonProperty("channels")] public long? Channels { get; set; } [JsonProperty("format")] public AudioFormat? Format { get; set; } [JsonProperty("loudness")] public LoudnessClass Loudness { get; set; } [JsonProperty("normalize_loudness", NullValueHandling = NullValueHandling.Ignore)] public bool? NormalizeLoudness { get; set; } [JsonProperty("sample_rate_hz")] public long? SampleRateHz { get; set; } } public partial class LoudnessClass { [JsonProperty("integrated_target")] public double? IntegratedTarget { get; set; } [JsonProperty("range_target")] public double? RangeTarget { get; set; } [JsonProperty("true_peak")] public double? TruePeak { get; set; } } public partial class Subtitle { [JsonProperty("mode", NullValueHandling = NullValueHandling.Ignore)] public Mode? Mode { get; set; } } public partial class Video { [JsonProperty("accel")] public AccelEnum? Accel { get; set; } [JsonProperty("bit_depth")] public long? BitDepth { get; set; } [JsonProperty("bitrate_kbps")] public long? BitrateKbps { get; set; } [JsonProperty("buffer_kbps")] public long? BufferKbps { get; set; } [JsonProperty("deinterlace", NullValueHandling = NullValueHandling.Ignore)] public bool? Deinterlace { get; set; } [JsonProperty("filters", NullValueHandling = NullValueHandling.Ignore)] public Filters Filters { get; set; } [JsonProperty("format")] public VideoFormat? Format { get; set; } [JsonProperty("height")] public long? Height { get; set; } [JsonProperty("scaling_mode", NullValueHandling = NullValueHandling.Ignore)] public ScalingMode? ScalingMode { get; set; } [JsonProperty("vaapi_device")] public string VaapiDevice { get; set; } [JsonProperty("vaapi_driver")] public VaapiDriverEnum? VaapiDriver { get; set; } [JsonProperty("width")] public long? Width { get; set; } } public partial class Filters { [JsonProperty("bwdif")] public BwdifClass Bwdif { get; set; } [JsonProperty("bwdif_cuda")] public BwdifCudaClass BwdifCuda { get; set; } [JsonProperty("deinterlace_qsv")] public DeinterlaceQsvClass DeinterlaceQsv { get; set; } [JsonProperty("deinterlace_vaapi")] public DeinterlaceVaapiClass DeinterlaceVaapi { get; set; } [JsonProperty("libplacebo")] public LibplaceboClass Libplacebo { get; set; } [JsonProperty("tonemap")] public TonemapClass Tonemap { get; set; } [JsonProperty("tonemap_opencl")] public TonemapOpenclClass TonemapOpencl { get; set; } [JsonProperty("w3fdif")] public W3FdifClass W3Fdif { get; set; } [JsonProperty("yadif")] public YadifClass Yadif { get; set; } [JsonProperty("yadif_cuda")] public YadifCudaClass YadifCuda { get; set; } } public partial class BwdifClass { [JsonProperty("mode")] public string Mode { get; set; } } public partial class BwdifCudaClass { [JsonProperty("mode")] public string Mode { get; set; } } public partial class DeinterlaceQsvClass { [JsonProperty("mode")] public string Mode { get; set; } } public partial class DeinterlaceVaapiClass { [JsonProperty("mode")] public string Mode { get; set; } } public partial class LibplaceboClass { [JsonProperty("tonemapping")] public string Tonemapping { get; set; } } public partial class TonemapClass { [JsonProperty("tonemap")] public string Tonemap { get; set; } } public partial class TonemapOpenclClass { [JsonProperty("tonemap")] public string Tonemap { get; set; } } public partial class W3FdifClass { [JsonProperty("mode")] public string Mode { get; set; } } public partial class YadifClass { [JsonProperty("mode")] public string Mode { get; set; } } public partial class YadifCudaClass { [JsonProperty("mode")] public string Mode { get; set; } } public partial class Playout { [JsonProperty("folder")] public string Folder { get; set; } /// /// RFC3339 formatted date/time, e.g. 2026-04-13T00:24:21.527-05:00 /// [JsonProperty("virtual_start")] public string VirtualStart { get; set; } } public enum AudioFormat { Aac, Ac3 }; public enum Mode { Burn, Convert }; public enum AccelEnum { Amf, Cuda, Qsv, Rkmpp, Vaapi, Videotoolbox, Vulkan }; public enum VideoFormat { H264, Hevc }; public enum ScalingMode { Crop, ScaleAndPad, Stretch }; public enum VaapiDriverEnum { I965, Ihd, Radeonsi }; public partial class ChannelConfig { public static ChannelConfig FromJson(string json) => JsonConvert.DeserializeObject(json, ErsatzTV.Core.Next.Config.Converter.Settings); } public static class Serialize { public static string ToJson(this ChannelConfig self) => JsonConvert.SerializeObject(self, ErsatzTV.Core.Next.Config.Converter.Settings); } internal static class Converter { public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, MetadataPropertyHandling = MetadataPropertyHandling.Ignore, DateParseHandling = DateParseHandling.None, Converters = { AudioFormatConverter.Singleton, ModeConverter.Singleton, AccelEnumConverter.Singleton, VideoFormatConverter.Singleton, ScalingModeConverter.Singleton, VaapiDriverEnumConverter.Singleton, new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } }, }; } internal class AudioFormatConverter : JsonConverter { public override bool CanConvert(Type t) => t == typeof(AudioFormat) || t == typeof(AudioFormat?); public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var value = serializer.Deserialize(reader); switch (value) { case "aac": return AudioFormat.Aac; case "ac3": return AudioFormat.Ac3; } throw new Exception("Cannot unmarshal type AudioFormat"); } public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) { if (untypedValue == null) { serializer.Serialize(writer, null); return; } var value = (AudioFormat)untypedValue; switch (value) { case AudioFormat.Aac: serializer.Serialize(writer, "aac"); return; case AudioFormat.Ac3: serializer.Serialize(writer, "ac3"); return; } throw new Exception("Cannot marshal type AudioFormat"); } public static readonly AudioFormatConverter Singleton = new AudioFormatConverter(); } internal class ModeConverter : JsonConverter { public override bool CanConvert(Type t) => t == typeof(Mode) || t == typeof(Mode?); public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var value = serializer.Deserialize(reader); switch (value) { case "burn": return Mode.Burn; case "convert": return Mode.Convert; } throw new Exception("Cannot unmarshal type Mode"); } public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) { if (untypedValue == null) { serializer.Serialize(writer, null); return; } var value = (Mode)untypedValue; switch (value) { case Mode.Burn: serializer.Serialize(writer, "burn"); return; case Mode.Convert: serializer.Serialize(writer, "convert"); return; } throw new Exception("Cannot marshal type Mode"); } public static readonly ModeConverter Singleton = new ModeConverter(); } internal class AccelEnumConverter : JsonConverter { public override bool CanConvert(Type t) => t == typeof(AccelEnum) || t == typeof(AccelEnum?); public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var value = serializer.Deserialize(reader); switch (value) { case "amf": return AccelEnum.Amf; case "cuda": return AccelEnum.Cuda; case "qsv": return AccelEnum.Qsv; case "rkmpp": return AccelEnum.Rkmpp; case "vaapi": return AccelEnum.Vaapi; case "videotoolbox": return AccelEnum.Videotoolbox; case "vulkan": return AccelEnum.Vulkan; } throw new Exception("Cannot unmarshal type AccelEnum"); } public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) { if (untypedValue == null) { serializer.Serialize(writer, null); return; } var value = (AccelEnum)untypedValue; switch (value) { case AccelEnum.Amf: serializer.Serialize(writer, "amf"); return; case AccelEnum.Cuda: serializer.Serialize(writer, "cuda"); return; case AccelEnum.Qsv: serializer.Serialize(writer, "qsv"); return; case AccelEnum.Rkmpp: serializer.Serialize(writer, "rkmpp"); return; case AccelEnum.Vaapi: serializer.Serialize(writer, "vaapi"); return; case AccelEnum.Videotoolbox: serializer.Serialize(writer, "videotoolbox"); return; case AccelEnum.Vulkan: serializer.Serialize(writer, "vulkan"); return; } throw new Exception("Cannot marshal type AccelEnum"); } public static readonly AccelEnumConverter Singleton = new AccelEnumConverter(); } internal class VideoFormatConverter : JsonConverter { public override bool CanConvert(Type t) => t == typeof(VideoFormat) || t == typeof(VideoFormat?); public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var value = serializer.Deserialize(reader); switch (value) { case "h264": return VideoFormat.H264; case "hevc": return VideoFormat.Hevc; } throw new Exception("Cannot unmarshal type VideoFormat"); } public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) { if (untypedValue == null) { serializer.Serialize(writer, null); return; } var value = (VideoFormat)untypedValue; switch (value) { case VideoFormat.H264: serializer.Serialize(writer, "h264"); return; case VideoFormat.Hevc: serializer.Serialize(writer, "hevc"); return; } throw new Exception("Cannot marshal type VideoFormat"); } public static readonly VideoFormatConverter Singleton = new VideoFormatConverter(); } internal class ScalingModeConverter : JsonConverter { public override bool CanConvert(Type t) => t == typeof(ScalingMode) || t == typeof(ScalingMode?); public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var value = serializer.Deserialize(reader); switch (value) { case "crop": return ScalingMode.Crop; case "scale_and_pad": return ScalingMode.ScaleAndPad; case "stretch": return ScalingMode.Stretch; } throw new Exception("Cannot unmarshal type ScalingMode"); } public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) { if (untypedValue == null) { serializer.Serialize(writer, null); return; } var value = (ScalingMode)untypedValue; switch (value) { case ScalingMode.Crop: serializer.Serialize(writer, "crop"); return; case ScalingMode.ScaleAndPad: serializer.Serialize(writer, "scale_and_pad"); return; case ScalingMode.Stretch: serializer.Serialize(writer, "stretch"); return; } throw new Exception("Cannot marshal type ScalingMode"); } public static readonly ScalingModeConverter Singleton = new ScalingModeConverter(); } internal class VaapiDriverEnumConverter : JsonConverter { public override bool CanConvert(Type t) => t == typeof(VaapiDriverEnum) || t == typeof(VaapiDriverEnum?); public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var value = serializer.Deserialize(reader); switch (value) { case "i965": return VaapiDriverEnum.I965; case "ihd": return VaapiDriverEnum.Ihd; case "radeonsi": return VaapiDriverEnum.Radeonsi; } throw new Exception("Cannot unmarshal type VaapiDriverEnum"); } public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) { if (untypedValue == null) { serializer.Serialize(writer, null); return; } var value = (VaapiDriverEnum)untypedValue; switch (value) { case VaapiDriverEnum.I965: serializer.Serialize(writer, "i965"); return; case VaapiDriverEnum.Ihd: serializer.Serialize(writer, "ihd"); return; case VaapiDriverEnum.Radeonsi: serializer.Serialize(writer, "radeonsi"); return; } throw new Exception("Cannot marshal type VaapiDriverEnum"); } public static readonly VaapiDriverEnumConverter Singleton = new VaapiDriverEnumConverter(); } }