From f1786ad871ecc128d75d03c42130a25f314ae3e0 Mon Sep 17 00:00:00 2001 From: bnkai <48220860+bnkai@users.noreply.github.com> Date: Fri, 11 Jun 2021 08:01:32 +0300 Subject: [PATCH] Make audio stream optional for preview generation (#1454) --- graphql/documents/data/config.graphql | 1 + graphql/schema/types/config.graphql | 4 ++++ pkg/api/resolver_mutation_configure.go | 3 +++ pkg/api/resolver_query_configuration.go | 1 + pkg/ffmpeg/encoder_scene_preview_chunk.go | 19 +++++++++++++++---- pkg/manager/config/config.go | 14 +++++++++++--- pkg/manager/generator.go | 2 ++ pkg/manager/generator_preview.go | 3 +++ pkg/manager/task_generate_preview.go | 2 ++ .../src/components/Changelog/versions/v080.md | 1 + .../Settings/SettingsConfigurationPanel.tsx | 16 ++++++++++++++++ 11 files changed, 59 insertions(+), 7 deletions(-) diff --git a/graphql/documents/data/config.graphql b/graphql/documents/data/config.graphql index b18fb7c91..878f53298 100644 --- a/graphql/documents/data/config.graphql +++ b/graphql/documents/data/config.graphql @@ -10,6 +10,7 @@ fragment ConfigGeneralData on ConfigGeneralResult { calculateMD5 videoFileNamingAlgorithm parallelTasks + previewAudio previewSegments previewSegmentDuration previewExcludeStart diff --git a/graphql/schema/types/config.graphql b/graphql/schema/types/config.graphql index f5b039b04..d9c3ae52c 100644 --- a/graphql/schema/types/config.graphql +++ b/graphql/schema/types/config.graphql @@ -47,6 +47,8 @@ input ConfigGeneralInput { videoFileNamingAlgorithm: HashAlgorithm! """Number of parallel tasks to start during scan/generate""" parallelTasks: Int + """Include audio stream in previews""" + previewAudio: Boolean! """Number of segments in a preview file""" previewSegments: Int """Preview segment duration, in seconds""" @@ -116,6 +118,8 @@ type ConfigGeneralResult { videoFileNamingAlgorithm: HashAlgorithm! """Number of parallel tasks to start during scan/generate""" parallelTasks: Int! + """Include audio stream in previews""" + previewAudio: Boolean! """Number of segments in a preview file""" previewSegments: Int! """Preview segment duration, in seconds""" diff --git a/pkg/api/resolver_mutation_configure.go b/pkg/api/resolver_mutation_configure.go index 681f04a61..7154ff219 100644 --- a/pkg/api/resolver_mutation_configure.go +++ b/pkg/api/resolver_mutation_configure.go @@ -88,6 +88,9 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input models.Co if input.ParallelTasks != nil { c.Set(config.ParallelTasks, *input.ParallelTasks) } + + c.Set(config.PreviewAudio, input.PreviewAudio) + if input.PreviewSegments != nil { c.Set(config.PreviewSegments, *input.PreviewSegments) } diff --git a/pkg/api/resolver_query_configuration.go b/pkg/api/resolver_query_configuration.go index 0f553dc0f..a3e226073 100644 --- a/pkg/api/resolver_query_configuration.go +++ b/pkg/api/resolver_query_configuration.go @@ -62,6 +62,7 @@ func makeConfigGeneralResult() *models.ConfigGeneralResult { CalculateMd5: config.IsCalculateMD5(), VideoFileNamingAlgorithm: config.GetVideoFileNamingAlgorithm(), ParallelTasks: config.GetParallelTasks(), + PreviewAudio: config.GetPreviewAudio(), PreviewSegments: config.GetPreviewSegments(), PreviewSegmentDuration: config.GetPreviewSegmentDuration(), PreviewExcludeStart: config.GetPreviewExcludeStart(), diff --git a/pkg/ffmpeg/encoder_scene_preview_chunk.go b/pkg/ffmpeg/encoder_scene_preview_chunk.go index 3251e8e44..a0b53a93f 100644 --- a/pkg/ffmpeg/encoder_scene_preview_chunk.go +++ b/pkg/ffmpeg/encoder_scene_preview_chunk.go @@ -12,6 +12,7 @@ type ScenePreviewChunkOptions struct { Duration float64 Width int OutputPath string + Audio bool } func (e *Encoder) ScenePreviewVideoChunk(probeResult VideoFile, options ScenePreviewChunkOptions, preset string, fallback bool) error { @@ -23,6 +24,17 @@ func (e *Encoder) ScenePreviewVideoChunk(probeResult VideoFile, options ScenePre "-v", "error", } + argsAudio := []string{ + "-c:a", "aac", + "-b:a", "128k", + } + + if !options.Audio { + argsAudio = []string{ + "-an", + } + } + // Non-fallback: enable xerror. // "-xerror" causes ffmpeg to fail on warnings, often the preview is fine but could be broken. if !fallback { @@ -70,13 +82,12 @@ func (e *Encoder) ScenePreviewVideoChunk(probeResult VideoFile, options ScenePre "-crf", "21", "-threads", "4", "-vf", fmt.Sprintf("scale=%v:-2", options.Width), - "-c:a", "aac", - "-b:a", "128k", "-strict", "-2", - options.OutputPath, } - finalArgs := append(args, args2...) + args3 := append(args, args2...) + args3 = append(args3, argsAudio...) + finalArgs := append(args3, options.OutputPath) _, err := e.run(probeResult, finalArgs) return err diff --git a/pkg/manager/config/config.go b/pkg/manager/config/config.go index 61aba72aa..0cf5d259b 100644 --- a/pkg/manager/config/config.go +++ b/pkg/manager/config/config.go @@ -56,14 +56,17 @@ const CalculateMD5 = "calculate_md5" // should be used when generating and using generated files for scenes. const VideoFileNamingAlgorithm = "video_file_naming_algorithm" -const PreviewPreset = "preview_preset" - const MaxTranscodeSize = "max_transcode_size" const MaxStreamingTranscodeSize = "max_streaming_transcode_size" const ParallelTasks = "parallel_tasks" const parallelTasksDefault = 1 +const PreviewPreset = "preview_preset" + +const PreviewAudio = "preview_audio" +const previewAudioDefault = true + const PreviewSegmentDuration = "preview_segment_duration" const previewSegmentDurationDefault = 0.75 @@ -403,6 +406,11 @@ func (i *Instance) GetParallelTasksWithAutoDetection() int { return parallelTasks } +func (i *Instance) GetPreviewAudio() bool { + viper.SetDefault(PreviewAudio, previewAudioDefault) + return viper.GetBool(PreviewAudio) +} + // GetPreviewSegments returns the amount of segments in a scene preview file. func (i *Instance) GetPreviewSegments() int { return viper.GetInt(PreviewSegments) @@ -560,7 +568,6 @@ func (i *Instance) GetMenuItems() []string { } func (i *Instance) GetSoundOnPreview() bool { - viper.SetDefault(SoundOnPreview, false) return viper.GetBool(SoundOnPreview) } @@ -740,6 +747,7 @@ func (i *Instance) setDefaultValues() error { viper.SetDefault(PreviewSegments, previewSegmentsDefault) viper.SetDefault(PreviewExcludeStart, previewExcludeStartDefault) viper.SetDefault(PreviewExcludeEnd, previewExcludeEndDefault) + viper.SetDefault(SoundOnPreview, false) viper.SetDefault(Database, i.GetDefaultDatabaseFilePath()) diff --git a/pkg/manager/generator.go b/pkg/manager/generator.go index 63c2dfb7f..4deec7bf6 100644 --- a/pkg/manager/generator.go +++ b/pkg/manager/generator.go @@ -27,6 +27,8 @@ type GeneratorInfo struct { ExcludeEnd string VideoFile ffmpeg.VideoFile + + Audio bool // used for preview generation } func newGeneratorInfo(videoFile ffmpeg.VideoFile) (*GeneratorInfo, error) { diff --git a/pkg/manager/generator_preview.go b/pkg/manager/generator_preview.go index c723b9e69..899e91df9 100644 --- a/pkg/manager/generator_preview.go +++ b/pkg/manager/generator_preview.go @@ -113,6 +113,8 @@ func (g *PreviewGenerator) generateVideo(encoder *ffmpeg.Encoder, fallback bool) logger.Warnf("[generator] Segment duration (%f) too short.Using 0.75 instead.", g.Info.ChunkDuration) } + includeAudio := g.Info.Audio + for i := 0; i < g.Info.ChunkCount; i++ { time := offset + (float64(i) * stepSize) num := fmt.Sprintf("%.3d", i) @@ -124,6 +126,7 @@ func (g *PreviewGenerator) generateVideo(encoder *ffmpeg.Encoder, fallback bool) Duration: durationSegment, Width: 640, OutputPath: chunkOutputPath, + Audio: includeAudio, } if err := encoder.ScenePreviewVideoChunk(g.Info.VideoFile, options, g.PreviewPreset, fallback); err != nil { return err diff --git a/pkg/manager/task_generate_preview.go b/pkg/manager/task_generate_preview.go index 839896c2f..c5c666a6d 100644 --- a/pkg/manager/task_generate_preview.go +++ b/pkg/manager/task_generate_preview.go @@ -5,6 +5,7 @@ import ( "github.com/stashapp/stash/pkg/ffmpeg" "github.com/stashapp/stash/pkg/logger" + "github.com/stashapp/stash/pkg/manager/config" "github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/utils" ) @@ -50,6 +51,7 @@ func (t *GeneratePreviewTask) Start(wg *sizedwaitgroup.SizedWaitGroup) { generator.Info.ChunkDuration = *t.Options.PreviewSegmentDuration generator.Info.ExcludeStart = *t.Options.PreviewExcludeStart generator.Info.ExcludeEnd = *t.Options.PreviewExcludeEnd + generator.Info.Audio = config.GetInstance().GetPreviewAudio() if err := generator.Generate(); err != nil { logger.Errorf("error generating preview: %s", err.Error()) diff --git a/ui/v2.5/src/components/Changelog/versions/v080.md b/ui/v2.5/src/components/Changelog/versions/v080.md index df3f02543..f808e72f6 100644 --- a/ui/v2.5/src/components/Changelog/versions/v080.md +++ b/ui/v2.5/src/components/Changelog/versions/v080.md @@ -8,6 +8,7 @@ * Added [DLNA server](/settings?tab=dlna). ([#1364](https://github.com/stashapp/stash/pull/1364)) ### 🎨 Improvements +* Add option to disable audio for generated previews. ([#1454](https://github.com/stashapp/stash/pull/1454)) * Prompt when leaving scene edit page with unsaved changes. ([#1429](https://github.com/stashapp/stash/pull/1429)) * Make multi-set mode buttons more obvious in multi-edit dialog. ([#1435](https://github.com/stashapp/stash/pull/1435)) * Filter modifiers and sort by options are now sorted alphabetically. ([#1406](https://github.com/stashapp/stash/pull/1406)) diff --git a/ui/v2.5/src/components/Settings/SettingsConfigurationPanel.tsx b/ui/v2.5/src/components/Settings/SettingsConfigurationPanel.tsx index b11283ccb..b8f86364c 100644 --- a/ui/v2.5/src/components/Settings/SettingsConfigurationPanel.tsx +++ b/ui/v2.5/src/components/Settings/SettingsConfigurationPanel.tsx @@ -84,6 +84,7 @@ export const SettingsConfigurationPanel: React.FC = () => { GQL.HashAlgorithm | undefined >(undefined); const [parallelTasks, setParallelTasks] = useState(0); + const [previewAudio, setPreviewAudio] = useState(true); const [previewSegments, setPreviewSegments] = useState(0); const [previewSegmentDuration, setPreviewSegmentDuration] = useState( 0 @@ -149,6 +150,7 @@ export const SettingsConfigurationPanel: React.FC = () => { videoFileNamingAlgorithm: (videoFileNamingAlgorithm as GQL.HashAlgorithm) ?? undefined, parallelTasks, + previewAudio, previewSegments, previewSegmentDuration, previewExcludeStart, @@ -194,6 +196,7 @@ export const SettingsConfigurationPanel: React.FC = () => { setVideoFileNamingAlgorithm(conf.general.videoFileNamingAlgorithm); setCalculateMD5(conf.general.calculateMD5); setParallelTasks(conf.general.parallelTasks); + setPreviewAudio(conf.general.previewAudio); setPreviewSegments(conf.general.previewSegments); setPreviewSegmentDuration(conf.general.previewSegmentDuration); setPreviewExcludeStart(conf.general.previewExcludeStart); @@ -656,6 +659,19 @@ export const SettingsConfigurationPanel: React.FC = () => { not recommended. + + + setPreviewAudio(!previewAudio)} + /> + + Includes audio stream when generating previews. + + +
Number of segments in preview