stash/pkg/ffmpeg/transcoder/transcode.go

108 lines
2.7 KiB
Go

package transcoder
import "github.com/stashapp/stash/pkg/ffmpeg"
type TranscodeOptions struct {
OutputPath string
Format ffmpeg.Format
VideoCodec ffmpeg.VideoCodec
VideoArgs ffmpeg.Args
AudioCodec ffmpeg.AudioCodec
AudioArgs ffmpeg.Args
// if XError is true, then ffmpeg will fail on warnings
XError bool
StartTime float64
SlowSeek bool
Duration float64
// Verbosity is the logging verbosity. Defaults to LogLevelError if not set.
Verbosity ffmpeg.LogLevel
// arguments added before the input argument
ExtraInputArgs []string
// arguments added before the output argument
ExtraOutputArgs []string
}
func (o *TranscodeOptions) setDefaults() {
if o.Verbosity == "" {
o.Verbosity = ffmpeg.LogLevelError
}
}
func Transcode(input string, options TranscodeOptions) ffmpeg.Args {
options.setDefaults()
// TODO - this should probably be generalised and applied to all operations. Need to verify impact on phash algorithm.
const fallbackMinSlowSeek = 20.0
var fastSeek float64
var slowSeek float64
if !options.SlowSeek {
fastSeek = options.StartTime
slowSeek = 0
} else {
// In slowseek mode, try a combination of fast/slow seek instead of just fastseek
// Commonly with avi/wmv ffmpeg doesn't seem to always predict the right start point to begin decoding when
// using fast seek. If you force ffmpeg to decode more, it avoids the "blocky green artifact" issue.
if options.StartTime > fallbackMinSlowSeek {
// Handle seeks longer than fallbackMinSlowSeek with fast/slow seeks
// Allow for at least fallbackMinSlowSeek seconds of slow seek
fastSeek = options.StartTime - fallbackMinSlowSeek
slowSeek = fallbackMinSlowSeek
} else {
// Handle seeks shorter than fallbackMinSlowSeek with only slow seeks.
slowSeek = options.StartTime
fastSeek = 0
}
}
var args ffmpeg.Args
args = args.LogLevel(options.Verbosity).Overwrite()
args = append(args, options.ExtraInputArgs...)
if options.XError {
args = args.XError()
}
if fastSeek > 0 {
args = args.Seek(fastSeek)
}
args = args.Input(input)
if slowSeek > 0 {
args = args.Seek(slowSeek)
}
if options.Duration > 0 {
args = args.Duration(options.Duration)
}
// https://trac.ffmpeg.org/ticket/6375
args = args.MaxMuxingQueueSize(1024)
args = args.VideoCodec(options.VideoCodec)
args = args.AppendArgs(options.VideoArgs)
// if audio codec is not provided, then skip it
if options.AudioCodec == "" {
args = args.SkipAudio()
} else {
args = args.AudioCodec(options.AudioCodec)
}
args = args.AppendArgs(options.AudioArgs)
args = append(args, options.ExtraOutputArgs...)
args = args.Format(options.Format)
args = args.Output(options.OutputPath)
return args
}