网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
官方文档
https://ffmpeg.org/ffmpeg-filters.html#drawtext-1
参考strftime() 方法相关参数;https://www.runoob.com/python/att-time-strftime.html
drawtext过滤器
本质是:使用libfreetype库从视频顶部的指定文件中绘制文本字符串或文本。
使用前提:要启用此过滤器的那么在编译ffmpeg的时候需要使用——enable-libfreetype配置FFmpeg。
如果要启用默认字体回退和字体选项,那您需要使用——enable-libfontconfig配置FFmpeg。
如果要启用text_shaping选项,需要使用——enable-libfribidi配置FFmpeg。
参数
box
用背景色在文本周围画一个方框。取值为1(启用)或0(禁用)。box的默认值为0。
boxborderw
使用框色设置框周围边框的宽度。boxborderw的默认值是0。
boxcolor
用于在文本周围绘制框的颜色。boxcolor默认值为“white”。
line_spacing
使用“方框”设置要在方框周围绘制的边框的像素线间距。line_spacing的默认值是0。
borderw
使用边框颜色设置要围绕文本绘制的边框的宽度。borderw的默认值为0。
bordercolor
设置用于在文本周围绘制边框的颜色。bordercolor的默认值为“black”。
expansion
选择文本的展开方式。可以是none、strftime(已弃用)或normal(默认)。详细信息请参阅下面的文本扩展部分。
basetime
设置计数的开始时间。取值单位为微秒。仅适用于已弃用的strftime扩展模式。要在普通扩展模式下进行模拟,使用pts函数,提供开始时间(以秒为单位)作为第二个参数。
fix_bounds
如果为真,检查并修复文本协调以避免剪切。
fontcolor
用于绘制字体的颜色。fontcolor 的默认值为“black”。
fontcolor_expr
字符串,以与文本相同的方式展开,以获得动态fontcolor值。默认情况下,该选项的值为空,不进行处理。当设置此选项时,它将覆盖fontcolor选项。
font
用于绘制文本的字体系列。在默认情况下没有。如STSONG.TTF字体类型,可以从 C:\Windows\Fonts 拷贝一个有效的字体文件
fontfile
用于绘制文本的字体文件。必须包括路径。当fontconfig支持被禁用时,此参数为必选参数。
alpha
绘制文本应用alpha混合。这个值可以是一个介于0.0和1.0之间的数字。表达式也接受相同的变量x, y。默认值为1。请参阅fontcolor_expr。
fontsize
用于绘制文本的字体大小。fontsize 默认值为16。
text_shaping
如果设置为1,则在绘制文本之前尝试对其进行整形(例如,颠倒文本从右到左的顺序并连接阿拉伯字符)。否则,就完全按照给定的方式绘制文本。默认为1(如果支持)。
ft_load_flags
用于加载字体的标志。flags映射了libfreetype支持的相应标志,并且是以下值的组合:默认值为“Default”。
default
no_scale
no_hinting
render
no_bitmap
vertical_layout
force_autohint
crop_bitmap
pedantic
ignore_global_advance_width
no_recurse
ignore_transform
monochrome
linear_design
no_autohint
shadowcolor
用于在绘制的文本后面绘制阴影的颜色。对于此选项的语法,请检查(ffmpeg-utils)ffmpeg-utils手册中的“颜色”部分。shadowcolor的默认值是“black”。
shadowx、shadowy
文本阴影位置相对于文本位置的x和y偏移量。它们可以是正的,也可以是负的。两者的默认值都是“0”。
start_number
n/frame_num变量的起始帧号。默认值为“0”。
tabsize
用于呈现选项卡的空格数的大小。默认值为4。
timecode
设置初始时间码表示格式为“hh:mm:ss[:;”。ff”格式。它可以带或不带文本参数使用。timeecode_rate选项必须指定。
timecode_rate, rate, r
设置时间码帧速率(仅限时间码)。值将四舍五入为最接近的整数。最小值为1。支持帧速率为30和60的拖帧时间码。
tc24hmax
如果设置为1,时间码选项的输出将环绕24小时。默认为0(禁用)。
text
要绘制的文本字符串。文本必须是UTF-8编码字符序列。如果没有指定textfile参数,则此参数为必选项。
textfile
包含要绘制的文本的文本文件。文本必须是UTF-8编码字符序列。如果没有指定文本字符串,则此参数为必选参数。如果同时指定了text和textfile,则抛出错误。
text_source
如果要在侧数据的检测框中使用文本数据,则文本源应该设置为side_data_detection_bboxes。
如果设置了text source, text和textfile将被忽略,在侧数据的检测框中仍然使用文本数据。因此,如果您不确定文本源,请不要使用此参数。
reload
如果设置为1,文本文件将在每一帧之前重新加载。一定要原子地更新它,否则它可能被部分读取,甚至失败。
x、y
指定在视频帧内绘制文本的偏移量的表达式。它们相对于输出图像的上/左边界。x和y的默认值为“0”。
文本扩展
如果将expansion设置为strftime,则过滤器将识别提供文本中的strftime()序列,并相应地展开它们。就是%s,%y这些格式。
如果expand设置为none,则会逐字打印文本。
如果“expansion”设置为“normal”(默认),则使用如下扩展机制。
反斜杠字符’ \ ‘后面跟着任何字符,总是扩展到第二个字符。
形式为%{…}是扩大。大括号之间的文本是一个函数名,后面可能跟以’:‘分隔的参数。如果参数包含特殊字符或分隔符(’:‘或’}’),则应转义。
注意,它们可能还必须转义为filter参数字符串中的text选项的值和filter图描述中的filter参数,也可能是shell的转义,这构成了四层转义;使用文本文件可以避免这些问题。
系统提供以下功能:
expr, e 表达式的计算结果。
它必须接受一个参数来指定要计算的表达式,该参数接受与x和y值相同的常量和函数。注意,不是所有的常量都应该被使用,例如,当计算表达式时,文本大小是未知的,所以常量text_w和text_h将有一个未定义的值。
expr_int_format, eif计算表达式的值并将其输出为格式化的整数。
它必须接受一个参数来指定要计算的表达式,该参数接受与x和y值相同的常量和函数。注意,不是所有的常量都应该被使用,例如,当计算表达式时,文本大小是未知的,所以常量text_w和text_h将有一个未定义的值。第一个参数是要计算的表达式,就像expr函数一样。第二个参数指定输出格式。允许的值是’ x ', ’ x ', ’ d ‘和’ u '。它们与printf函数中的处理方法完全相同。第三个参数是可选的,用于设置输出的位置数。它可以用来添加从左侧为零的填充。
gmtime
过滤器运行的时间,以UTC表示。它可以接受一个参数:strftime()格式字符串。
本地时间
过滤器运行的时间,以当地时区表示。它可以接受一个参数:strftime()格式字符串。
pts
当前帧的时间戳。它最多可以有三个参数。
第一个参数是时间戳的格式;它默认使用FLT表示秒,作为微秒精度的十进制数;hms表示格式化的[-]HH:MM:SS。毫秒精度的MMM时间戳。gmtime表示UTC时间格式的帧的时间戳;Localtime表示格式化为本地时区时间的帧的时间戳。
第二个参数是添加到时间戳的偏移量。
如果格式设置为hms,则可以提供第三个参数24HH,以24h格式(00-23)表示格式化时间戳的小时部分。
如果格式设置为localtime或gmtime,则可以提供第三个参数:strftime()格式字符串。默认使用YYYY-MM-DD HH:MM:SS格式。
测试案例
drawtext=“fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text=‘Test Text’:
x=100: y=50: fontsize=24: fontcolor=yellow@0.2: box=1: boxcolor=red@0.2”
在x=100和y=50的位置(从屏幕的左上角开始计算),用字体FreeSerif绘制大小为24的“测试文本”,文本是黄色的,周围有一个红色框。文本和框的不透明度均为20%。
ffmpeg -t 5 -i recodeFile.mp4 -vf drawtext="fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Test Text':\x=100: y=50: fontsize=60: fontcolor=yellow@0.2: box=1: boxcolor=red@0.2" -c:v libx264 -an -f mp4 output.mp4 -y
相关命令实现;
参考;https://blog.csdn.net/ternence_hsu/article/details/102540626
ffmpeg -t 5 -i recodeFile.mp4 -vf "drawtext=fontsize=60:text='%{localtime\:%Y-%M-%d %H.%m.%S}'" -c:v libx264 -an -f mp4 output.mp4 -y
ffmpeg -t 5 -i recodeFile.mp4 -vf "drawtext=fontfile=STSONG.TTF:fontcolor=red:fontsize=100:x=0:y=0:text='%{localtime\:%Y-%M-%d %H.%m.%S}'" -c:v libx264 -an -f mp4 output.mp4 -y
还可以增加属性
fontfile=STSONG.TTF字体类型,可以从 C:\Windows\Fonts 拷贝一个有效的字体文件放到当前目录。
fontcolor=red颜色
fontsize=100大小
x=0:y=0坐标
text='%{localtime\:%Y-%M-%d %H.%m.%S}'具体的值
API实现
参考;https://blog.csdn.net/dancing_night/article/details/80536510
int InitAvFilter(AVFilterGraph *&filter_graph, AVFilterContext * &bufferSrc_ctx, AVFilterContext* &bufferSink_ctx, const char *args)
{
int ret = 0;
avfilter_register_all();
filter_graph = avfilter_graph_alloc();
if (!filter_graph)
{
cout << "create filter graph Fial" << endl;
return -1;
}
//创建一个buffer源过滤器并创建对应的过滤器实列并加入过滤器图中,之后就需要将图里面的不同过滤器链接到一起即可
AVFilter* bufferSrc = avfilter_get_by_name("buffer");
ret = avfilter_graph_create_filter(&bufferSrc_ctx, bufferSrc ,"in", args, NULL, filter_graph);
if (ret < 0) {
printf("Fail to create filter\n");
return -1;
}
//创建buffersink目的过滤器
//bufferSink需要设置参数 允许的像素格式列表,以AV_PIX_FMT_NONE结束
AVBufferSinkParams *bufferSink_params = NULL;
enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };
bufferSink_params = av_buffersink_params_alloc();
bufferSink_params->pixel_fmts = pix_fmts;
AVFilter* bufferSink = avfilter_get_by_name("buffersink"); //ffbuffersink带缓冲的buffersink
ret = avfilter_graph_create_filter(&bufferSink_ctx, bufferSink, "out", NULL, bufferSink_params, filter_graph);
if (ret < 0) {
printf("Fail to create filter sink filter\n");
return -1;
}
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
outputs->name = av_strdup("in");
outputs->filter_ctx = bufferSrc_ctx;
outputs->pad_idx = 0;
outputs->next = NULL;
inputs->name = av_strdup("out");
inputs->filter_ctx = bufferSink_ctx;
inputs->pad_idx = 0;
inputs->next = NULL;
time_t now = time(0);
string strTime = "";
char ch[100] = { 0 };
tm *ltm = localtime(&now);
// 输出 tm 结构的各个组成部分
itoa(ltm->tm_sec, ch, 10);
strTime = ch;
string m_filters_descr = "drawtext=fontfile=STSONG.TTF:fontcolor=red:fontsize=50:x=0:y=0:text=";
m_filters_descr += "\'%{localtime\\:%Y-%m-%d %H.%M.%S}\'";
//string m_filters_descr = "settb=AVTB,setpts='trunc(PTS/1K)*1K+st(1,trunc(RTCTIME/1K))-1K*trunc(ld(1)/1K)',drawtext=fontsize=100:fontcolor=white:text='%{localtime}.%{eif\:1M*t-1K*trunc(t*1K)\:d}'";
if ((ret = avfilter_graph_parse_ptr(filter_graph, m_filters_descr.c_str(),
&inputs, &outputs, NULL)) < 0)
return -1;
![img](https://img-blog.csdnimg.cn/img_convert/09295bd18583c688229ca4a20e42f44e.png)
![img](https://img-blog.csdnimg.cn/img_convert/186885d14ac3e636ae1ea9754d0669cf.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
mg-ZSOk2nzs-1715745372239)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**