0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于FFMPEG水印添加---avfilter库

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-09-29 15:42 次阅读

基于FFMPEG水印添加---avfilter库

 avfilter,是ffmpeg为图像和语音处理提供的滤镜子框架,代码位于libavfilter目录。

  libavfilter提供了一个通用框架来实现audio和video的原始数据filter处理,如对视频添加叠加Logo图片或者时间文字等信息、对视频进行裁剪和翻转。

1.硬件平台

操作系统:Ubuntu18.04
ffmpeg版本:ffmpeg4.2.5

2.FFMPEG编译

  在使用avfilter库添加汉字水印时,ffmepg默认模式时不支持矢量字库的,要实现汉字水印添加就需要进行configure配置。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf6Zi_5rC0,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center

2.1 freetype库编译

   freetype下载地址:https://download.savannah.gnu.org/releases/freetype/

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf6Zi_5rC0,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center

2.2 FriBidi库编译

   FriBidi下载地址:https://www.linuxfromscratch.org/blfs/view/svn/general/fribidi.html

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf6Zi_5rC0,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center
#解压源码
tar xvf /mnt/hgfs/ubuntu/software_pack/fribidi-1.0.11.tar.xz
#配置生成Makefile
./configure --prefix=$PWD/_install
#编译安装
make && make install 
#编译安装
#将生成的文件拷贝到/usr/lib目录下
cp ./_install/lib/pkgconfig/ /usr/lib -rf

2.3 ffmpeg库编译

#解压源码
tar xvf /mnt/hgfs/ubuntu/software_pack/ffmpeg-4.2.5.tar.bz2 
#配置生成Makefile
./configure --enable-static
 --enable-shared --prefix=$PWD/_install
 --extra-cflags=-I/home/wbyq/src_pack/x264-master/_install/include
 --extra-ldflags=-L/home/wbyq/src_pack/x264-master/_install/lib
 --extra-cflags=-I/home/wbyq/src_pack/freetype-2.10.0/_install/include
 --extra-ldflags=-L/home/wbyq/src_pack/freetype-2.10.0/_install/lib
 --extra-cflags=-I/home/wbyq/src_pack/fribidi-1.0.11/_install/include
 --extra-ldflags=-L/home/wbyq/src_pack/fribidi-1.0.11/_install/lib
 --enable-ffmpeg --enable-libx264 --enable-gpl --enable-libfreetype --enable-libfontconfig --enable-libfribidi --enable-avfilter
#编译安装
make && make install 
#将生成的文件拷贝到/usr/lib目录下
cp ./_install/lib/pkgconfig/ /usr/lib -rf

2.4 ffmpeg命令行添加时间水印

2.4.1 以实时时间动态添加时间水印

ffmpeg -i 最后一滴水.mp4 -vf drawtext=“fontfile=msyhbd.ttc:x=100:y=10:fontcolor=white:fontsize=30:expansion=strftime:basetime=$(date +%s )000000:text=‘%Y-%m-%d %H:%M: %S’” output.mp4
drawtext 字符串水印
fontfile=msyhbd.ttc矢量字库,可在windows下C:WindowsFonts拷贝到当期目录下
x=100:y=10显示位置,距离左上脚
fontcolor=white:fontsize=30字体颜色和大小
expansion=strftime:basetime=$(date +%s )000000以当前实时时间添加动态水印
text=‘%Y-%m-%d %H:%M: %S’ 时间显示格式
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf6Zi_5rC0,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center

2.4.1 以指定时间动态添加时间水印

ffmpeg -i 最后一滴水.mp4 -vf drawtext="fontfile=msyhbd.ttc:x=100:y=10:fontcolor=white:fontsize=30:expansion=strftime:basetime=$(date +%s -d '2020-8-8 14:10:50')000000:text='%Y-%m-%d  %H:%M: %S'  IT_阿水" output.mp4
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf6Zi_5rC0,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center

3.代码实现水印添加

  参考雷霄骅博客处理示例:https://blog.csdn.net/leixiaohua1020/article/details/50618190
  致敬雷神!致敬雷神!致敬雷神!

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define FILE_SRC "sintel_480x272_yuv420p.yuv" //源文件
int waterMark(AVFrame *frame_in,AVFrame *frame_out,int w,int h,const char *str);
int main(int argc,char *argv[])
{
	int ret;
	/*打开输入yuv文件*/
	FILE *fp_in=fopen(FILE_SRC,"rb+");
	if(fp_in==NULL)
	{
		printf("文件打开失败n");
		return 0;
	}
	int in_width=480;
	int in_height=272;
	/*处理后的文件*/
	FILE *fp_out=fopen("new.yuv","wb+");
	if(fp_out==NULL)
	{
		printf("文件创建失败n");
		return 0;
	}
	char buff[50];

	AVFrame *frame_in=av_frame_alloc();
	unsigned char *frame_buffer_in;
	frame_buffer_in=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P,in_width,in_height,4));
	/*根据图像设置图像指针和内存对齐方式*/
	av_image_fill_arrays(frame_in->data,frame_in->linesize,frame_buffer_in,AV_PIX_FMT_YUV420P,in_width,in_height,4);

	AVFrame *frame_out=av_frame_alloc();
	unsigned char *frame_buffer_out;
	frame_buffer_out=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P,in_width,in_height,4));
	av_image_fill_arrays(frame_out->data,frame_out->linesize,frame_buffer_out,AV_PIX_FMT_YUV420P,in_width,in_height,4);
	
	frame_in->width=in_width;
	frame_in->height=in_height;
	frame_in->format=AV_PIX_FMT_YUV420P;
	char sys_time[64];
	time_t sec,sec2;
	while(1)
	{

		if(fread(frame_buffer_in,1,in_width*in_height*3/2,fp_in)!=in_width*in_height*3/2)
		{
			break;
		}
		frame_in->data[0]=frame_buffer_in;
		frame_in->data[1]=frame_buffer_in+in_width*in_height;
		frame_in->data[2]=frame_buffer_in+in_width*in_height*5/4;
		
		sec=time(NULL);
		if(sec!=sec2)
		{
			sec2=sec;
			struct tm* today = localtime(&sec2);	
			strftime(sys_time, sizeof(sys_time), "%Y/%m/%d %H:%M:%S", today);    
		}
		
		waterMark(frame_in,frame_out,in_width,in_height,sys_time);//添加水印
	
		/*添加水印后的数据写入到过滤器*/
		if(frame_out->format==AV_PIX_FMT_YUV420P)
		{
			for(int i=0;iheight;i++)
			{
				fwrite(frame_out->data[0]+frame_out->linesize[0]*i,1,frame_out->width,fp_out);
			}
			for(int i=0;iheight/2;i++)
			{
				fwrite(frame_out->data[1]+frame_out->linesize[1]*i,1,frame_out->width/2,fp_out);
			}
			for(int i=0;iheight/2;i++)
			{
				fwrite(frame_out->data[2]+frame_out->linesize[2]*i,1,frame_out->width/2,fp_out);
			}
			printf("一帧数据处理完成n");
		}
		av_frame_unref(frame_out);
	}
	fclose(fp_in);
	fclose(fp_out);
	av_frame_free(&frame_in);
	av_frame_free(&frame_out);
    return 0;	
	
}
int waterMark(AVFrame *frame_in,AVFrame *frame_out,int w,int h,const char *str)
{
	int ret;
	/*根据名字获取ffmegding定义的filter*/
	const AVFilter *buffersrc=avfilter_get_by_name("buffer");//原始数据
	const AVFilter *buffersink=avfilter_get_by_name("buffersink");//处理后的数据
	/*动态分配AVFilterInOut空间*/
	AVFilterInOut *outputs=avfilter_inout_alloc();
	AVFilterInOut *inputs=avfilter_inout_alloc();	
	/*创建AVFilterGraph,分配空间*/
	AVFilterGraph *filter_graph;//对filters系统的整体管理结构体
	filter_graph = avfilter_graph_alloc();
	enum AVPixelFormat pix_fmts[]={AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE};//设置格式
	/*过滤器参数:解码器的解码帧将被插入这里。*/
	char args[256];
	snprintf(args, sizeof(args),
		"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
		w,h,AV_PIX_FMT_YUV420P,1,25,1,1);//图像宽高,格式,帧率,画面横纵比
	/*创建过滤器上下文,源数据AVFilterContext*/
	AVFilterContext *buffersrc_ctx;
	ret=avfilter_graph_create_filter(&buffersrc_ctx,buffersrc,"in",args,NULL,filter_graph);
	if(ret<0)
	{
		printf("创建src过滤器上下文失败AVFilterContextn");
		return -1;
	}		
	/*创建过滤器上下文,处理后数据buffersink_params*/
	AVBufferSinkParams *buffersink_params;
	buffersink_params=av_buffersink_params_alloc();
	buffersink_params->pixel_fmts=pix_fmts;//设置格式
	AVFilterContext *buffersink_ctx;
	ret=avfilter_graph_create_filter(&buffersink_ctx,buffersink,"out",NULL,buffersink_params,filter_graph);
	av_free(buffersink_params);
	if(ret<0)
	{
		printf("创建sink过滤器上下文失败AVFilterContextn");
		return -2;
	}	
	/*过滤器链输入/输出链接列表*/
	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;
	char filter_desrc[200]={0};//要添加的水印数据
	snprintf(filter_desrc,sizeof(filter_desrc),"drawtext=fontfile=msyhbd.ttc:fontcolor=green:fontsize=20:x=50:y=20:text='%snIT_阿水'",str);
	if(avfilter_graph_parse_ptr(filter_graph,filter_desrc,&inputs,&outputs, NULL)<0)//设置过滤器数据内容
	{
		printf("添加字符串信息失败n");
		return -3;
	}
	/*检测配置信息是否正常*/
	if(avfilter_graph_config(filter_graph,NULL)<0)
	{
		printf("配置信息有误n");
		return -4;
	}	
	#if 0
	/*
		查找要在使用的过滤器,将要触处理的数据添加到过滤器
		注意:时间若从外面传入(即144行数据已完整),则此处不需要查找,直接添加即可,否则需要添加下面代码
	*/
	AVFilterContext* filter_ctx;//上下文
	int parsed_drawtext_0_index = -1;
	 for(int i=0;inb_filters;i++)//查找使用的过滤器
	 {
		 AVFilterContext *filter_ctxn=filter_graph->filters[i];
		 printf("[%s %d]:filter_ctxn_name=%sn",__FUNCTION__,__LINE__,filter_ctxn->name);
		 if(!strcmp(filter_ctxn->name,"Parsed_drawtext_0"))
		 {
			parsed_drawtext_0_index=i;
		 }
	 }
	 if(parsed_drawtext_0_index==-1)
	 {
		printf("[%s %d]:no Parsed_drawtext_0n",__FUNCTION__,__LINE__);//没有找到过滤器
	 }
	 filter_ctx=filter_graph->filters[parsed_drawtext_0_index];//保存找到的过滤器
	 
		/*获取系统时间,将时间加入到过滤器*/
		char sys_time[64];
		time_t sec,sec2;	 
		sec=time(NULL);
		if(sec!=sec2)
		{
			sec2=sec;
			struct tm* today = localtime(&sec2);	
			strftime(sys_time, sizeof(sys_time), "%Y/%m/%d %H:%M:%S", today);       //24小时制
		}
		av_opt_set(filter_ctx->priv, "text", sys_time, 0 );  //设置text到过滤器
	 #endif
	/*往源滤波器buffer中输入待处理数据*/
	 if(av_buffersrc_add_frame(buffersrc_ctx,frame_in)<0)
	 {
		return -5;
	 }
	 /*从滤波器中输出处理数据*/
	 if(av_buffersink_get_frame(buffersink_ctx, frame_out)<0)
	 {
		return -6;
	 }
	avfilter_inout_free(&outputs);
    avfilter_inout_free(&inputs);
    avfilter_graph_free(&filter_graph);
	return 0;
}

  Makefile文件:

OBJ=addwatermart.o
CFLAGS =-I/home/wbyq/src_pack/ffmpeg-4.2.5/_install/include -L/home/wbyq/src_pack/ffmpeg-4.2.5/_install/lib
CFLAGS +=-lpthread -lm -ldl -lSDL2_image -lavcodec -lavfilter -lavutil -lswresample -lavdevice -lavformat -lpostproc -lswscale -lpthread -lstdc++ -lm -lasound -lavfilter -lfreetype
app:$(OBJ)
	gcc -o app $(OBJ) $(CFLAGS) 
.PHONY=clean
clean:
	rm app -f

  本示例实现效果为动态添加时间水印。示例效果:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf6Zi_5rC0,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 水印
    +关注

    关注

    0

    文章

    26

    浏览量

    11583
  • 编译
    +关注

    关注

    0

    文章

    615

    浏览量

    32396
  • ffmpeg
    +关注

    关注

    0

    文章

    45

    浏览量

    7290
收藏 人收藏

    评论

    相关推荐

    基于FFMPEG采集摄像头图像编码MP4视频+时间水印

    基于FFMPEG采集摄像头图像编码MP4视频+时间水印
    的头像 发表于 09-29 15:46 2436次阅读
    基于<b class='flag-5'>FFMPEG</b>采集摄像头图像编码MP4视频+时间<b class='flag-5'>水印</b>

    《深入理解FFmpeg阅读体验》ffmpeg安装

    打开环境变量: 将刚才复制的地址添加进去 到此就安装结束,测试一下是否安装成功,打开shell输入ffmpeg -version就可以看到输出信息:
    发表于 01-25 21:35

    图像水印

    本人学生。毕业设计是基于Labview 数字图像水印的利用LabVIEW平台,在图像中嵌入二值水印图像并进行水印的盲提取,系统主要由水印的嵌入与提取两部分组成。通过LabVIEW软件的
    发表于 05-19 14:34

    如何删除pdf文件中的水印 删除pdf中水印的方法

    浏览器中搜索“迅捷PDF编辑器”,将它下载安装到电脑上。   2、运行该软件,点击软件界面的“打开”,将要去除水印的PDF文件添加到该软件的操作界面中。  3、在软件界面上方的功能中,我们找到“文档”选项
    发表于 07-24 11:39

    板子自带的系统上有gstreamer使用vpu,有vpu的ffmpeg吗?

    你好,板子自带的系统上有gstreamer使用vpu,有vpu 的ffmpeg
    发表于 12-31 06:34

    如何交叉编译X264/FFmpeg源码?

    如何交叉编译X264/FFmpeg源码?
    发表于 03-07 08:00

    如何基于ffmpeg在ubuntu系统上添加硬解支持

    firefly-rk3288 linux上H264、H265解码一直都是软解,下面将介绍如何基于ffmpeg,在ubuntu系统上添加硬解支持,首先安装硬解驱动。这里使用的是国外友人mac_l1
    发表于 06-14 09:30

    如何怎么样删除去pdf水印

    如何怎么样删除去pdf水印:总结了几个方法,你看哪个比较好用: 一、1 使用Acrobt Professional v7.0中文版打开PDF文件; 2 文档→添加水印和背景: 2.1 “类
    发表于 01-26 12:33 2.5w次阅读

    C#教程之批量添加水印

    C#教程之批量添加水印,很好的C#资料,快来学习吧。
    发表于 04-20 11:13 5次下载

    教你如何给PDF文件添加水印

        为了保证PDF文件的完整性,防止他人在其他用途上仿制使用该文件,这就是需要给PDF文件添加水印的目的,那么,怎么给PDF文件添加水印呢?使用迅捷PDF编辑器可以轻松实现,跟随小编学起来
    发表于 07-09 13:53 720次阅读
    教你如何给PDF文件<b class='flag-5'>添加水印</b>

    用PDF编辑软件如何为PDF文件添加水印

           无论是工作中,还是生活中都会使用到PDF文件,PDF文件的修改编辑是需要使用到PDF编辑软件的,那么,用PDF编辑软件如何为PDF文件添加水印呢,是不是有很多的小伙伴都想知道怎么操作
    发表于 11-19 11:34 311次阅读

    报告如何单独添加水印?永洪BIV9.2解锁版权保护新方式

    为了给报告添加版权保护信息,防止企业报告被他人盗用,永洪BIV8.0版本水印功能应运而生,解决了企业数据版权问题,但随着使用场景多元化,简单的统一设置水印方式已无法满足大家的需求,备受吐槽。 历经
    发表于 05-28 14:53 1153次阅读
    报告如何单独<b class='flag-5'>添加水印</b>?永洪BIV9.2解锁版权保护新方式

    Linux开发_介绍BMP图片上下翻转、添加水印

    介绍BMP图片上下翻转、添加水印、通过学习BMP图片结构学习文件编程。
    的头像 发表于 09-17 15:43 1388次阅读

    Linux开发_BMP图片编程(翻转、添加水印)

    接收BMP图片编程,完成BMP图片翻转、水印添加等知识点。
    的头像 发表于 09-17 15:33 1141次阅读
    Linux开发_BMP图片编程(翻转、<b class='flag-5'>添加水印</b>)

    Python批量加水印

    现在只要你会使用命令,我们就能教大家怎么使用Python超级简单地为图片添加水印
    的头像 发表于 02-24 11:06 528次阅读
    Python批量加<b class='flag-5'>水印</b>