mirror of https://github.com/stashapp/stash.git
Make audio stream optional for preview generation (#1454)
This commit is contained in:
parent
f843359ba3
commit
f1786ad871
|
@ -10,6 +10,7 @@ fragment ConfigGeneralData on ConfigGeneralResult {
|
|||
calculateMD5
|
||||
videoFileNamingAlgorithm
|
||||
parallelTasks
|
||||
previewAudio
|
||||
previewSegments
|
||||
previewSegmentDuration
|
||||
previewExcludeStart
|
||||
|
|
|
@ -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"""
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -84,6 +84,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||
GQL.HashAlgorithm | undefined
|
||||
>(undefined);
|
||||
const [parallelTasks, setParallelTasks] = useState<number>(0);
|
||||
const [previewAudio, setPreviewAudio] = useState<boolean>(true);
|
||||
const [previewSegments, setPreviewSegments] = useState<number>(0);
|
||||
const [previewSegmentDuration, setPreviewSegmentDuration] = useState<number>(
|
||||
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.
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<Form.Check
|
||||
id="preview-include-audio"
|
||||
checked={previewAudio}
|
||||
label="Include audio"
|
||||
onChange={() => setPreviewAudio(!previewAudio)}
|
||||
/>
|
||||
<Form.Text className="text-muted">
|
||||
Includes audio stream when generating previews.
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group id="preview-segments">
|
||||
<h6>Number of segments in preview</h6>
|
||||
<Form.Control
|
||||
|
|
Loading…
Reference in New Issue