ffmpeg - 是否有针对不使用边框的 drawtext fontcolor alpha 的解决方法

mwj*_*wjb 4 ffmpeg

我想使用 drawtext 过滤器来呈现带有半透明白色文本和黑色边框的字符串。

但是,过滤器绘制字符的方式似乎存在已知限制,导致在启用边框时不遵守字体颜色 alpha。这记录在这里https://trac.ffmpeg.org/ticket/3571

我的问题是是否有办法以某种方式解决这个问题,也许使用 filter_complex 绘制没有边框的文本,然后使用覆盖过滤器以某种方式再次绘制带有边框的文本并将其覆盖在初始文本上以获取边框,从而实现相同的带有黑色边框的不透明白色文本。

当前命令:

ffmpeg \
-f lavfi \
-i "color=red:size=1920x1080" \
-vf "
drawtext=fontfile=/Library/Fonts/Arial.ttf:text=BORDER_OFF:fontcolor=white@0.3:fontsize=250:x=20:y=20,
drawtext=fontfile=/Library/Fonts/Arial.ttf:text=BORDER_ON:fontcolor=white@0.3:fontsize=250:x=20:y=20+(text_h+10):borderw=3:bordercolor=black@0.3" \
-frames:v 1 \
output.png
Run Code Online (Sandbox Code Playgroud)

完整输出:

ffmpeg -f lavfi -i "color=red:size=1920x1080" -vf "drawtext=fontfile=/Library/Fonts/Arial.ttf:fontcolor=white@0.3:fontsize=250:x=20:y=20:text=BORDER_OFF,drawtext=fontfile=/Library/Fonts/Arial.ttf:fontcolor=white@0.3:borderw=3:bordercolor=black@0.3:fontsize=250:x=20:y=20+(text_h+10):text=BORDER_ON" -frames:v 1 output.png
ffmpeg version N-94664-g0821bc4eee-tessus  https://evermeet.cx/ffmpeg/  Copyright (c) 2000-2019 the FFmpeg developers
  built with Apple LLVM version 10.0.1 (clang-1001.0.46.4)
  configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libmysofa --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvmaf --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-version3 --pkg-config-flags=--static --disable-ffplay
  libavutil      56. 33.100 / 56. 33.100
  libavcodec     58. 55.101 / 58. 55.101
  libavformat    58. 31.104 / 58. 31.104
  libavdevice    58.  9.100 / 58.  9.100
  libavfilter     7. 58.101 /  7. 58.101
  libswscale      5.  6.100 /  5.  6.100
  libswresample   3.  6.100 /  3.  6.100
  libpostproc    55.  6.100 / 55.  6.100
Input #0, lavfi, from 'color=red:size=1920x1080':
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 25 tbr, 25 tbn, 25 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> png (native))
Press [q] to stop, [?] for help
Output #0, image2, to 'output.png':
  Metadata:
    encoder         : Lavf58.31.104
    Stream #0:0: Video: png, rgb24, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc
    Metadata:
      encoder         : Lavc58.55.101 png
frame=    1 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.04 bitrate=N/A speed=0.283x    
video:85kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Run Code Online (Sandbox Code Playgroud)

输出显示文本的颜色正在被边框改变,即使字体颜色在 drawtext 过滤器的两个实例中相同。

drawtext 解决方案 (这已被下面答案中的第三个 @llogan 命令取代)

基于@llogan 第二个 drawtext 解决方案,此版本增加了使用 fontcolor 上的标准 alpha 控制填充不透明度的能力。使用@llogan 解决方案通过改变灰度值来控制边框的不透明度并修复文本上的锯齿状渲染:

ffmpeg \
-y \
-f lavfi \
-i color=s=1920x1080:c=white \
-f lavfi \
-i color=s=1920x1080:c=black \
-f lavfi \
-i smptebars=s=1920x1080 \
-filter_complex "\
[0]drawtext=fontfile=/Library/Fonts/Arial.ttf:text='BORDER':fontcolor=white:fontsize=200:x=(w-text_w)/2:y=(h-text_h)/2:borderw=3:bordercolor=#bfbfbf[ahpla];
[1]drawtext=fontfile=/Library/Fonts/Arial.ttf:text='BORDER':fontcolor=black:fontsize=200:x=(w-text_w)/2:y=(h-text_h)/2[txt];
[2]drawtext=fontfile=/Library/Fonts/Arial.ttf:text='BORDER':fontcolor=white@0.1:fontsize=200:x=(w-text_w)/2:y=(h-text_h)/2[bg];
[ahpla]negate[alpha];
[txt][alpha]alphamerge[fg];
[bg][fg]overlay" \
-frames:v 1 \
output.png
Run Code Online (Sandbox Code Playgroud)

llo*_*gan 5

绘图文本过滤器

在此处输入图片说明

解决方法可以包括alphamerge覆盖过滤器:

ffmpeg -y \
-f lavfi -i color=s=1920x1080 \
-f lavfi -i smptebars=s=1920x1080 \
-filter_complex \
  "[0]drawtext=fontfile=/Library/Fonts/Arial.ttf:text='BORDER':fontcolor=black:fontsize=200:x=(w-text_w)/2:y=(h-text_h)/2:borderw=3:bordercolor=#404040[border];
   [0][border]alphamerge[alpha];
   [1][alpha]overlay=format=rgb,drawtext=fontfile=/Library/Fonts/Arial.ttf:text='BORDER':fontcolor=white@0.1:fontsize=200:x=(w-text_w)/2:y=(h-text_h)/2" \
-frames:v 1 \
output.png
Run Code Online (Sandbox Code Playgroud)

更改bordercolor以控制边框不透明度。我的示例使用了任意值,因此您需要进行调整以满足您的需要。仅使用灰色。较深的阴影会使结果不太透明。如果您不喜欢十六进制值,请参阅有效颜色名称列表。

scale2ref过滤器(带),可以使用,如果你不想手动匹配的颜色源过滤器s的主输入的大小。

ffmpeg -y \
-f lavfi -i color \
-f lavfi -i smptebars=s=1920x1080 \
-filter_complex \
  "[0][1]scale2ref[color][mainbg];
   [color]split[colorbg0][colorbg1];
   [colorbg0]drawtext=fontfile=/Library/Fonts/Arial.ttf:text='BORDER':fontcolor=black:fontsize=200:x=(w-text_w)/2:y=(h-text_h)/2:borderw=3:bordercolor=#404040[border];
   [colorbg1][border]alphamerge[alpha];
   [mainbg][alpha]overlay=format=rgb,drawtext=fontfile=/Library/Fonts/Arial.ttf:text='BORDER':fontcolor=white@0.1:fontsize=200:x=(w-text_w)/2:y=(h-text_h)/2" \
-frames:v 1 \
output.png
Run Code Online (Sandbox Code Playgroud)

字幕过滤器

另一个解决方法是,如果您想要硬字幕,请使用带有 Advanced SubStation Alpha (ASS) 字幕的字幕过滤器:

ffmpeg -f lavfi -i smptebars=s=320x180,format=rgb24 -vf subtitles=subs.ass -frames:v 1 hardsubs.png
Run Code Online (Sandbox Code Playgroud)

如果你想要软字幕,或者多路复用 ASS 文件:

ffmpeg -i input -i subs.ass -map 0 -map 1 -c copy output.mkv
Run Code Online (Sandbox Code Playgroud)

示例 ASS 文件:

[Script Info]
; Script generated by Aegisub 3.2.2
; http://www.aegisub.org/
Title: Default Aegisub file
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: None

[Aegisub Project Garbage]
Last Style Storage: Default

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Bitstream Vera Sans,92,&HB4FFFFFF,&H000000FF,&H4B000000,&H00000000,0,0,0,0,100,100,0,0,1,4,0,5,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,BORDER ON
Run Code Online (Sandbox Code Playgroud)