基于FFMPEG水印添加---avfilter庫
??avfilter,是ffmpeg為圖像和語音處理提供的濾鏡子框架,代碼位于libavfilter目錄。
??libavfilter提供了一個(gè)通用框架來實(shí)現(xiàn)audio和video的原始數(shù)據(jù)filter處理,如對(duì)視頻添加疊加Logo圖片或者時(shí)間文字等信息、對(duì)視頻進(jìn)行裁剪和翻轉(zhuǎn)。
1.硬件平臺(tái)
操作系統(tǒng):Ubuntu18.04
ffmpeg版本:ffmpeg4.2.5
2.FFMPEG編譯
??在使用avfilter庫添加漢字水印時(shí),ffmepg默認(rèn)模式時(shí)不支持矢量字庫的,要實(shí)現(xiàn)漢字水印添加就需要進(jìn)行configure配置。

2.1 freetype庫編譯
?? freetype下載地址:https://download.savannah.gnu.org/releases/freetype/

2.2 FriBidi庫編譯
?? FriBidi下載地址:https://www.linuxfromscratch.org/blfs/view/svn/general/fribidi.html

#解壓源碼
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命令行添加時(shí)間水印
2.4.1 以實(shí)時(shí)時(shí)間動(dòng)態(tài)添加時(shí)間水印
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拷貝到當(dāng)期目錄下
x=100:y=10顯示位置,距離左上腳
fontcolor=white:fontsize=30字體顏色和大小
expansion=strftime:basetime=$(date +%s )000000以當(dāng)前實(shí)時(shí)時(shí)間添加動(dòng)態(tài)水印
text=‘%Y-%m-%d %H:%M: %S’ 時(shí)間顯示格式

2.4.1 以指定時(shí)間動(dòng)態(tài)添加時(shí)間水印
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

3.代碼實(shí)現(xiàn)水印添加
??參考雷霄驊博客處理示例: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("文件創(chuàng)建失敗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));
/*根據(jù)圖像設(shè)置圖像指針和內(nèi)存對(duì)齊方式*/
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);//添加水印
/*添加水印后的數(shù)據(jù)寫入到過濾器*/
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("一幀數(shù)據(jù)處理完成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;
/*根據(jù)名字獲取ffmegding定義的filter*/
const AVFilter *buffersrc=avfilter_get_by_name("buffer");//原始數(shù)據(jù)
const AVFilter *buffersink=avfilter_get_by_name("buffersink");//處理后的數(shù)據(jù)
/*動(dòng)態(tài)分配AVFilterInOut空間*/
AVFilterInOut *outputs=avfilter_inout_alloc();
AVFilterInOut *inputs=avfilter_inout_alloc();
/*創(chuàng)建AVFilterGraph,分配空間*/
AVFilterGraph *filter_graph;//對(duì)filters系統(tǒng)的整體管理結(jié)構(gòu)體
filter_graph = avfilter_graph_alloc();
enum AVPixelFormat pix_fmts[]={AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE};//設(shè)置格式
/*過濾器參數(shù):解碼器的解碼幀將被插入這里。*/
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);//圖像寬高,格式,幀率,畫面橫縱比
/*創(chuàng)建過濾器上下文,源數(shù)據(jù)AVFilterContext*/
AVFilterContext *buffersrc_ctx;
ret=avfilter_graph_create_filter(&buffersrc_ctx,buffersrc,"in",args,NULL,filter_graph);
if(ret<0)
{
printf("創(chuàng)建src過濾器上下文失敗AVFilterContextn");
return -1;
}
/*創(chuàng)建過濾器上下文,處理后數(shù)據(jù)buffersink_params*/
AVBufferSinkParams *buffersink_params;
buffersink_params=av_buffersink_params_alloc();
buffersink_params->pixel_fmts=pix_fmts;//設(shè)置格式
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("創(chuàng)建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};//要添加的水印數(shù)據(jù)
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)//設(shè)置過濾器數(shù)據(jù)內(nèi)容
{
printf("添加字符串信息失敗n");
return -3;
}
/*檢測(cè)配置信息是否正常*/
if(avfilter_graph_config(filter_graph,NULL)<0)
{
printf("配置信息有誤n");
return -4;
}
#if 0
/*
查找要在使用的過濾器,將要觸處理的數(shù)據(jù)添加到過濾器
注意:時(shí)間若從外面?zhèn)魅?即144行數(shù)據(jù)已完整),則此處不需要查找,直接添加即可,否則需要添加下面代碼
*/
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];//保存找到的過濾器
/*獲取系統(tǒng)時(shí)間,將時(shí)間加入到過濾器*/
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小時(shí)制
}
av_opt_set(filter_ctx->priv, "text", sys_time, 0 ); //設(shè)置text到過濾器
#endif
/*往源濾波器buffer中輸入待處理數(shù)據(jù)*/
if(av_buffersrc_add_frame(buffersrc_ctx,frame_in)<0)
{
return -5;
}
/*從濾波器中輸出處理數(shù)據(jù)*/
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
??本示例實(shí)現(xiàn)效果為動(dòng)態(tài)添加時(shí)間水印。示例效果:

-
水印
+關(guān)注
關(guān)注
0文章
26瀏覽量
11693 -
編譯
+關(guān)注
關(guān)注
0文章
674瀏覽量
33602 -
ffmpeg
+關(guān)注
關(guān)注
0文章
46瀏覽量
7558
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
《深入理解FFmpeg閱讀體驗(yàn)》ffmpeg安裝
如何刪除pdf文件中的水印 刪除pdf中水印的方法
如何基于ffmpeg在ubuntu系統(tǒng)上添加硬解支持
面向內(nèi)容認(rèn)證的關(guān)系數(shù)據(jù)庫水印技術(shù)研究
基于混沌變換的關(guān)系數(shù)據(jù)庫水印算法

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

用PDF編輯軟件如何為PDF文件添加水印
報(bào)告如何單獨(dú)添加水印?永洪BIV9.2解鎖版權(quán)保護(hù)新方式
Linux開發(fā)_介紹BMP圖片上下翻轉(zhuǎn)、添加水印
Hello FFmpeg

評(píng)論