Config: Downscale videos based on largest dimension (#3510)
* Adds resolution limit * Fixes 2 video filters and makes the env variable work * Adds FFMPEG_RESOLUTION to all the docker-compose files * Makes the resolution based on the longer side * Fixes failing test
This commit is contained in:
parent
2dc9e142ef
commit
19ac83dd20
10 changed files with 21 additions and 47 deletions
|
@ -109,7 +109,7 @@ services:
|
|||
# PHOTOPRISM_FFMPEG_ENCODER: "nvidia" # FFmpeg encoder ("software", "intel", "nvidia", "apple", "raspberry", "vaapi") Intel: "intel" for Broadwell or later and "vaapi" for Haswell or earlier
|
||||
# PHOTOPRISM_FFMPEG_ENCODER: "intel" # FFmpeg encoder ("software", "intel", "nvidia", "apple", "raspberry", "vaapi") Intel: "intel" for Broadwell or later and "vaapi" for Haswell or earlier`
|
||||
# PHOTOPRISM_FFMPEG_BITRATE: "32" # FFmpeg encoding bitrate limit in Mbit/s (default: 50)
|
||||
# PHOTOPRISM_FFMPEG_RESOLUTION: "1080" # FFmpeg encoding resolution limit in pixel height (default: 2160)
|
||||
# PHOTOPRISM_FFMPEG_RESOLUTION: "1920" # FFmpeg encoding resolution limit in pixel height (default: 4096)
|
||||
# LIBVA_DRIVER_NAME: "i965" # For Intel architectures Haswell and older which do not support QSV yet but use VAAPI instead
|
||||
## Share hardware devices with FFmpeg and TensorFlow (optional):
|
||||
# devices:
|
||||
|
|
|
@ -41,11 +41,9 @@ func (c *Config) FFmpegBitrate() int {
|
|||
func (c *Config) FFmpegResolution() int {
|
||||
switch {
|
||||
case c.options.FFmpegResolution <= 0:
|
||||
return 4320
|
||||
case c.options.FFmpegResolution <= 144:
|
||||
return 144
|
||||
case c.options.FFmpegResolution >= 4320:
|
||||
return 4320
|
||||
return 4096
|
||||
case c.options.FFmpegResolution >= 8192:
|
||||
return 8192
|
||||
default:
|
||||
return c.options.FFmpegResolution
|
||||
}
|
||||
|
@ -81,7 +79,7 @@ func (c *Config) FFmpegMapAudio() string {
|
|||
}
|
||||
|
||||
// FFmpegOptions returns the FFmpeg transcoding options.
|
||||
func (c *Config) FFmpegOptions(encoder ffmpeg.AvcEncoder, bitrate string, resolution string) (ffmpeg.Options, error) {
|
||||
func (c *Config) FFmpegOptions(encoder ffmpeg.AvcEncoder, bitrate string) (ffmpeg.Options, error) {
|
||||
// Transcode all other formats with FFmpeg.
|
||||
opt := ffmpeg.Options{
|
||||
Bin: c.FFmpegBin(),
|
||||
|
@ -89,7 +87,7 @@ func (c *Config) FFmpegOptions(encoder ffmpeg.AvcEncoder, bitrate string, resolu
|
|||
Bitrate: bitrate,
|
||||
MapVideo: c.FFmpegMapVideo(),
|
||||
MapAudio: c.FFmpegMapAudio(),
|
||||
Resolution: resolution,
|
||||
Resolution: fmt.Sprintf("%v", c.FFmpegResolution()),
|
||||
}
|
||||
|
||||
// Check
|
||||
|
|
|
@ -45,7 +45,7 @@ func TestConfig_FFmpegBitrate(t *testing.T) {
|
|||
|
||||
func TestConfig_FFmpegResolution(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
assert.Equal(t, 4320, c.FFmpegResolution())
|
||||
assert.Equal(t, 4096, c.FFmpegResolution())
|
||||
|
||||
c.options.FFmpegResolution = 1920
|
||||
assert.Equal(t, 1920, c.FFmpegResolution())
|
||||
|
@ -88,8 +88,7 @@ func TestConfig_FFmpegMapAudio(t *testing.T) {
|
|||
func TestConfig_FFmpegOptions(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
bitrate := "25M"
|
||||
resolution := "1080"
|
||||
opt, err := c.FFmpegOptions(ffmpeg.SoftwareEncoder, bitrate, resolution)
|
||||
opt, err := c.FFmpegOptions(ffmpeg.SoftwareEncoder, bitrate)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, c.FFmpegBin(), opt.Bin)
|
||||
assert.Equal(t, ffmpeg.SoftwareEncoder, opt.Encoder)
|
||||
|
@ -98,5 +97,4 @@ func TestConfig_FFmpegOptions(t *testing.T) {
|
|||
assert.Equal(t, ffmpeg.MapAudioDefault, opt.MapAudio)
|
||||
assert.Equal(t, c.FFmpegMapVideo(), opt.MapVideo)
|
||||
assert.Equal(t, c.FFmpegMapAudio(), opt.MapAudio)
|
||||
assert.Equal(t, resolution, opt.Resolution)
|
||||
}
|
||||
|
|
|
@ -583,7 +583,7 @@ var Flags = CliFlags{
|
|||
Flag: cli.IntFlag{
|
||||
Name: "ffmpeg-resolution",
|
||||
Usage: "maximum FFmpeg encoding `RESOLUTION` (height)",
|
||||
Value: 2160,
|
||||
Value: 4096,
|
||||
EnvVar: EnvVar("FFMPEG_RESOLUTION"),
|
||||
}}, {
|
||||
Flag: cli.StringFlag{
|
||||
|
|
|
@ -14,7 +14,7 @@ func AvcConvertCommand(fileName, avcName string, opt Options) (result *exec.Cmd,
|
|||
} else if avcName == "" {
|
||||
return nil, false, fmt.Errorf("empty output filename")
|
||||
}
|
||||
|
||||
scale := "scale='if(gte(iw,ih), min(" + opt.Resolution + ", iw), -2):if(gte(iw,ih), -2, min(" + opt.Resolution + ", ih))'"
|
||||
// Don't transcode more than one video at the same time.
|
||||
useMutex = true
|
||||
|
||||
|
@ -25,7 +25,6 @@ func AvcConvertCommand(fileName, avcName string, opt Options) (result *exec.Cmd,
|
|||
"-i", fileName,
|
||||
"-movflags", "faststart",
|
||||
"-pix_fmt", "yuv420p",
|
||||
// "-vf", "scale='-2:trunc("+opt.Resolution+"/2)*2'",
|
||||
"-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2",
|
||||
"-f", "mp4",
|
||||
"-y",
|
||||
|
@ -49,7 +48,7 @@ func AvcConvertCommand(fileName, avcName string, opt Options) (result *exec.Cmd,
|
|||
"-qsv_device", "/dev/dri/renderD128",
|
||||
"-i", fileName,
|
||||
"-c:a", "aac",
|
||||
"-vf", "\"scale='-2:"+opt.Resolution+"',"+format+"\"",
|
||||
"-vf", scale+", "+format+"",
|
||||
"-c:v", opt.Encoder.String(),
|
||||
"-map", opt.MapVideo,
|
||||
"-map", opt.MapAudio,
|
||||
|
@ -72,7 +71,7 @@ func AvcConvertCommand(fileName, avcName string, opt Options) (result *exec.Cmd,
|
|||
"-map", opt.MapVideo,
|
||||
"-map", opt.MapAudio,
|
||||
"-c:a", "aac",
|
||||
"-vf", "\"scale='-2:"+opt.Resolution+"',"+format+"\"",
|
||||
"-vf", scale+", "+format+"",
|
||||
"-profile", "high",
|
||||
"-level", "51",
|
||||
"-vsync", "vfr",
|
||||
|
@ -90,7 +89,7 @@ func AvcConvertCommand(fileName, avcName string, opt Options) (result *exec.Cmd,
|
|||
"-hwaccel", "vaapi",
|
||||
"-i", fileName,
|
||||
"-c:a", "aac",
|
||||
"-vf", "\"scale='-2:"+opt.Resolution+"',"+format+"\"",
|
||||
"-vf", scale+", "+format+"",
|
||||
"-c:v", opt.Encoder.String(),
|
||||
"-map", opt.MapVideo,
|
||||
"-map", opt.MapAudio,
|
||||
|
@ -117,7 +116,7 @@ func AvcConvertCommand(fileName, avcName string, opt Options) (result *exec.Cmd,
|
|||
"-preset", "15",
|
||||
"-pixel_format", "yuv420p",
|
||||
"-gpu", "any",
|
||||
"-vf", "\"scale='-2:"+opt.Resolution+"',"+format+"\"",
|
||||
"-vf", scale+", "+format+"",
|
||||
"-rc:v", "constqp",
|
||||
"-cq", "0",
|
||||
"-tune", "2",
|
||||
|
@ -141,7 +140,7 @@ func AvcConvertCommand(fileName, avcName string, opt Options) (result *exec.Cmd,
|
|||
"-map", opt.MapVideo,
|
||||
"-map", opt.MapAudio,
|
||||
"-c:a", "aac",
|
||||
"-vf", "\"scale='-2:"+opt.Resolution+"',"+format+"\"",
|
||||
"-vf", scale+", "+format+"",
|
||||
"-num_output_buffers", "72",
|
||||
"-num_capture_buffers", "64",
|
||||
"-max_muxing_queue_size", "1024",
|
||||
|
@ -163,7 +162,7 @@ func AvcConvertCommand(fileName, avcName string, opt Options) (result *exec.Cmd,
|
|||
"-map", opt.MapVideo,
|
||||
"-map", opt.MapAudio,
|
||||
"-c:a", "aac",
|
||||
"-vf", "\"scale='-2:"+opt.Resolution+"',"+format+"\"",
|
||||
"-vf", scale+", "+format+"",
|
||||
"-max_muxing_queue_size", "1024",
|
||||
"-crf", "23",
|
||||
"-vsync", "vfr",
|
||||
|
|
|
@ -149,8 +149,7 @@ func (c *Convert) AvcConvertCommand(f *MediaFile, avcName string, encoder ffmpeg
|
|||
|
||||
// Transcode all other formats with FFmpeg.
|
||||
var opt ffmpeg.Options
|
||||
|
||||
if opt, err = c.conf.FFmpegOptions(encoder, c.AvcBitrate(f), c.AvcResolution(f)); err != nil {
|
||||
if opt, err = c.conf.FFmpegOptions(encoder, c.AvcBitrate(f)); err != nil {
|
||||
return nil, false, fmt.Errorf("convert: failed to transcode %s (%s)", clean.Log(f.BaseName()), err)
|
||||
} else {
|
||||
return ffmpeg.AvcConvertCommand(fileName, avcName, opt)
|
||||
|
@ -178,24 +177,3 @@ func (c *Convert) AvcBitrate(f *MediaFile) string {
|
|||
|
||||
return fmt.Sprintf("%dM", bitrate)
|
||||
}
|
||||
|
||||
// AvcResolution returns the resolution to use for transcoding.
|
||||
func (c *Convert) AvcResolution(f *MediaFile) string {
|
||||
const defaultResolution = "2160"
|
||||
|
||||
if f == nil {
|
||||
return defaultResolution
|
||||
}
|
||||
|
||||
limit := c.conf.FFmpegResolution()
|
||||
|
||||
resolution := f.height
|
||||
|
||||
if resolution <= 144 {
|
||||
return defaultResolution
|
||||
} else if resolution > limit {
|
||||
resolution = limit
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%d", resolution)
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ services:
|
|||
## Hardware Video Transcoding:
|
||||
# PHOTOPRISM_FFMPEG_ENCODER: "raspberry" # FFmpeg encoder ("software", "intel", "nvidia", "apple", "raspberry")
|
||||
# PHOTOPRISM_FFMPEG_BITRATE: "32" # FFmpeg encoding bitrate limit in Mbit/s (default: 50)
|
||||
# PHOTOPRISM_FFMPEG_RESOLUTION: "1080" # FFmpeg encoding resolution limit in pixel height (default: 2160)
|
||||
# PHOTOPRISM_FFMPEG_RESOLUTION: "1920" # FFmpeg encoding resolution limit in pixel height (default: 4096)
|
||||
## Run as a non-root user after initialization (supported: 0, 33, 50-99, 500-600, and 900-1200):
|
||||
# PHOTOPRISM_UID: 1000
|
||||
# PHOTOPRISM_GID: 1000
|
||||
|
|
|
@ -78,7 +78,7 @@ services:
|
|||
## Hardware Video Transcoding:
|
||||
# PHOTOPRISM_FFMPEG_ENCODER: "software" # FFmpeg encoder ("software", "intel", "nvidia", "apple", "raspberry")
|
||||
# PHOTOPRISM_FFMPEG_BITRATE: "32" # FFmpeg encoding bitrate limit in Mbit/s (default: 50)
|
||||
# PHOTOPRISM_FFMPEG_RESOLUTION: "1080" # FFmpeg encoding resolution limit in pixel height (default: 2160)
|
||||
# PHOTOPRISM_FFMPEG_RESOLUTION: "1920" # FFmpeg encoding resolution limit in pixel height (default: 4096)
|
||||
## Run as a non-root user after initialization (supported: 0, 33, 50-99, 500-600, and 900-1200):
|
||||
# PHOTOPRISM_UID: 1000
|
||||
# PHOTOPRISM_GID: 1000
|
||||
|
|
|
@ -83,7 +83,7 @@ services:
|
|||
## see https://docs.photoprism.app/getting-started/advanced/transcoding/#nvidia-container-toolkit
|
||||
PHOTOPRISM_FFMPEG_ENCODER: "nvidia"
|
||||
PHOTOPRISM_FFMPEG_BITRATE: "50"
|
||||
PHOTOPRISM_FFMPEG_RESOLUTION: "2160"
|
||||
PHOTOPRISM_FFMPEG_RESOLUTION: "4096"
|
||||
NVIDIA_VISIBLE_DEVICES: "all"
|
||||
NVIDIA_DRIVER_CAPABILITIES: "compute,video,utility"
|
||||
## Run as a non-root user after initialization (supported: 0, 33, 50-99, 500-600, and 900-1200):
|
||||
|
|
|
@ -82,6 +82,7 @@ services:
|
|||
## Hardware Video Transcoding:
|
||||
# PHOTOPRISM_FFMPEG_ENCODER: "software" # FFmpeg encoder ("software", "intel", "nvidia", "apple", "raspberry")
|
||||
# PHOTOPRISM_FFMPEG_BITRATE: "32" # FFmpeg encoding bitrate limit in Mbit/s (default: 50)
|
||||
# PHOTOPRISM_FFMPEG_RESOLUTION: "1920" # FFmpeg encoding resolution limit in pixel (default: 4096)
|
||||
## Run as a non-root user after initialization (supported: 0, 33, 50-99, 500-600, and 900-1200):
|
||||
# PHOTOPRISM_UID: 1000
|
||||
# PHOTOPRISM_GID: 1000
|
||||
|
|
Loading…
Reference in a new issue