mirror of
https://github.com/photoprism/photoprism.git
synced 2026-07-17 16:49:04 +00:00
Video: Name the matched exclude entry and apply it to transcode #5617
Add Formats.Match to report which exclude-list entry matched, and use it in the remux, download, transcode, and index skip messages instead of always printing the codec (which could be empty or differ from the entry the user configured). Also apply the exclude list when building "videos transcode" plans so excluded files are skipped during dry runs and real runs, and report exclusion clearly when no preview image can be generated for an excluded video.
This commit is contained in:
parent
c691b8cbe0
commit
a57ca16bb3
9 changed files with 62 additions and 23 deletions
|
|
@ -261,8 +261,8 @@ func downloadAction(ctx *cli.Context) error {
|
|||
continue
|
||||
}
|
||||
|
||||
if ffmpeg.Exclude().Contains(result.Info.VCodec, result.Info.Ext, result.Info.Container) {
|
||||
log.Warnf("skipping %s because format %s is on the FFmpeg exclude list", clean.Log(u.String()), clean.Log(result.Info.VCodec))
|
||||
if matched := ffmpeg.Exclude().Match(result.Info.VCodec, result.Info.Ext, result.Info.Container); matched != "" {
|
||||
log.Warnf("skipping %s because format %s is on the FFmpeg exclude list", clean.Log(u.String()), clean.Log(matched))
|
||||
failures++
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,8 +165,8 @@ func runDownload(conf *config.Config, opts DownloadOpts, inputURLs []string) err
|
|||
continue
|
||||
}
|
||||
|
||||
if ffmpeg.Exclude().Contains(result.Info.VCodec, result.Info.Ext, result.Info.Container) {
|
||||
log.Warnf("skipping %s because format %s is on the FFmpeg exclude list", clean.Log(u.String()), clean.Log(result.Info.VCodec))
|
||||
if matched := ffmpeg.Exclude().Match(result.Info.VCodec, result.Info.Ext, result.Info.Container); matched != "" {
|
||||
log.Warnf("skipping %s because format %s is on the FFmpeg exclude list", clean.Log(u.String()), clean.Log(matched))
|
||||
failures++
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,8 +160,8 @@ func videoBuildRemuxPlans(conf *config.Config, results []search.Photo, force boo
|
|||
}
|
||||
}
|
||||
|
||||
if ffmpeg.Exclude().Contains(videoFile.FileCodec, fs.FileType(srcPath).String()) {
|
||||
log.Warnf("remux: skipping %s because format %s is on the FFmpeg exclude list", clean.Log(videoFile.FileName), clean.Log(videoFile.FileCodec))
|
||||
if matched := ffmpeg.Exclude().Match(videoFile.FileCodec, fs.FileType(srcPath).String()); matched != "" {
|
||||
log.Warnf("remux: skipping %s because format %s is on the FFmpeg exclude list", clean.Log(videoFile.FileName), clean.Log(matched))
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/photoprism/photoprism/internal/config"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/entity/search"
|
||||
"github.com/photoprism/photoprism/internal/ffmpeg"
|
||||
"github.com/photoprism/photoprism/internal/photoprism"
|
||||
"github.com/photoprism/photoprism/internal/photoprism/get"
|
||||
"github.com/photoprism/photoprism/pkg/clean"
|
||||
|
|
@ -154,6 +155,11 @@ func videoBuildTranscodePlans(conf *config.Config, results []search.Photo, force
|
|||
continue
|
||||
}
|
||||
|
||||
if matched := ffmpeg.Exclude().Match(videoFile.FileCodec, fs.FileType(srcPath).String()); matched != "" {
|
||||
log.Warnf("transcode: skipping %s because format %s is on the FFmpeg exclude list", clean.Log(videoFile.FileName), clean.Log(matched))
|
||||
continue
|
||||
}
|
||||
|
||||
if !conf.SidecarWritable() || !fs.PathWritable(conf.SidecarPath()) {
|
||||
return nil, nil, config.ErrReadOnly
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,6 +153,9 @@ func (w *Convert) JpegConvertCmds(f *MediaFile, jpegName string, xmpName string)
|
|||
|
||||
// No suitable converter found?
|
||||
if len(result) == 0 {
|
||||
if f.IsAnimated() && w.conf.FFmpegEnabled() && !w.FFmpegAllowed(f) {
|
||||
return result, useMutex, fmt.Errorf("format %s is on the FFmpeg exclude list", w.ffmpegExclude.Match(f.MetaData().Codec, f.VideoInfo().VideoCodec, f.FileType().String()))
|
||||
}
|
||||
return result, useMutex, fmt.Errorf("file type %s not supported", f.FileType())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ func (w *Convert) PngConvertCmds(f *MediaFile, pngName string) (result ConvertCm
|
|||
|
||||
// No suitable converter found?
|
||||
if len(result) == 0 {
|
||||
if f.IsAnimated() && w.conf.FFmpegEnabled() && !w.FFmpegAllowed(f) {
|
||||
return result, useMutex, fmt.Errorf("format %s is on the FFmpeg exclude list", w.ffmpegExclude.Match(f.MetaData().Codec, f.VideoInfo().VideoCodec, f.FileType().String()))
|
||||
}
|
||||
return result, useMutex, fmt.Errorf("file type %s not supported", f.FileType())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,10 +37,7 @@ func (w *Convert) ToAvc(f *MediaFile, encoder encode.Encoder, noMutex, force boo
|
|||
|
||||
// Skip files whose codec or container is on the FFmpeg exclude list.
|
||||
if !w.FFmpegAllowed(f) {
|
||||
format := clean.Log(f.MetaData().Codec)
|
||||
if format == "" {
|
||||
format = clean.Log(f.FileType().String())
|
||||
}
|
||||
format := clean.Log(w.ffmpegExclude.Match(f.MetaData().Codec, f.VideoInfo().VideoCodec, f.FileType().String()))
|
||||
log.Warnf("convert: skipping %s because format %s is on the FFmpeg exclude list", logFileName, format)
|
||||
return nil, fmt.Errorf("convert: format %s is excluded from FFmpeg processing", format)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,25 +24,34 @@ func NewFormats(formats ...string) Formats {
|
|||
return list
|
||||
}
|
||||
|
||||
// Match returns the first of the given format names that is in the list,
|
||||
// reported as its canonical codec alias, or "" if none match. Empty values are
|
||||
// skipped so callers can pass both a codec and a container even when only one
|
||||
// is known. Use it to name the matched entry when reporting why a file was
|
||||
// excluded.
|
||||
func (b Formats) Match(formats ...string) string {
|
||||
if len(b) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, format := range formats {
|
||||
if format = clean.Format(format); format == "" {
|
||||
continue
|
||||
} else if canonical := Canonical(format); b[canonical] {
|
||||
return canonical
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Contains reports whether any of the given format names is in the list.
|
||||
// Empty values are skipped so callers can pass both a codec and a container
|
||||
// even when only one is known. Names are matched by their canonical codec
|
||||
// alias, so the original name (e.g. "m8ra") and its mapped name (e.g. "magy")
|
||||
// are treated as equivalent.
|
||||
func (b Formats) Contains(formats ...string) bool {
|
||||
if len(b) == 0 || len(formats) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, format := range formats {
|
||||
if format = clean.Format(format); format == "" {
|
||||
continue
|
||||
} else if _, ok := b[Canonical(format)]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return b.Match(formats...) != ""
|
||||
}
|
||||
|
||||
// Allow reports whether the given format is NOT in the list.
|
||||
|
|
|
|||
|
|
@ -120,6 +120,27 @@ func TestFormats_Allow(t *testing.T) {
|
|||
assert.True(t, list.Allow(""))
|
||||
}
|
||||
|
||||
func TestFormats_Match(t *testing.T) {
|
||||
list := NewFormats("magy, mov")
|
||||
|
||||
t.Run("ReturnsCanonicalEntry", func(t *testing.T) {
|
||||
// The matched entry is reported, not the first argument.
|
||||
assert.Equal(t, "mov", list.Match("avc1", "mov"))
|
||||
assert.Equal(t, "magy", list.Match("m8ra", "avi"))
|
||||
})
|
||||
t.Run("SkipsEmptyArgs", func(t *testing.T) {
|
||||
assert.Equal(t, "magy", list.Match("", "magicyuv"))
|
||||
})
|
||||
t.Run("NoMatch", func(t *testing.T) {
|
||||
assert.Equal(t, "", list.Match("avc1", "mp4"))
|
||||
assert.Equal(t, "", list.Match())
|
||||
assert.Equal(t, "", list.Match(""))
|
||||
})
|
||||
t.Run("EmptyList", func(t *testing.T) {
|
||||
assert.Equal(t, "", NewFormats("").Match("magy"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormats_Set(t *testing.T) {
|
||||
t.Run("Empty", func(t *testing.T) {
|
||||
list := make(Formats)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue