feat(api): add channel templates
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 5m34s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m58s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped

This commit is contained in:
2026-07-06 18:43:39 +02:00
parent c4007293bf
commit 7858ac002a
39 changed files with 17722 additions and 43 deletions
@@ -0,0 +1,109 @@
using System.ComponentModel.DataAnnotations;
using ErsatzTV.Application.ChannelTemplates;
using ErsatzTV.Controllers.Api.Requests;
using ErsatzTV.Core;
using ErsatzTV.Core.Api.ChannelTemplates;
using ErsatzTV.Extensions;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace ErsatzTV.Controllers.Api;
[ApiController]
public class ChannelTemplateController(IMediator mediator) : ControllerBase
{
[HttpGet("/api/channel-templates", Name = "GetChannelTemplates")]
[Tags("Channel Templates")]
[EndpointSummary("Get all channel templates")]
[EndpointGroupName("general")]
[ProducesResponseType(typeof(List<ChannelTemplateResponseModel>), StatusCodes.Status200OK)]
public async Task<List<ChannelTemplateResponseModel>> GetAll(CancellationToken cancellationToken) =>
await mediator.Send(new GetAllChannelTemplates(), cancellationToken);
[HttpGet("/api/channel-templates/default", Name = "GetDefaultChannelTemplate")]
[Tags("Channel Templates")]
[EndpointSummary("Get the default channel template")]
[EndpointGroupName("general")]
[ProducesResponseType(typeof(ChannelTemplateResponseModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetDefault(CancellationToken cancellationToken)
{
Option<ChannelTemplateResponseModel> result =
await mediator.Send(new GetDefaultChannelTemplate(), cancellationToken);
return result.ToGetResult();
}
[HttpPut("/api/channel-templates/default/{id:int}", Name = "SetDefaultChannelTemplate")]
[Tags("Channel Templates")]
[EndpointSummary("Set the default channel template")]
[EndpointGroupName("general")]
[ProducesResponseType(typeof(ChannelTemplateResponseModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status422UnprocessableEntity)]
public async Task<IActionResult> SetDefault(int id, CancellationToken cancellationToken)
{
Either<BaseError, ChannelTemplateResponseModel> result =
await mediator.Send(new SetDefaultChannelTemplate(id), cancellationToken);
return result.ToUpdatedResult();
}
[HttpGet("/api/channel-templates/{id:int}", Name = "GetChannelTemplateById")]
[Tags("Channel Templates")]
[EndpointSummary("Get a channel template by id")]
[EndpointGroupName("general")]
[ProducesResponseType(typeof(ChannelTemplateResponseModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetById(int id, CancellationToken cancellationToken)
{
Option<ChannelTemplateResponseModel> result =
await mediator.Send(new GetChannelTemplateById(id), cancellationToken);
return result.ToGetResult();
}
[HttpPost("/api/channel-templates", Name = "CreateChannelTemplate")]
[Tags("Channel Templates")]
[EndpointSummary("Create a channel template")]
[EndpointGroupName("general")]
[ProducesResponseType(typeof(ChannelTemplateResponseModel), StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status422UnprocessableEntity)]
public async Task<IActionResult> Create(
[Required] [FromBody] CreateChannelTemplateRequest request,
CancellationToken cancellationToken)
{
Either<BaseError, ChannelTemplateResponseModel> result =
await mediator.Send(request.ToCommand(), cancellationToken);
return result.ToCreatedResult(vm => $"/api/channel-templates/{vm.Id}", vm => vm);
}
[HttpPut("/api/channel-templates/{id:int}", Name = "UpdateChannelTemplate")]
[Tags("Channel Templates")]
[EndpointSummary("Update a channel template")]
[EndpointGroupName("general")]
[ProducesResponseType(typeof(ChannelTemplateResponseModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status422UnprocessableEntity)]
public async Task<IActionResult> Update(
int id,
[Required] [FromBody] UpdateChannelTemplateRequest request,
CancellationToken cancellationToken)
{
Either<BaseError, ChannelTemplateResponseModel> result =
await mediator.Send(request.ToCommand(id), cancellationToken);
return result.ToUpdatedResult();
}
[HttpDelete("/api/channel-templates/{id:int}", Name = "DeleteChannelTemplate")]
[Tags("Channel Templates")]
[EndpointSummary("Delete a channel template")]
[EndpointGroupName("general")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status422UnprocessableEntity)]
public async Task<IActionResult> Delete(int id, CancellationToken cancellationToken)
{
Either<BaseError, Unit> result = await mediator.Send(new DeleteChannelTemplate(id), cancellationToken);
return result.ToDeletedResult();
}
}
@@ -0,0 +1,63 @@
#nullable enable
using ErsatzTV.Application.ChannelTemplates;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Scheduling;
namespace ErsatzTV.Controllers.Api.Requests;
public record CreateChannelTemplateRequest(
string Name,
string Description,
int FFmpegProfileId,
int? WatermarkId,
int? FallbackFillerId,
int? PreRollFillerId,
int? MidRollFillerId,
int? PostRollFillerId,
ChannelStreamSelectorMode StreamSelectorMode,
string? StreamSelector,
string? PreferredAudioLanguageCode,
string? PreferredAudioTitle,
ChannelPlayoutSource PlayoutSource,
ChannelPlayoutMode PlayoutMode,
StreamingMode StreamingMode,
string? PreferredSubtitleLanguageCode,
ChannelSubtitleMode SubtitleMode,
ChannelMusicVideoCreditsMode MusicVideoCreditsMode,
string? MusicVideoCreditsTemplate,
ChannelSongVideoMode SongVideoMode,
ChannelTranscodeMode TranscodeMode,
ChannelIdleBehavior IdleBehavior,
bool ShuffleScheduleItems,
bool RandomStartPoint,
FixedStartTimeBehavior FixedStartTimeBehavior)
{
public CreateChannelTemplate ToCommand() =>
new(
Name,
Description,
FFmpegProfileId,
WatermarkId,
FallbackFillerId,
PreRollFillerId,
MidRollFillerId,
PostRollFillerId,
StreamSelectorMode,
StreamSelector,
PreferredAudioLanguageCode,
PreferredAudioTitle,
PlayoutSource,
PlayoutMode,
StreamingMode,
PreferredSubtitleLanguageCode,
SubtitleMode,
MusicVideoCreditsMode,
MusicVideoCreditsTemplate,
SongVideoMode,
TranscodeMode,
IdleBehavior,
ShuffleScheduleItems,
RandomStartPoint,
FixedStartTimeBehavior);
}
@@ -0,0 +1,64 @@
#nullable enable
using ErsatzTV.Application.ChannelTemplates;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Scheduling;
namespace ErsatzTV.Controllers.Api.Requests;
public record UpdateChannelTemplateRequest(
string Name,
string Description,
int FFmpegProfileId,
int? WatermarkId,
int? FallbackFillerId,
int? PreRollFillerId,
int? MidRollFillerId,
int? PostRollFillerId,
ChannelStreamSelectorMode StreamSelectorMode,
string? StreamSelector,
string? PreferredAudioLanguageCode,
string? PreferredAudioTitle,
ChannelPlayoutSource PlayoutSource,
ChannelPlayoutMode PlayoutMode,
StreamingMode StreamingMode,
string? PreferredSubtitleLanguageCode,
ChannelSubtitleMode SubtitleMode,
ChannelMusicVideoCreditsMode MusicVideoCreditsMode,
string? MusicVideoCreditsTemplate,
ChannelSongVideoMode SongVideoMode,
ChannelTranscodeMode TranscodeMode,
ChannelIdleBehavior IdleBehavior,
bool ShuffleScheduleItems,
bool RandomStartPoint,
FixedStartTimeBehavior FixedStartTimeBehavior)
{
public UpdateChannelTemplate ToCommand(int id) =>
new(
id,
Name,
Description,
FFmpegProfileId,
WatermarkId,
FallbackFillerId,
PreRollFillerId,
MidRollFillerId,
PostRollFillerId,
StreamSelectorMode,
StreamSelector,
PreferredAudioLanguageCode,
PreferredAudioTitle,
PlayoutSource,
PlayoutMode,
StreamingMode,
PreferredSubtitleLanguageCode,
SubtitleMode,
MusicVideoCreditsMode,
MusicVideoCreditsTemplate,
SongVideoMode,
TranscodeMode,
IdleBehavior,
ShuffleScheduleItems,
RandomStartPoint,
FixedStartTimeBehavior);
}
+61
View File
@@ -0,0 +1,61 @@
using ErsatzTV.Infrastructure;
using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Logging.Abstractions;
namespace ErsatzTV;
public class TvContextDesignTimeFactory : IDesignTimeDbContextFactory<TvContext>
{
public TvContext CreateDbContext(string[] args)
{
string provider = GetProvider(args);
var optionsBuilder = new DbContextOptionsBuilder<TvContext>();
if (provider.Equals("MySql", StringComparison.OrdinalIgnoreCase))
{
TvContext.IsSqlite = false;
TvContext.LastInsertedRowId = "last_insert_id()";
TvContext.CaseInsensitiveCollation = "utf8mb4_general_ci";
string connectionString =
Environment.GetEnvironmentVariable("MySql__ConnectionString") ??
"Server=localhost;Database=ersatztv_design_time;User=root;Password=ersatztv;";
optionsBuilder.UseMySql(
connectionString,
new MySqlServerVersion(new Version(8, 0, 36)),
builder => builder.MigrationsAssembly("ErsatzTV.Infrastructure.MySql"));
}
else
{
TvContext.IsSqlite = true;
TvContext.LastInsertedRowId = "last_insert_rowid()";
TvContext.CaseInsensitiveCollation = "NOCASE";
string configFolder = Environment.GetEnvironmentVariable("ETV_CONFIG_FOLDER");
string databasePath = string.IsNullOrWhiteSpace(configFolder)
? Path.Combine(Path.GetTempPath(), "ersatztv-design-time.sqlite3")
: Path.Combine(configFolder, "ersatztv.sqlite3");
optionsBuilder.UseSqlite(
$"Data Source={databasePath}",
builder => builder.MigrationsAssembly("ErsatzTV.Infrastructure.Sqlite"));
}
return new TvContext(
optionsBuilder.Options,
NullLoggerFactory.Instance,
new SlowQueryInterceptor(NullLogger<SlowQueryInterceptor>.Instance));
}
private static string GetProvider(string[] args)
{
for (int index = 0; index < args.Length - 1; index++)
{
if (args[index].Equals("--provider", StringComparison.OrdinalIgnoreCase))
{
return args[index + 1];
}
}
return "Sqlite";
}
}
+942
View File
@@ -816,6 +816,503 @@
}
}
},
"/api/channel-templates": {
"get": {
"tags": [
"Channel Templates"
],
"summary": "Get all channel templates",
"operationId": "GetChannelTemplates",
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
}
},
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
}
},
"text/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
}
}
}
}
}
},
"post": {
"tags": [
"Channel Templates"
],
"summary": "Create a channel template",
"operationId": "CreateChannelTemplate",
"requestBody": {
"content": {
"application/json-patch+json": {
"schema": {
"$ref": "#/components/schemas/CreateChannelTemplateRequest"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateChannelTemplateRequest"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/CreateChannelTemplateRequest"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/CreateChannelTemplateRequest"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "Created",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"422": {
"description": "Unprocessable Entity",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
}
},
"/api/channel-templates/default": {
"get": {
"tags": [
"Channel Templates"
],
"summary": "Get the default channel template",
"operationId": "GetDefaultChannelTemplate",
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
}
},
"/api/channel-templates/default/{id}": {
"put": {
"tags": [
"Channel Templates"
],
"summary": "Set the default channel template",
"operationId": "SetDefaultChannelTemplate",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"422": {
"description": "Unprocessable Entity",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
}
},
"/api/channel-templates/{id}": {
"get": {
"tags": [
"Channel Templates"
],
"summary": "Get a channel template by id",
"operationId": "GetChannelTemplateById",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
},
"put": {
"tags": [
"Channel Templates"
],
"summary": "Update a channel template",
"operationId": "UpdateChannelTemplate",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"requestBody": {
"content": {
"application/json-patch+json": {
"schema": {
"$ref": "#/components/schemas/UpdateChannelTemplateRequest"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateChannelTemplateRequest"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/UpdateChannelTemplateRequest"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/UpdateChannelTemplateRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ChannelTemplateResponseModel"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"422": {
"description": "Unprocessable Entity",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
},
"delete": {
"tags": [
"Channel Templates"
],
"summary": "Delete a channel template",
"operationId": "DeleteChannelTemplate",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"204": {
"description": "No Content"
},
"404": {
"description": "Not Found",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"422": {
"description": "Unprocessable Entity",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
}
},
"/api/collections": {
"get": {
"tags": [
@@ -4289,6 +4786,162 @@
],
"type": "string"
},
"ChannelTemplateResponseModel": {
"required": [
"id",
"name",
"description",
"isSystem",
"isDefault",
"fFmpegProfileId",
"watermarkId",
"fallbackFillerId",
"preRollFillerId",
"midRollFillerId",
"postRollFillerId",
"streamSelectorMode",
"streamSelector",
"preferredAudioLanguageCode",
"preferredAudioTitle",
"playoutSource",
"playoutMode",
"streamingMode",
"preferredSubtitleLanguageCode",
"subtitleMode",
"musicVideoCreditsMode",
"musicVideoCreditsTemplate",
"songVideoMode",
"transcodeMode",
"idleBehavior",
"shuffleScheduleItems",
"randomStartPoint",
"fixedStartTimeBehavior"
],
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"isSystem": {
"type": "boolean"
},
"isDefault": {
"type": "boolean"
},
"fFmpegProfileId": {
"type": "integer",
"format": "int32"
},
"watermarkId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"fallbackFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"preRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"midRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"postRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"streamSelectorMode": {
"$ref": "#/components/schemas/ChannelStreamSelectorMode"
},
"streamSelector": {
"type": [
"null",
"string"
]
},
"preferredAudioLanguageCode": {
"type": [
"null",
"string"
]
},
"preferredAudioTitle": {
"type": [
"null",
"string"
]
},
"playoutSource": {
"$ref": "#/components/schemas/ChannelPlayoutSource"
},
"playoutMode": {
"$ref": "#/components/schemas/ChannelPlayoutMode"
},
"streamingMode": {
"$ref": "#/components/schemas/StreamingMode"
},
"preferredSubtitleLanguageCode": {
"type": [
"null",
"string"
]
},
"subtitleMode": {
"$ref": "#/components/schemas/ChannelSubtitleMode"
},
"musicVideoCreditsMode": {
"$ref": "#/components/schemas/ChannelMusicVideoCreditsMode"
},
"musicVideoCreditsTemplate": {
"type": [
"null",
"string"
]
},
"songVideoMode": {
"$ref": "#/components/schemas/ChannelSongVideoMode"
},
"transcodeMode": {
"$ref": "#/components/schemas/ChannelTranscodeMode"
},
"idleBehavior": {
"$ref": "#/components/schemas/ChannelIdleBehavior"
},
"shuffleScheduleItems": {
"type": "boolean"
},
"randomStartPoint": {
"type": "boolean"
},
"fixedStartTimeBehavior": {
"$ref": "#/components/schemas/FixedStartTimeBehavior"
}
}
},
"ChannelTranscodeMode": {
"enum": [
"OnDemand"
@@ -4697,6 +5350,149 @@
}
}
},
"CreateChannelTemplateRequest": {
"required": [
"name",
"description",
"fFmpegProfileId",
"watermarkId",
"fallbackFillerId",
"preRollFillerId",
"midRollFillerId",
"postRollFillerId",
"streamSelectorMode",
"streamSelector",
"preferredAudioLanguageCode",
"preferredAudioTitle",
"playoutSource",
"playoutMode",
"streamingMode",
"preferredSubtitleLanguageCode",
"subtitleMode",
"musicVideoCreditsMode",
"musicVideoCreditsTemplate",
"songVideoMode",
"transcodeMode",
"idleBehavior",
"shuffleScheduleItems",
"randomStartPoint",
"fixedStartTimeBehavior"
],
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"fFmpegProfileId": {
"type": "integer",
"format": "int32"
},
"watermarkId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"fallbackFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"preRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"midRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"postRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"streamSelectorMode": {
"$ref": "#/components/schemas/ChannelStreamSelectorMode"
},
"streamSelector": {
"type": [
"null",
"string"
]
},
"preferredAudioLanguageCode": {
"type": [
"null",
"string"
]
},
"preferredAudioTitle": {
"type": [
"null",
"string"
]
},
"playoutSource": {
"$ref": "#/components/schemas/ChannelPlayoutSource"
},
"playoutMode": {
"$ref": "#/components/schemas/ChannelPlayoutMode"
},
"streamingMode": {
"$ref": "#/components/schemas/StreamingMode"
},
"preferredSubtitleLanguageCode": {
"type": [
"null",
"string"
]
},
"subtitleMode": {
"$ref": "#/components/schemas/ChannelSubtitleMode"
},
"musicVideoCreditsMode": {
"$ref": "#/components/schemas/ChannelMusicVideoCreditsMode"
},
"musicVideoCreditsTemplate": {
"type": [
"null",
"string"
]
},
"songVideoMode": {
"$ref": "#/components/schemas/ChannelSongVideoMode"
},
"transcodeMode": {
"$ref": "#/components/schemas/ChannelTranscodeMode"
},
"idleBehavior": {
"$ref": "#/components/schemas/ChannelIdleBehavior"
},
"shuffleScheduleItems": {
"type": "boolean"
},
"randomStartPoint": {
"type": "boolean"
},
"fixedStartTimeBehavior": {
"$ref": "#/components/schemas/FixedStartTimeBehavior"
}
}
},
"CreateCollectionRequest": {
"required": [
"name"
@@ -7052,6 +7848,149 @@
}
}
},
"UpdateChannelTemplateRequest": {
"required": [
"name",
"description",
"fFmpegProfileId",
"watermarkId",
"fallbackFillerId",
"preRollFillerId",
"midRollFillerId",
"postRollFillerId",
"streamSelectorMode",
"streamSelector",
"preferredAudioLanguageCode",
"preferredAudioTitle",
"playoutSource",
"playoutMode",
"streamingMode",
"preferredSubtitleLanguageCode",
"subtitleMode",
"musicVideoCreditsMode",
"musicVideoCreditsTemplate",
"songVideoMode",
"transcodeMode",
"idleBehavior",
"shuffleScheduleItems",
"randomStartPoint",
"fixedStartTimeBehavior"
],
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"fFmpegProfileId": {
"type": "integer",
"format": "int32"
},
"watermarkId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"fallbackFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"preRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"midRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"postRollFillerId": {
"type": [
"null",
"integer"
],
"format": "int32"
},
"streamSelectorMode": {
"$ref": "#/components/schemas/ChannelStreamSelectorMode"
},
"streamSelector": {
"type": [
"null",
"string"
]
},
"preferredAudioLanguageCode": {
"type": [
"null",
"string"
]
},
"preferredAudioTitle": {
"type": [
"null",
"string"
]
},
"playoutSource": {
"$ref": "#/components/schemas/ChannelPlayoutSource"
},
"playoutMode": {
"$ref": "#/components/schemas/ChannelPlayoutMode"
},
"streamingMode": {
"$ref": "#/components/schemas/StreamingMode"
},
"preferredSubtitleLanguageCode": {
"type": [
"null",
"string"
]
},
"subtitleMode": {
"$ref": "#/components/schemas/ChannelSubtitleMode"
},
"musicVideoCreditsMode": {
"$ref": "#/components/schemas/ChannelMusicVideoCreditsMode"
},
"musicVideoCreditsTemplate": {
"type": [
"null",
"string"
]
},
"songVideoMode": {
"$ref": "#/components/schemas/ChannelSongVideoMode"
},
"transcodeMode": {
"$ref": "#/components/schemas/ChannelTranscodeMode"
},
"idleBehavior": {
"$ref": "#/components/schemas/ChannelIdleBehavior"
},
"shuffleScheduleItems": {
"type": "boolean"
},
"randomStartPoint": {
"type": "boolean"
},
"fixedStartTimeBehavior": {
"$ref": "#/components/schemas/FixedStartTimeBehavior"
}
}
},
"UpdateCollectionRequest": {
"required": [
"name",
@@ -7418,6 +8357,9 @@
{
"name": "Channels"
},
{
"name": "Channel Templates"
},
{
"name": "Collections"
},