diff --git a/graphql/schema/types/filters.graphql b/graphql/schema/types/filters.graphql index 190432594..b80cf851b 100644 --- a/graphql/schema/types/filters.graphql +++ b/graphql/schema/types/filters.graphql @@ -194,6 +194,10 @@ input SceneFilterType { duplicated: PHashDuplicationCriterionInput """Filter by resolution""" resolution: ResolutionCriterionInput + """Filter by video codec""" + video_codec: StringCriterionInput + """Filter by audio codec""" + audio_codec: StringCriterionInput """Filter by duration (in seconds)""" duration: IntCriterionInput """Filter to only include scenes which have markers. `true` or `false`""" diff --git a/pkg/models/scene.go b/pkg/models/scene.go index 73e7b6507..15cecb38b 100644 --- a/pkg/models/scene.go +++ b/pkg/models/scene.go @@ -45,6 +45,10 @@ type SceneFilterType struct { Duplicated *PHashDuplicationCriterionInput `json:"duplicated"` // Filter by resolution Resolution *ResolutionCriterionInput `json:"resolution"` + // Filter by video codec + VideoCodec *StringCriterionInput `json:"video_codec"` + // Filter by audio codec + AudioCodec *StringCriterionInput `json:"audio_codec"` // Filter by duration (in seconds) Duration *IntCriterionInput `json:"duration"` // Filter to only include scenes which have markers. `true` or `false` diff --git a/pkg/sqlite/scene.go b/pkg/sqlite/scene.go index f2e7f07c2..3bbcea41c 100644 --- a/pkg/sqlite/scene.go +++ b/pkg/sqlite/scene.go @@ -926,6 +926,9 @@ func (qb *SceneStore) makeFilter(ctx context.Context, sceneFilter *models.SceneF query.handleCriterion(ctx, floatIntCriterionHandler(sceneFilter.Duration, "video_files.duration", qb.addVideoFilesTable)) query.handleCriterion(ctx, resolutionCriterionHandler(sceneFilter.Resolution, "video_files.height", "video_files.width", qb.addVideoFilesTable)) + query.handleCriterion(ctx, codecCriterionHandler(sceneFilter.VideoCodec, "video_files.video_codec", qb.addVideoFilesTable)) + query.handleCriterion(ctx, codecCriterionHandler(sceneFilter.AudioCodec, "video_files.audio_codec", qb.addVideoFilesTable)) + query.handleCriterion(ctx, hasMarkersCriterionHandler(sceneFilter.HasMarkers)) query.handleCriterion(ctx, sceneIsMissingCriterionHandler(qb, sceneFilter.IsMissing)) query.handleCriterion(ctx, stringCriterionHandler(sceneFilter.URL, "scenes.url")) @@ -1201,6 +1204,18 @@ func resolutionCriterionHandler(resolution *models.ResolutionCriterionInput, hei } } +func codecCriterionHandler(codec *models.StringCriterionInput, codecColumn string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc { + return func(ctx context.Context, f *filterBuilder) { + if codec != nil { + if addJoinFn != nil { + addJoinFn(f) + } + + stringCriterionHandler(codec, codecColumn)(ctx, f) + } + } +} + func hasMarkersCriterionHandler(hasMarkers *string) criterionHandlerFunc { return func(ctx context.Context, f *filterBuilder) { if hasMarkers != nil { diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index e5ca446f1..4e0f3f144 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -129,6 +129,7 @@ "also_known_as": "Also known as", "appears_with": "Appears With", "ascending": "Ascending", + "audio_codec": "Audio Codec", "average_resolution": "Average Resolution", "between_and": "and", "birth_year": "Birth Year", @@ -1259,6 +1260,7 @@ "required": "${path} is a required field" }, "videos": "Videos", + "video_codec": "Video Codec", "view_all": "View All", "weight": "Weight", "weight_kg": "Weight (kg)", diff --git a/ui/v2.5/src/models/list-filter/criteria/factory.ts b/ui/v2.5/src/models/list-filter/criteria/factory.ts index 5096a14b0..d45042aa0 100644 --- a/ui/v2.5/src/models/list-filter/criteria/factory.ts +++ b/ui/v2.5/src/models/list-filter/criteria/factory.ts @@ -107,6 +107,10 @@ export function makeCriteria( return new ResolutionCriterion(); case "average_resolution": return new AverageResolutionCriterion(); + case "video_codec": + return new StringCriterion(new StringCriterionOption(type, type)); + case "audio_codec": + return new StringCriterion(new StringCriterionOption(type, type)); case "resume_time": case "duration": case "play_duration": diff --git a/ui/v2.5/src/models/list-filter/scenes.ts b/ui/v2.5/src/models/list-filter/scenes.ts index f4be9f78a..106875a12 100644 --- a/ui/v2.5/src/models/list-filter/scenes.ts +++ b/ui/v2.5/src/models/list-filter/scenes.ts @@ -75,6 +75,8 @@ const criterionOptions = [ new NullNumberCriterionOption("rating", "rating100"), createMandatoryNumberCriterionOption("o_counter"), ResolutionCriterionOption, + createStringCriterionOption("video_codec"), + createStringCriterionOption("audio_codec"), createMandatoryNumberCriterionOption("duration"), createMandatoryNumberCriterionOption("resume_time"), createMandatoryNumberCriterionOption("play_duration"), diff --git a/ui/v2.5/src/models/list-filter/types.ts b/ui/v2.5/src/models/list-filter/types.ts index 79731eb3b..a200024f7 100644 --- a/ui/v2.5/src/models/list-filter/types.ts +++ b/ui/v2.5/src/models/list-filter/types.ts @@ -109,6 +109,8 @@ export type CriterionType = | "o_counter" | "resolution" | "average_resolution" + | "video_codec" + | "audio_codec" | "duration" | "favorite" | "hasMarkers"