Support FFmpeg drawtext param #487

This commit is contained in:
Alexey Khit
2023-07-03 00:45:51 +03:00
parent c29dd8c4e3
commit c34f9ae2b7
4 changed files with 65 additions and 21 deletions

View File

@@ -41,7 +41,8 @@ FROM base
# Install ffmpeg, tini (for signal handling),
# and other common tools for the echo source.
# alsa-plugins-pulse for ALSA support (+0MB)
RUN apk add --no-cache tini ffmpeg bash curl jq alsa-plugins-pulse
# font-droid for FFmpeg drawtext filter (+2MB)
RUN apk add --no-cache tini ffmpeg bash curl jq alsa-plugins-pulse font-droid
# Hardware Acceleration for Intel CPU (+50MB)
ARG TARGETARCH

View File

@@ -89,8 +89,8 @@ var defaults = map[string]string{
// hardware NVidia on Linux and Windows
// preset=p2 - faster, tune=ll - low latency
"h264/cuda": "-c:v h264_nvenc -g 50 -profile:v high -level:v auto -preset:v p2 -tune:v ll",
"h265/cuda": "-c:v hevc_nvenc -g 50 -profile:v high -level:v auto",
"h264/cuda": "-c:v h264_nvenc -g 50 -bf 0 -profile:v high -level:v auto -preset:v p2 -tune:v ll",
"h265/cuda": "-c:v hevc_nvenc -g 50 -bf 0 -profile:v high -level:v auto",
// hardware Intel on Windows
"h264/dxva2": "-c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1",
@@ -234,6 +234,18 @@ func parseArgs(s string) *ffmpeg.Args {
}
}
for _, drawtext := range query["drawtext"] {
// support templates https://github.com/AlexxIT/go2rtc/issues/487
drawtext = configTemplate(drawtext)
// support default timestamp format
if !strings.Contains(drawtext, "text=") {
drawtext += `:text='%{localtime\:%Y-%m-%d %X}'`
}
args.AddFilter("drawtext=" + drawtext)
}
// 3. Process video codecs
if args.Video > 0 {
for _, video := range query["video"] {

View File

@@ -55,33 +55,51 @@ func MakeHardware(args *ffmpeg.Args, engine string, defaults map[string]string)
switch engine {
case EngineVAAPI:
args.Input = "-hwaccel vaapi -hwaccel_output_format vaapi " + args.Input
args.Codecs[i] = defaults[name+"/"+engine]
for i, filter := range args.Filters {
if strings.HasPrefix(filter, "scale=") {
args.Filters[i] = "scale_vaapi=" + filter[6:]
}
if strings.HasPrefix(filter, "transpose=") {
if filter == "transpose=1,transpose=1" { // 180 degrees half-turn
args.Filters[i] = "transpose_vaapi=4" // reversal
} else {
args.Filters[i] = "transpose_vaapi=" + filter[10:]
if !args.HasFilters("drawtext=") {
args.Input = "-hwaccel vaapi -hwaccel_output_format vaapi " + args.Input
for i, filter := range args.Filters {
if strings.HasPrefix(filter, "scale=") {
args.Filters[i] = "scale_vaapi=" + filter[6:]
}
if strings.HasPrefix(filter, "transpose=") {
if filter == "transpose=1,transpose=1" { // 180 degrees half-turn
args.Filters[i] = "transpose_vaapi=4" // reversal
} else {
args.Filters[i] = "transpose_vaapi=" + filter[10:]
}
}
}
// fix if input doesn't support hwaccel, do nothing when support
// insert as first filter before hardware scale and transpose
args.InsertFilter("format=vaapi|nv12,hwupload")
} else {
// enable software pixel for drawtext, scale and transpose
args.Input = "-hwaccel vaapi -hwaccel_output_format nv12 " + args.Input
args.AddFilter("hwupload")
}
// fix if input doesn't support hwaccel, do nothing when support
args.InsertFilter("format=vaapi|nv12,hwupload")
case EngineCUDA:
args.Input = "-hwaccel cuda -hwaccel_output_format cuda -extra_hw_frames 2 " + args.Input
args.Codecs[i] = defaults[name+"/"+engine]
for i, filter := range args.Filters {
if strings.HasPrefix(filter, "scale=") {
args.Filters[i] = "scale_cuda=" + filter[6:]
// CUDA doesn't support hardware transpose
// https://github.com/AlexxIT/go2rtc/issues/389
if !args.HasFilters("drawtext=", "transpose=") {
args.Input = "-hwaccel cuda -hwaccel_output_format cuda " + args.Input
for i, filter := range args.Filters {
if strings.HasPrefix(filter, "scale=") {
args.Filters[i] = "scale_cuda=" + filter[6:]
}
}
} else {
args.Input = "-hwaccel cuda -hwaccel_output_format nv12 " + args.Input
args.AddFilter("hwupload")
}
case EngineDXVA2:

View File

@@ -29,6 +29,18 @@ func (a *Args) InsertFilter(filter string) {
a.Filters = append([]string{filter}, a.Filters...)
}
func (a *Args) HasFilters(filters ...string) bool {
for _, f1 := range a.Filters {
for _, f2 := range filters {
if strings.HasPrefix(f1, f2) {
return true
}
}
}
return false
}
func (a *Args) String() string {
b := bytes.NewBuffer(make([]byte, 0, 512))
@@ -65,12 +77,13 @@ func (a *Args) String() string {
if a.Filters != nil {
for i, filter := range a.Filters {
if i == 0 {
b.WriteString(" -vf ")
b.WriteString(` -vf "`)
} else {
b.WriteByte(',')
}
b.WriteString(filter)
}
b.WriteByte('"')
}
b.WriteByte(' ')