Browse Source

feat: add channel config overlays for next engine (#2891)

pull/2892/head
Jason Dove 1 week ago committed by GitHub
parent
commit
6429659711
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      CHANGELOG.md
  2. 28
      ErsatzTV.Application/Streaming/Commands/StartFFmpegNextSessionHandler.cs
  3. 21
      ErsatzTV.Application/Streaming/NextSessionWorker.cs
  4. 2
      ErsatzTV.Core/FileSystemLayout.cs
  5. 100
      ErsatzTV.Core/Next/Config/ChannelConfig.cs
  6. 1
      ErsatzTV/Startup.cs

8
CHANGELOG.md

@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Added
- Add channel config overlay system for Next engine
- The channel config schema can be found at https://github.com/ErsatzTV/next/blob/main/schema/channel_config.json
- Config overlays should be created in the config subfolder `next/channel-config-overlays`
- A config file named `default.json` will apply to all channels using the Next engine
- A config file named `{channel_number}.json` (e.g. `1.json`) will apply to the channel with that number
- Channel overlays will override values from the default overlay which will override values from the FFmpeg Profile
### Fixed
- Fix HLS Direct playback when JWT auth is also used

28
ErsatzTV.Application/Streaming/Commands/StartFFmpegNextSessionHandler.cs

@ -324,6 +324,16 @@ public class StartFFmpegNextSessionHandler( @@ -324,6 +324,16 @@ public class StartFFmpegNextSessionHandler(
};
}
string tonemapAlgorithm = ffmpegProfile.TonemapAlgorithm switch
{
FFmpegProfileTonemapAlgorithm.Clip => "clip",
FFmpegProfileTonemapAlgorithm.Gamma => "gamma",
FFmpegProfileTonemapAlgorithm.Reinhard => "reinhard",
FFmpegProfileTonemapAlgorithm.Mobius => "mobius",
FFmpegProfileTonemapAlgorithm.Hable => "hable",
_ => "linear"
};
var videoNormalization = new Video
{
Format = ffmpegProfile.VideoFormat switch
@ -356,8 +366,22 @@ public class StartFFmpegNextSessionHandler( @@ -356,8 +366,22 @@ public class StartFFmpegNextSessionHandler(
ScalingBehavior.Crop => ScalingMode.Crop,
_ => ScalingMode.ScaleAndPad
},
// TODO: NEXT: more tonemap algorithms
TonemapAlgorithm = "linear",
Deinterlace = ffmpegProfile.DeinterlaceVideo,
Filters = new Filters
{
Tonemap = new TonemapClass
{
Tonemap = tonemapAlgorithm
},
TonemapOpencl = new TonemapOpenclClass
{
Tonemap = tonemapAlgorithm
},
Libplacebo = new LibplaceboClass
{
Tonemapping = tonemapAlgorithm
}
},
VaapiDevice = ffmpegProfile.VaapiDevice,
VaapiDriver = ffmpegProfile.VaapiDriver switch
{

21
ErsatzTV.Application/Streaming/NextSessionWorker.cs

@ -99,9 +99,26 @@ public class NextSessionWorker( @@ -99,9 +99,26 @@ public class NextSessionWorker(
_workingDirectory = fileSystem.Path.Combine(FileSystemLayout.TranscodeFolder, _channelNumber);
_heartbeatFileName = fileSystem.Path.Combine(_workingDirectory, ".heartbeat");
List<string> arguments = ["run", "--output-folder", _workingDirectory, "--number", channelNumber, "-"];
string defaultOverlayFile = fileSystem.Path.Combine(
FileSystemLayout.NextChannelConfigOverlaysFolder,
"default.json");
if (fileSystem.File.Exists(defaultOverlayFile))
{
arguments.Add(defaultOverlayFile);
}
string channelOverlayFile = fileSystem.Path.Combine(
FileSystemLayout.NextChannelConfigOverlaysFolder,
$"{channelNumber}.json");
if (fileSystem.File.Exists(channelOverlayFile))
{
arguments.Add(channelOverlayFile);
}
CommandResult commandResult = await Cli.Wrap(channelBinary)
.WithArguments(
["run", "--output-folder", _workingDirectory, "--number", channelNumber, "-"])
.WithArguments(arguments)
.WithStandardInputPipe(PipeSource.FromString(channelConfig.ToJson()))
.WithStandardOutputPipe(PipeTarget.ToDelegate(l => logger.LogDebug("{Line}", l)))
.WithStandardErrorPipe(PipeTarget.ToDelegate(l => logger.LogDebug("{Line}", l)))

2
ErsatzTV.Core/FileSystemLayout.cs

@ -67,6 +67,7 @@ public static class FileSystemLayout @@ -67,6 +67,7 @@ public static class FileSystemLayout
public static readonly string DefaultMpegTsScriptFolder;
public static readonly string NextChannelConfigOverlaysFolder;
public static readonly string NextPlayoutsFolder;
public static readonly string MacOsOldAppDataFolder = Path.Combine(
@ -195,6 +196,7 @@ public static class FileSystemLayout @@ -195,6 +196,7 @@ public static class FileSystemLayout
MpegTsScriptsFolder = Path.Combine(ScriptsFolder, "mpegts");
DefaultMpegTsScriptFolder = Path.Combine(MpegTsScriptsFolder, "default");
NextChannelConfigOverlaysFolder = Path.Combine(AppDataFolder, "next", "channel-config-overlays");
NextPlayoutsFolder = Path.Combine(AppDataFolder, "next", "playouts");
}
}

100
ErsatzTV.Core/Next/Config/ChannelConfig.cs

@ -113,6 +113,9 @@ namespace ErsatzTV.Core.Next.Config @@ -113,6 +113,9 @@ namespace ErsatzTV.Core.Next.Config
[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; }
@ -122,9 +125,6 @@ namespace ErsatzTV.Core.Next.Config @@ -122,9 +125,6 @@ namespace ErsatzTV.Core.Next.Config
[JsonProperty("scaling_mode", NullValueHandling = NullValueHandling.Ignore)]
public ScalingMode? ScalingMode { get; set; }
[JsonProperty("tonemap_algorithm")]
public string TonemapAlgorithm { get; set; }
[JsonProperty("vaapi_device")]
public string VaapiDevice { get; set; }
@ -135,6 +135,99 @@ namespace ErsatzTV.Core.Next.Config @@ -135,6 +135,99 @@ namespace ErsatzTV.Core.Next.Config
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")]
@ -173,6 +266,7 @@ namespace ErsatzTV.Core.Next.Config @@ -173,6 +266,7 @@ namespace ErsatzTV.Core.Next.Config
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =

1
ErsatzTV/Startup.cs

@ -363,6 +363,7 @@ public class Startup @@ -363,6 +363,7 @@ public class Startup
FileSystemLayout.AudioStreamSelectorScriptsFolder,
FileSystemLayout.MpegTsScriptsFolder,
FileSystemLayout.DefaultMpegTsScriptFolder,
FileSystemLayout.NextChannelConfigOverlaysFolder,
FileSystemLayout.NextPlayoutsFolder,
];

Loading…
Cancel
Save