searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

ffmpeg去水印功能改造-使用相对位置去除水印

2023-09-27 06:02:33
270
0
1.前言
使用ffmpeg添加和去除水印是常见的功能,两者的参数都跟在-vf选项后,本文主要介绍水印去除功能。
 
2.水印去除功能简介
常见的ffmpeg水印去除功能的命令行如下
ffmpeg -i xxx.mp4 -vf "delogo=x=1:y=1:w=800:h=100" -c:a copy delogo.mp4
意思是从左上角开始去除水印,水印的范围是长度为800,宽度为100的矩形。一个720P(1280x720)的视频,去除水印的效果如下
 
但是这样将水印坐标固定的写法会导致一些问题,比如当视频的分辨率更低时,很容易出现去除水印区域的长度非法的问题。
比如我们调整去除水印区域的长度超过视频画面的长度,比如1800对于1080P(1920x1080)的视频是合法的,但是对于720P(1280x720)的视频,就不合法了。
ffmpeg -i xxx.mp4 -vf "delogo=x=1:y=1:w=1800:h=100" -c:a copy delogo.mp4
 
所以我们很自然的会想到参考添加水印时采用的方式,使用相对长度和位置,以保证不会使水印去除区域过大。添加水印时,视频画面的长度记为W,视频画面的宽度为H,如下所示
ffmpeg -i xxx.mp4 -vf  "drawtext=text='asdf':fontcolor=white:fontfile=jdsongti.ttf:fontsize=48:x=72:y=H-th-72" -c:a copy logo.mp4
 
但是如果我们直接套用到去除水印的功能里的话,就会出错
ffmpeg -i xxx.mp4 -vf "delogo=x=1:y=1:w=W/2:h=H/10" -c:a copy delogo.mp4
 
那么,这个问题应该如何解决呢?如果要修改ffmpeg,应该如何修改呢?
 
3.修改ffmpeg代码
由于添加水印的部分已经具备了相对长度,所以我们可以参考水印添加的代码,位于libavfilter/vf_drawtext.c,而我们需要修改的代码位于libavfilter/vf_delogo.c,改动如下:
 
首先增加变量名称main_hmain_w来匹配ffmpeg命令行参数中的字符(如x=main_h/2)
static const char * const var_names[] = {
    "main_h",       ///< height of the input video
    "main_w",       ///< width  of the input video
    "x",
    "y",
    "w",
    "h",
    "n",            ///< number of frame
    "t",            ///< timestamp expressed in seconds
    NULL
};
 
其次添加变量VAR_MAIN_HVAR_MAIN_W来记录视频的高和宽
enum var_name {
    VAR_MAIN_H,
    VAR_MAIN_W,
    VAR_X,
    VAR_Y,
    VAR_W,
    VAR_H,
    VAR_N,
    VAR_T,
    VAR_VARS_NB
};
 
最后在config_input处理每一帧时,计算出水印去除区域的坐标。config_input保存了视频的长和宽,并解析表达式(如x=main_h/2),得到计算后的值。
static int config_input(AVFilterLink *inlink)
{
    DelogoContext *s = inlink->dst->priv;
    s->var_values[VAR_MAIN_W] = inlink->w;
    s->var_values[VAR_MAIN_H] = inlink->h;
 
    s->x = av_expr_eval(s->x_pexpr, s->var_values, s);
    s->y = av_expr_eval(s->y_pexpr, s->var_values, s);
    s->w = av_expr_eval(s->w_pexpr, s->var_values, s);
    s->h = av_expr_eval(s->h_pexpr, s->var_values, s);
//    printf("s->x:%d s->y:%d s->w:%d s->h:%d s->band:%d \n", s->x, s->y, s->w, s->y, s->band);
 
    /* Check whether the logo area fits in the frame */
    if (s->x + (s->band - 1) < 0 || s->x + s->w - (s->band*2 - 2) > inlink->w ||
        s->y + (s->band - 1) < 0 || s->y + s->h - (s->band*2 - 2) > inlink->h) {
        av_log(s, AV_LOG_ERROR, "Logo area is outside of the frame.\n");
        return AVERROR(EINVAL);
    }
 
    return 0;
}
 
4.效果
重新编译修改后的ffmpeg,新生成的ffmpeg可以使用以下参数进行水印去除。并且随着视频分辨率的变化,去除水印的位置也会相对发生变化,做到了自适应。
ffmpeg -i xxx.mp4 -vf "delogo=x=1:y=1:w=main_w/2:h=main_h/10" -c:a copy delogo.mp4
可以看到水印去除的区域,就位于整个视频画面长度的一半。
 
5.总结
ffmpeg源码里有很多值得学习的地方,新功能可以基于已有的功能进行移植和裁剪来实现。
0条评论
0 / 1000
1****m
3文章数
0粉丝数
1****m
3 文章 | 0 粉丝
1****m
3文章数
0粉丝数
1****m
3 文章 | 0 粉丝
原创

ffmpeg去水印功能改造-使用相对位置去除水印

2023-09-27 06:02:33
270
0
1.前言
使用ffmpeg添加和去除水印是常见的功能,两者的参数都跟在-vf选项后,本文主要介绍水印去除功能。
 
2.水印去除功能简介
常见的ffmpeg水印去除功能的命令行如下
ffmpeg -i xxx.mp4 -vf "delogo=x=1:y=1:w=800:h=100" -c:a copy delogo.mp4
意思是从左上角开始去除水印,水印的范围是长度为800,宽度为100的矩形。一个720P(1280x720)的视频,去除水印的效果如下
 
但是这样将水印坐标固定的写法会导致一些问题,比如当视频的分辨率更低时,很容易出现去除水印区域的长度非法的问题。
比如我们调整去除水印区域的长度超过视频画面的长度,比如1800对于1080P(1920x1080)的视频是合法的,但是对于720P(1280x720)的视频,就不合法了。
ffmpeg -i xxx.mp4 -vf "delogo=x=1:y=1:w=1800:h=100" -c:a copy delogo.mp4
 
所以我们很自然的会想到参考添加水印时采用的方式,使用相对长度和位置,以保证不会使水印去除区域过大。添加水印时,视频画面的长度记为W,视频画面的宽度为H,如下所示
ffmpeg -i xxx.mp4 -vf  "drawtext=text='asdf':fontcolor=white:fontfile=jdsongti.ttf:fontsize=48:x=72:y=H-th-72" -c:a copy logo.mp4
 
但是如果我们直接套用到去除水印的功能里的话,就会出错
ffmpeg -i xxx.mp4 -vf "delogo=x=1:y=1:w=W/2:h=H/10" -c:a copy delogo.mp4
 
那么,这个问题应该如何解决呢?如果要修改ffmpeg,应该如何修改呢?
 
3.修改ffmpeg代码
由于添加水印的部分已经具备了相对长度,所以我们可以参考水印添加的代码,位于libavfilter/vf_drawtext.c,而我们需要修改的代码位于libavfilter/vf_delogo.c,改动如下:
 
首先增加变量名称main_hmain_w来匹配ffmpeg命令行参数中的字符(如x=main_h/2)
static const char * const var_names[] = {
    "main_h",       ///< height of the input video
    "main_w",       ///< width  of the input video
    "x",
    "y",
    "w",
    "h",
    "n",            ///< number of frame
    "t",            ///< timestamp expressed in seconds
    NULL
};
 
其次添加变量VAR_MAIN_HVAR_MAIN_W来记录视频的高和宽
enum var_name {
    VAR_MAIN_H,
    VAR_MAIN_W,
    VAR_X,
    VAR_Y,
    VAR_W,
    VAR_H,
    VAR_N,
    VAR_T,
    VAR_VARS_NB
};
 
最后在config_input处理每一帧时,计算出水印去除区域的坐标。config_input保存了视频的长和宽,并解析表达式(如x=main_h/2),得到计算后的值。
static int config_input(AVFilterLink *inlink)
{
    DelogoContext *s = inlink->dst->priv;
    s->var_values[VAR_MAIN_W] = inlink->w;
    s->var_values[VAR_MAIN_H] = inlink->h;
 
    s->x = av_expr_eval(s->x_pexpr, s->var_values, s);
    s->y = av_expr_eval(s->y_pexpr, s->var_values, s);
    s->w = av_expr_eval(s->w_pexpr, s->var_values, s);
    s->h = av_expr_eval(s->h_pexpr, s->var_values, s);
//    printf("s->x:%d s->y:%d s->w:%d s->h:%d s->band:%d \n", s->x, s->y, s->w, s->y, s->band);
 
    /* Check whether the logo area fits in the frame */
    if (s->x + (s->band - 1) < 0 || s->x + s->w - (s->band*2 - 2) > inlink->w ||
        s->y + (s->band - 1) < 0 || s->y + s->h - (s->band*2 - 2) > inlink->h) {
        av_log(s, AV_LOG_ERROR, "Logo area is outside of the frame.\n");
        return AVERROR(EINVAL);
    }
 
    return 0;
}
 
4.效果
重新编译修改后的ffmpeg,新生成的ffmpeg可以使用以下参数进行水印去除。并且随着视频分辨率的变化,去除水印的位置也会相对发生变化,做到了自适应。
ffmpeg -i xxx.mp4 -vf "delogo=x=1:y=1:w=main_w/2:h=main_h/10" -c:a copy delogo.mp4
可以看到水印去除的区域,就位于整个视频画面长度的一半。
 
5.总结
ffmpeg源码里有很多值得学习的地方,新功能可以基于已有的功能进行移植和裁剪来实现。
文章来自个人专栏
Keep Moving
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0