Browse Source

api changes for ffmpeg profiles (#2520)

pull/2521/head
Jason Dove 3 months ago committed by GitHub
parent
commit
b851a7daba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 20
      ErsatzTV.Application/FFmpegProfiles/Mapper.cs
  2. 2
      ErsatzTV.Application/FFmpegProfiles/Queries/GetAllFFmpegProfilesForApi.cs
  3. 15
      ErsatzTV.Application/FFmpegProfiles/Queries/GetAllFFmpegProfilesForApiHandler.cs
  4. 5
      ErsatzTV.Application/FFmpegProfiles/Queries/GetResolutionByName.cs
  5. 18
      ErsatzTV.Application/FFmpegProfiles/Queries/GetResolutionByNameHandler.cs
  6. 25
      ErsatzTV.Core/Api/FFmpegProfiles/FFmpegFullProfileResponseModel.cs
  7. 5
      ErsatzTV.Core/Domain/FFmpegProfileAudioFormat.cs
  8. 3
      ErsatzTV.Core/Domain/FFmpegProfileBitDepth.cs
  9. 3
      ErsatzTV.Core/Domain/FFmpegProfileTonemapAlgorithm.cs
  10. 5
      ErsatzTV.Core/Domain/FFmpegProfileVideoFormat.cs
  11. 5
      ErsatzTV.Core/Domain/HardwareAccelerationKind.cs
  12. 3
      ErsatzTV.Core/Domain/NormalizeLoudnessMode.cs
  13. 3
      ErsatzTV.Core/Domain/ScalingBehavior.cs
  14. 2
      ErsatzTV.Core/FFmpeg/VaapiDriver.cs
  15. 45
      ErsatzTV/Controllers/Api/FFmpegProfileController.cs
  16. 18
      ErsatzTV/Controllers/Api/ResolutionController.cs
  17. 2
      ErsatzTV/Controllers/Api/VersionController.cs
  18. 633
      ErsatzTV/wwwroot/openapi/v1.json

20
ErsatzTV.Application/FFmpegProfiles/Mapper.cs

@ -47,19 +47,25 @@ internal static class Mapper @@ -47,19 +47,25 @@ internal static class Mapper
ffmpegProfile.Id,
ffmpegProfile.Name,
ffmpegProfile.ThreadCount,
(int)ffmpegProfile.HardwareAcceleration,
ffmpegProfile.HardwareAcceleration,
ffmpegProfile.VaapiDisplay,
(int)ffmpegProfile.VaapiDriver,
ffmpegProfile.VaapiDriver,
ffmpegProfile.VaapiDevice,
ffmpegProfile.ResolutionId,
(int)ffmpegProfile.VideoFormat,
ffmpegProfile.QsvExtraHardwareFrames,
ffmpegProfile.Resolution.Name,
ffmpegProfile.ScalingBehavior,
ffmpegProfile.VideoFormat,
ffmpegProfile.VideoProfile,
ffmpegProfile.VideoPreset,
ffmpegProfile.AllowBFrames,
ffmpegProfile.BitDepth,
ffmpegProfile.VideoBitrate,
ffmpegProfile.VideoBufferSize,
(int)ffmpegProfile.TonemapAlgorithm,
(int)ffmpegProfile.AudioFormat,
ffmpegProfile.TonemapAlgorithm,
ffmpegProfile.AudioFormat,
ffmpegProfile.AudioBitrate,
ffmpegProfile.AudioBufferSize,
(int)ffmpegProfile.NormalizeLoudnessMode,
ffmpegProfile.NormalizeLoudnessMode,
ffmpegProfile.AudioChannels,
ffmpegProfile.AudioSampleRate,
ffmpegProfile.NormalizeFramerate,

2
ErsatzTV.Application/FFmpegProfiles/Queries/GetAllFFmpegProfilesForApi.cs

@ -2,4 +2,4 @@ @@ -2,4 +2,4 @@
namespace ErsatzTV.Application.FFmpegProfiles;
public record GetAllFFmpegProfilesForApi : IRequest<List<FFmpegProfileResponseModel>>;
public record GetAllFFmpegProfilesForApi : IRequest<List<FFmpegFullProfileResponseModel>>;

15
ErsatzTV.Application/FFmpegProfiles/Queries/GetAllFFmpegProfilesForApiHandler.cs

@ -6,23 +6,18 @@ using static ErsatzTV.Application.FFmpegProfiles.Mapper; @@ -6,23 +6,18 @@ using static ErsatzTV.Application.FFmpegProfiles.Mapper;
namespace ErsatzTV.Application.FFmpegProfiles;
public class
GetAllFFmpegProfilesForApiHandler : IRequestHandler<GetAllFFmpegProfilesForApi, List<FFmpegProfileResponseModel>>
public class GetAllFFmpegProfilesForApiHandler(IDbContextFactory<TvContext> dbContextFactory)
: IRequestHandler<GetAllFFmpegProfilesForApi, List<FFmpegFullProfileResponseModel>>
{
private readonly IDbContextFactory<TvContext> _dbContextFactory;
public GetAllFFmpegProfilesForApiHandler(IDbContextFactory<TvContext> dbContextFactory) =>
_dbContextFactory = dbContextFactory;
public async Task<List<FFmpegProfileResponseModel>> Handle(
public async Task<List<FFmpegFullProfileResponseModel>> Handle(
GetAllFFmpegProfilesForApi request,
CancellationToken cancellationToken)
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
List<FFmpegProfile> ffmpegProfiles = await dbContext.FFmpegProfiles
.AsNoTracking()
.Include(p => p.Resolution)
.ToListAsync(cancellationToken);
return ffmpegProfiles.Map(ProjectToResponseModel).ToList();
return ffmpegProfiles.Map(ProjectToFullResponseModel).ToList();
}
}

5
ErsatzTV.Application/FFmpegProfiles/Queries/GetResolutionByName.cs

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
using ErsatzTV.Core;
namespace ErsatzTV.Application.FFmpegProfiles;
public record GetResolutionByName(string Name) : IRequest<Option<int>>;

18
ErsatzTV.Application/FFmpegProfiles/Queries/GetResolutionByNameHandler.cs

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions;
using Microsoft.EntityFrameworkCore;
namespace ErsatzTV.Application.FFmpegProfiles;
public class GetResolutionByNameHandler(IDbContextFactory<TvContext> dbContextFactory)
: IRequestHandler<GetResolutionByName, Option<int>>
{
public async Task<Option<int>> Handle(GetResolutionByName request, CancellationToken cancellationToken)
{
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
return await dbContext.Resolutions
.AsNoTracking()
.SelectOneAsync(r => r.Name, r => r.Name == request.Name, cancellationToken)
.MapT(r => r.Id);
}
}

25
ErsatzTV.Core/Api/FFmpegProfiles/FFmpegFullProfileResponseModel.cs

@ -1,22 +1,31 @@ @@ -1,22 +1,31 @@
namespace ErsatzTV.Core.Api.FFmpegProfiles;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.FFmpeg;
namespace ErsatzTV.Core.Api.FFmpegProfiles;
public record FFmpegFullProfileResponseModel(
int Id,
string Name,
int ThreadCount,
int HardwareAcceleration,
HardwareAccelerationKind HardwareAcceleration,
string VaapiDisplay,
int VaapiDriver,
VaapiDriver VaapiDriver,
string VaapiDevice,
int ResolutionId,
int VideoFormat,
int? QsvExtraHardwareFrames,
string Resolution,
ScalingBehavior ScalingBehavior,
FFmpegProfileVideoFormat VideoFormat,
string VideoProfile,
string VideoPreset,
bool AllowBFrames,
FFmpegProfileBitDepth BitDepth,
int VideoBitrate,
int VideoBufferSize,
int TonemapAlgorithm,
int AudioFormat,
FFmpegProfileTonemapAlgorithm TonemapAlgorithm,
FFmpegProfileAudioFormat AudioFormat,
int AudioBitrate,
int AudioBufferSize,
int NormalizeLoudnessMode,
NormalizeLoudnessMode NormalizeLoudnessMode,
int AudioChannels,
int AudioSampleRate,
bool NormalizeFramerate,

5
ErsatzTV.Core/Domain/FFmpegProfileAudioFormat.cs

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
namespace ErsatzTV.Core.Domain;
using System.Text.Json.Serialization;
namespace ErsatzTV.Core.Domain;
[JsonConverter(typeof(JsonStringEnumConverter<FFmpegProfileAudioFormat>))]
public enum FFmpegProfileAudioFormat
{
None = 0,

3
ErsatzTV.Core/Domain/FFmpegProfileBitDepth.cs

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
using System.Text.Json.Serialization;
namespace ErsatzTV.Core.Domain;
[JsonConverter(typeof(JsonStringEnumConverter<FFmpegProfileBitDepth>))]
public enum FFmpegProfileBitDepth
{
EightBit = 0,

3
ErsatzTV.Core/Domain/FFmpegProfileTonemapAlgorithm.cs

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
using System.Text.Json.Serialization;
namespace ErsatzTV.Core.Domain;
[JsonConverter(typeof(JsonStringEnumConverter<FFmpegProfileTonemapAlgorithm>))]
public enum FFmpegProfileTonemapAlgorithm
{
Linear = 0,

5
ErsatzTV.Core/Domain/FFmpegProfileVideoFormat.cs

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
namespace ErsatzTV.Core.Domain;
using System.Text.Json.Serialization;
namespace ErsatzTV.Core.Domain;
[JsonConverter(typeof(JsonStringEnumConverter<FFmpegProfileVideoFormat>))]
public enum FFmpegProfileVideoFormat
{
None = 0,

5
ErsatzTV.Core/Domain/HardwareAccelerationKind.cs

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
namespace ErsatzTV.Core.Domain;
using System.Text.Json.Serialization;
namespace ErsatzTV.Core.Domain;
[JsonConverter(typeof(JsonStringEnumConverter<HardwareAccelerationKind>))]
public enum HardwareAccelerationKind
{
None = 0,

3
ErsatzTV.Core/Domain/NormalizeLoudnessMode.cs

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
using System.Text.Json.Serialization;
namespace ErsatzTV.Core.Domain;
[JsonConverter(typeof(JsonStringEnumConverter<NormalizeLoudnessMode>))]
public enum NormalizeLoudnessMode
{
Off = 0,

3
ErsatzTV.Core/Domain/ScalingBehavior.cs

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
using System.Text.Json.Serialization;
namespace ErsatzTV.Core.Domain;
[JsonConverter(typeof(JsonStringEnumConverter<ScalingBehavior>))]
public enum ScalingBehavior
{
ScaleAndPad = 0,

2
ErsatzTV.Core/FFmpeg/VaapiDriver.cs

@ -1,8 +1,10 @@ @@ -1,8 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ErsatzTV.Core.FFmpeg;
[SuppressMessage("ReSharper", "InconsistentNaming")]
[JsonConverter(typeof(JsonStringEnumConverter<VaapiDriver>))]
public enum VaapiDriver
{
Default = 0,

45
ErsatzTV/Controllers/Api/FFmpegProfileController.cs

@ -2,34 +2,43 @@ @@ -2,34 +2,43 @@
using ErsatzTV.Application.FFmpegProfiles;
using ErsatzTV.Core;
using ErsatzTV.Core.Api.FFmpegProfiles;
using ErsatzTV.Filters;
using MediatR;
using Microsoft.AspNetCore.Mvc;
namespace ErsatzTV.Controllers.Api;
[ApiController]
[V2ApiActionFilter]
public class FFmpegProfileController(IMediator mediator)
[EndpointGroupName("general")]
public class FFmpegProfileController(IMediator mediator) : ControllerBase
{
[HttpGet("/api/ffmpeg/profiles")]
public async Task<List<FFmpegProfileResponseModel>> GetAll() =>
await mediator.Send(new GetAllFFmpegProfilesForApi());
[HttpGet("/api/ffmpeg/profiles", Name="GetFFmpegProfiles")]
public async Task<List<FFmpegFullProfileResponseModel>> GetAll(CancellationToken cancellationToken) =>
await mediator.Send(new GetAllFFmpegProfilesForApi(), cancellationToken);
[HttpPost("/api/ffmpeg/profiles/new")]
public async Task<Either<BaseError, CreateFFmpegProfileResult>> AddOne(
[HttpPost("/api/ffmpeg/profiles/new", Name="CreateFFmpegProfile")]
public async Task<IActionResult> AddOne(
[Required] [FromBody]
CreateFFmpegProfile request) => await mediator.Send(request);
CreateFFmpegProfile request,
CancellationToken cancellationToken)
{
Either<BaseError, CreateFFmpegProfileResult> result = await mediator.Send(request, cancellationToken);
return result.Match<IActionResult>(Ok, error => Problem(error.ToString()));
}
[HttpPut("/api/ffmpeg/profiles/update")]
public async Task<Either<BaseError, UpdateFFmpegProfileResult>> UpdateOne(
[HttpPut("/api/ffmpeg/profiles/update", Name="UpdateFFmpegProfile")]
public async Task<IActionResult> UpdateOne(
[Required] [FromBody]
UpdateFFmpegProfile request) => await mediator.Send(request);
UpdateFFmpegProfile request,
CancellationToken cancellationToken)
{
Either<BaseError, UpdateFFmpegProfileResult> result = await mediator.Send(request, cancellationToken);
return result.Match<IActionResult>(Ok, error => Problem(error.ToString()));
}
[HttpGet("/api/ffmpeg/profiles/{id:int}")]
public async Task<Option<FFmpegFullProfileResponseModel>> GetOne(int id) =>
await mediator.Send(new GetFFmpegFullProfileByIdForApi(id));
[HttpDelete("/api/ffmpeg/delete/{id:int}")]
public async Task DeleteProfileAsync(int id) => await mediator.Send(new DeleteFFmpegProfile(id));
[HttpDelete("/api/ffmpeg/delete/{id:int}", Name="DeleteFFmpegProfile")]
public async Task<IActionResult> DeleteProfileAsync(int id, CancellationToken cancellationToken)
{
Either<BaseError, Unit> result = await mediator.Send(new DeleteFFmpegProfile(id), cancellationToken);
return result.Match<IActionResult>(_ => Ok(), error => Problem(error.ToString()));
}
}

18
ErsatzTV/Controllers/Api/ResolutionController.cs

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
using ErsatzTV.Application.FFmpegProfiles;
using MediatR;
using Microsoft.AspNetCore.Mvc;
namespace ErsatzTV.Controllers.Api;
[ApiController]
[EndpointGroupName("general")]
public class ResolutionController(IMediator mediator) : ControllerBase
{
[HttpGet("/api/ffmpeg/resolution/by-name/{name}", Name="GetResolutionByName")]
public async Task<ActionResult<int>> GetResolutionByName(string name, CancellationToken cancellationToken)
{
Option<int> result = await mediator.Send(new GetResolutionByName(name), cancellationToken);
return result.Match<ActionResult<int>>(i => Ok(i), () => NotFound());
}
}

2
ErsatzTV/Controllers/Api/VersionController.cs

@ -11,7 +11,7 @@ public class VersionController @@ -11,7 +11,7 @@ public class VersionController
static VersionController() =>
Version = new CombinedVersion(
1,
2,
Assembly.GetEntryAssembly()?
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
.InformationalVersion ?? "unknown");

633
ErsatzTV/wwwroot/openapi/v1.json

@ -66,6 +66,145 @@ @@ -66,6 +66,145 @@
}
}
},
"/api/ffmpeg/profiles": {
"get": {
"tags": [
"FFmpegProfile"
],
"operationId": "GetFFmpegProfiles",
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/FFmpegFullProfileResponseModel"
}
}
},
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/FFmpegFullProfileResponseModel"
}
}
},
"text/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/FFmpegFullProfileResponseModel"
}
}
}
}
}
}
}
},
"/api/ffmpeg/profiles/new": {
"post": {
"tags": [
"FFmpegProfile"
],
"operationId": "CreateFFmpegProfile",
"requestBody": {
"content": {
"application/json-patch+json": {
"schema": {
"$ref": "#/components/schemas/CreateFFmpegProfile"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateFFmpegProfile"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/CreateFFmpegProfile"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/CreateFFmpegProfile"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/api/ffmpeg/profiles/update": {
"put": {
"tags": [
"FFmpegProfile"
],
"operationId": "UpdateFFmpegProfile",
"requestBody": {
"content": {
"application/json-patch+json": {
"schema": {
"$ref": "#/components/schemas/UpdateFFmpegProfile"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateFFmpegProfile"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/UpdateFFmpegProfile"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/UpdateFFmpegProfile"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/api/ffmpeg/delete/{id}": {
"delete": {
"tags": [
"FFmpegProfile"
],
"operationId": "DeleteFFmpegProfile",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/api/libraries/{id}/scan": {
"post": {
"tags": [
@ -175,6 +314,49 @@ @@ -175,6 +314,49 @@
}
}
},
"/api/ffmpeg/resolution/by-name/{name}": {
"get": {
"tags": [
"Resolution"
],
"operationId": "GetResolutionByName",
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"type": "integer",
"format": "int32"
}
},
"application/json": {
"schema": {
"type": "integer",
"format": "int32"
}
},
"text/json": {
"schema": {
"type": "integer",
"format": "int32"
}
}
}
}
}
}
},
"/api/sessions": {
"get": {
"tags": [
@ -464,6 +646,128 @@ @@ -464,6 +646,128 @@
}
}
},
"CreateFFmpegProfile": {
"required": [
"name",
"threadCount",
"hardwareAcceleration",
"vaapiDisplay",
"vaapiDriver",
"vaapiDevice",
"qsvExtraHardwareFrames",
"resolutionId",
"scalingBehavior",
"videoFormat",
"videoProfile",
"videoPreset",
"allowBFrames",
"bitDepth",
"videoBitrate",
"videoBufferSize",
"tonemapAlgorithm",
"audioFormat",
"audioBitrate",
"audioBufferSize",
"normalizeLoudnessMode",
"audioChannels",
"audioSampleRate",
"normalizeFramerate",
"deinterlaceVideo"
],
"type": "object",
"properties": {
"name": {
"type": "string",
"nullable": true
},
"threadCount": {
"type": "integer",
"format": "int32"
},
"hardwareAcceleration": {
"$ref": "#/components/schemas/HardwareAccelerationKind"
},
"vaapiDisplay": {
"type": "string",
"nullable": true
},
"vaapiDriver": {
"$ref": "#/components/schemas/VaapiDriver"
},
"vaapiDevice": {
"type": "string",
"nullable": true
},
"qsvExtraHardwareFrames": {
"type": "integer",
"format": "int32",
"nullable": true
},
"resolutionId": {
"type": "integer",
"format": "int32"
},
"scalingBehavior": {
"$ref": "#/components/schemas/ScalingBehavior"
},
"videoFormat": {
"$ref": "#/components/schemas/FFmpegProfileVideoFormat"
},
"videoProfile": {
"type": "string",
"nullable": true
},
"videoPreset": {
"type": "string",
"nullable": true
},
"allowBFrames": {
"type": "boolean"
},
"bitDepth": {
"$ref": "#/components/schemas/FFmpegProfileBitDepth"
},
"videoBitrate": {
"type": "integer",
"format": "int32"
},
"videoBufferSize": {
"type": "integer",
"format": "int32"
},
"tonemapAlgorithm": {
"$ref": "#/components/schemas/FFmpegProfileTonemapAlgorithm"
},
"audioFormat": {
"$ref": "#/components/schemas/FFmpegProfileAudioFormat"
},
"audioBitrate": {
"type": "integer",
"format": "int32"
},
"audioBufferSize": {
"type": "integer",
"format": "int32"
},
"normalizeLoudnessMode": {
"$ref": "#/components/schemas/NormalizeLoudnessMode"
},
"audioChannels": {
"type": "integer",
"format": "int32"
},
"audioSampleRate": {
"type": "integer",
"format": "int32"
},
"normalizeFramerate": {
"type": "boolean"
},
"deinterlaceVideo": {
"type": "boolean"
}
}
},
"CreateSmartCollection": {
"required": [
"query",
@ -481,6 +785,180 @@ @@ -481,6 +785,180 @@
}
}
},
"FFmpegFullProfileResponseModel": {
"required": [
"id",
"name",
"threadCount",
"hardwareAcceleration",
"vaapiDisplay",
"vaapiDriver",
"vaapiDevice",
"qsvExtraHardwareFrames",
"resolution",
"scalingBehavior",
"videoFormat",
"videoProfile",
"videoPreset",
"allowBFrames",
"bitDepth",
"videoBitrate",
"videoBufferSize",
"tonemapAlgorithm",
"audioFormat",
"audioBitrate",
"audioBufferSize",
"normalizeLoudnessMode",
"audioChannels",
"audioSampleRate",
"normalizeFramerate",
"deinterlaceVideo"
],
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string",
"nullable": true
},
"threadCount": {
"type": "integer",
"format": "int32"
},
"hardwareAcceleration": {
"$ref": "#/components/schemas/HardwareAccelerationKind"
},
"vaapiDisplay": {
"type": "string",
"nullable": true
},
"vaapiDriver": {
"$ref": "#/components/schemas/VaapiDriver"
},
"vaapiDevice": {
"type": "string",
"nullable": true
},
"qsvExtraHardwareFrames": {
"type": "integer",
"format": "int32",
"nullable": true
},
"resolution": {
"type": "string",
"nullable": true
},
"scalingBehavior": {
"$ref": "#/components/schemas/ScalingBehavior"
},
"videoFormat": {
"$ref": "#/components/schemas/FFmpegProfileVideoFormat"
},
"videoProfile": {
"type": "string",
"nullable": true
},
"videoPreset": {
"type": "string",
"nullable": true
},
"allowBFrames": {
"type": "boolean"
},
"bitDepth": {
"$ref": "#/components/schemas/FFmpegProfileBitDepth"
},
"videoBitrate": {
"type": "integer",
"format": "int32"
},
"videoBufferSize": {
"type": "integer",
"format": "int32"
},
"tonemapAlgorithm": {
"$ref": "#/components/schemas/FFmpegProfileTonemapAlgorithm"
},
"audioFormat": {
"$ref": "#/components/schemas/FFmpegProfileAudioFormat"
},
"audioBitrate": {
"type": "integer",
"format": "int32"
},
"audioBufferSize": {
"type": "integer",
"format": "int32"
},
"normalizeLoudnessMode": {
"$ref": "#/components/schemas/NormalizeLoudnessMode"
},
"audioChannels": {
"type": "integer",
"format": "int32"
},
"audioSampleRate": {
"type": "integer",
"format": "int32"
},
"normalizeFramerate": {
"type": "boolean"
},
"deinterlaceVideo": {
"type": "boolean",
"nullable": true
}
}
},
"FFmpegProfileAudioFormat": {
"enum": [
"None",
"Aac",
"Ac3",
"Copy"
]
},
"FFmpegProfileBitDepth": {
"enum": [
"EightBit",
"TenBit"
]
},
"FFmpegProfileTonemapAlgorithm": {
"enum": [
"Linear",
"Clip",
"Gamma",
"Reinhard",
"Mobius",
"Hable"
]
},
"FFmpegProfileVideoFormat": {
"enum": [
"None",
"H264",
"Hevc",
"Mpeg2Video",
"Av1",
"Copy"
]
},
"HardwareAccelerationKind": {
"enum": [
"None",
"Qsv",
"Nvenc",
"Vaapi",
"VideoToolbox",
"Amf",
"V4l2m2m",
"Rkmpp"
]
},
"HlsSessionModel": {
"required": [
"channelNumber",
@ -508,6 +986,19 @@ @@ -508,6 +986,19 @@
}
}
},
"NormalizeLoudnessMode": {
"enum": [
"Off",
"LoudNorm"
]
},
"ScalingBehavior": {
"enum": [
"ScaleAndPad",
"Stretch",
"Crop"
]
},
"ScanShowRequest": {
"required": [
"showTitle"
@ -546,6 +1037,133 @@ @@ -546,6 +1037,133 @@
}
}
},
"UpdateFFmpegProfile": {
"required": [
"fFmpegProfileId",
"name",
"threadCount",
"hardwareAcceleration",
"vaapiDisplay",
"vaapiDriver",
"vaapiDevice",
"qsvExtraHardwareFrames",
"resolutionId",
"scalingBehavior",
"videoFormat",
"videoProfile",
"videoPreset",
"allowBFrames",
"bitDepth",
"videoBitrate",
"videoBufferSize",
"tonemapAlgorithm",
"audioFormat",
"audioBitrate",
"audioBufferSize",
"normalizeLoudnessMode",
"audioChannels",
"audioSampleRate",
"normalizeFramerate",
"deinterlaceVideo"
],
"type": "object",
"properties": {
"fFmpegProfileId": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string",
"nullable": true
},
"threadCount": {
"type": "integer",
"format": "int32"
},
"hardwareAcceleration": {
"$ref": "#/components/schemas/HardwareAccelerationKind"
},
"vaapiDisplay": {
"type": "string",
"nullable": true
},
"vaapiDriver": {
"$ref": "#/components/schemas/VaapiDriver"
},
"vaapiDevice": {
"type": "string",
"nullable": true
},
"qsvExtraHardwareFrames": {
"type": "integer",
"format": "int32",
"nullable": true
},
"resolutionId": {
"type": "integer",
"format": "int32"
},
"scalingBehavior": {
"$ref": "#/components/schemas/ScalingBehavior"
},
"videoFormat": {
"$ref": "#/components/schemas/FFmpegProfileVideoFormat"
},
"videoProfile": {
"type": "string",
"nullable": true
},
"videoPreset": {
"type": "string",
"nullable": true
},
"allowBFrames": {
"type": "boolean"
},
"bitDepth": {
"$ref": "#/components/schemas/FFmpegProfileBitDepth"
},
"videoBitrate": {
"type": "integer",
"format": "int32"
},
"videoBufferSize": {
"type": "integer",
"format": "int32"
},
"tonemapAlgorithm": {
"$ref": "#/components/schemas/FFmpegProfileTonemapAlgorithm"
},
"audioFormat": {
"$ref": "#/components/schemas/FFmpegProfileAudioFormat"
},
"audioBitrate": {
"type": "integer",
"format": "int32"
},
"audioBufferSize": {
"type": "integer",
"format": "int32"
},
"normalizeLoudnessMode": {
"$ref": "#/components/schemas/NormalizeLoudnessMode"
},
"audioChannels": {
"type": "integer",
"format": "int32"
},
"audioSampleRate": {
"type": "integer",
"format": "int32"
},
"normalizeFramerate": {
"type": "boolean"
},
"deinterlaceVideo": {
"type": "boolean"
}
}
},
"UpdateSmartCollection": {
"required": [
"id",
@ -567,6 +1185,15 @@ @@ -567,6 +1185,15 @@
"nullable": true
}
}
},
"VaapiDriver": {
"enum": [
"Default",
"iHD",
"i965",
"RadeonSI",
"Nouveau"
]
}
}
},
@ -577,12 +1204,18 @@ @@ -577,12 +1204,18 @@
{
"name": "Channels"
},
{
"name": "FFmpegProfile"
},
{
"name": "Libraries"
},
{
"name": "Maintenance"
},
{
"name": "Resolution"
},
{
"name": "Sessions"
},

Loading…
Cancel
Save