Honor marker end times by default; skip zero-interval previews

Follow-up to the initial ceiling-configurable change, incorporating
product-review feedback. Two design shifts plus a read-side bug fix:

- Default MaxMarkerPreviewDuration flipped from 20 to 0 (ceiling
  disabled). User-set end times are now honored by default; the
  ceiling becomes an opt-in safety for imports or untrusted data.
  A buried setting at its old 20s default was unlikely to be found
  by users hitting the silent-truncation case.

- Non-positive intervals (endSeconds <= seconds) now skip preview
  generation entirely rather than falling back to the 20s default.
  A user who sets zero or negative duration either made a mistake
  (don't invent output) or marked a point without wanting a video
  (don't generate one they didn't ask for). Either way, skip with
  a warning log.

- Fix missing ConfigGeneralResult field wiring in
  resolver_query_configuration.go. The schema and mutation sides
  were wired in the initial commit but the query read path was
  missed, causing the Settings UI to display Go's zero-value (0)
  regardless of the stored config value.

Behavior change on upgrade: existing preview files remain unchanged.
To refresh previews for markers whose end times were previously
truncated at 20s, run Generate > Marker Previews with "Overwrite
Existing" enabled. To keep the old 20s ceiling, set Max marker
preview duration to 20 under Settings > System > Preview Generation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Speck Pratt 2026-04-22 08:03:37 -04:00
parent e9e427772b
commit ebca98b46f
4 changed files with 13 additions and 9 deletions

View file

@ -104,6 +104,7 @@ func makeConfigGeneralResult() *ConfigGeneralResult {
PreviewAudio: config.GetPreviewAudio(),
PreviewSegments: config.GetPreviewSegments(),
PreviewSegmentDuration: config.GetPreviewSegmentDuration(),
MaxMarkerPreviewDuration: config.GetMaxMarkerPreviewDuration(),
PreviewExcludeStart: config.GetPreviewExcludeStart(),
PreviewExcludeEnd: config.GetPreviewExcludeEnd(),
PreviewPreset: config.GetPreviewPreset(),

View file

@ -120,7 +120,7 @@ const (
previewExcludeEndDefault = "0"
MaxMarkerPreviewDuration = "max_marker_preview_duration"
maxMarkerPreviewDurationDefault = 20
maxMarkerPreviewDurationDefault = 0
WriteImageThumbnails = "write_image_thumbnails"
writeImageThumbnailsDefault = true

View file

@ -39,16 +39,19 @@ func (g Generator) MarkerPreviewVideo(ctx context.Context, input string, hash st
// Honor the marker's explicit interval when present and positive, capped
// by the configured safety ceiling. maxDuration <= 0 disables the ceiling.
// Non-positive intervals are treated as "no video wanted" and skipped —
// if the user intentionally set end = start they didn't want a preview,
// and if it's a data mistake we'd rather surface it than silently default.
if endSeconds != nil {
interval := *endSeconds - seconds
if interval > 0 {
if maxDuration <= 0 || interval <= float64(maxDuration) {
duration = interval
} else {
duration = float64(maxDuration)
}
if interval <= 0 {
logger.Warnf("[generator] marker at %.2fs has non-positive interval (end=%.2f); skipping video preview generation", seconds, *endSeconds)
return nil
}
if maxDuration <= 0 || interval <= float64(maxDuration) {
duration = interval
} else {
logger.Warnf("[generator] marker at %.2fs has non-positive interval (end=%.2f); falling back to %ds default", seconds, *endSeconds, markerPreviewDefaultDuration)
duration = float64(maxDuration)
}
}

View file

@ -418,7 +418,7 @@
"include_audio_desc": "Includes audio stream when generating previews.",
"include_audio_head": "Include audio",
"logging": "Logging",
"max_marker_preview_duration_desc": "Ceiling (in seconds) applied to generated marker preview videos when the marker has an explicit end time. Protects against unexpectedly long previews from imports or data entry mistakes. Set to 0 to disable the ceiling and honor the marker's end time verbatim.",
"max_marker_preview_duration_desc": "Optional ceiling (in seconds) for marker preview videos with explicit end times. Default is 0 (no ceiling, the marker's end time is honored verbatim). Set a positive value to cap preview duration as a safety against imports or data entry mistakes. Markers without an end time use a fixed 20-second default, unaffected by this setting.",
"max_marker_preview_duration_head": "Max marker preview duration",
"maximum_streaming_transcode_size_desc": "Maximum size for transcoded streams.",
"maximum_streaming_transcode_size_head": "Maximum streaming transcode size",