ffmpeg实现动态调整字幕和水印位置

紧接上一篇文章,字幕内容的修改可以通过av_opt_set修改AVFilterContext的priv来实现,那么字幕和水印的位置是否也可以这样呢?

打开vf_drawtext.c和vf_overlayer.c这两个文件,发现它们都有名为"x"和"y"的设置,然而当我采用av_opt_set将这两个值设置之后,图像位置却没有发生改变,仔细阅读源码,可以看到这两个滤镜都有这样几个变量:

char *x_expr, *y_expr;
AVExpr *x_pexpr, *y_pexpr;

其中x_expr和y_expr是对应滤镜的AVOption中"x"和"y",然而在这两个滤镜在输出时,并不是处理x_expr和y_expr将值赋给AVFilterContext的x和y,而是从x_pexpr和y_pexpr取值,x_pexpr和y_pexpr仅在初始化时从x_expr和y_expr得到设置时的值,这样我就知道需要怎样修改了。

字幕需要修改vf_drawtext.c的draw_text函数,找到

    s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
    s->y = s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, &s->prng);

修改成:

    av_expr_parse(&s->x_pexpr, s->x_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx);
    av_expr_parse(&s->y_pexpr, s->y_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx);

    s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
    s->y = s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, &s->prng);

这样滤镜在每次输出文字时就会重新读取一下AVOption的"x"和"y"。

水印需要修改vf_overlayer.c的do_blend函数,找到

eval_expr(ctx);

修改成:

set_expr(&s->x_pexpr,      s->x_expr,      "x",      ctx);
set_expr(&s->y_pexpr,      s->y_expr,      "y",      ctx);
eval_expr(ctx);

这样每次滤镜在每次输出时,就会重读一下"x"和"y"了。

完成修改后,重新编译ffmpeg,然后就可以在程序中使用

av_opt_set(filter_ctx3->priv, "x", str3, 0 );
av_opt_set(filter_ctx3->priv, "y", str4, 0 );

来重新给水印设置坐标了,其中filter_ctx3是参照上篇文章获取的水印的AVFilterContext,str3和str4是要设置的x和y值的字符串

你可能感兴趣的:(音视频,ffmpeg,滤镜,动态,坐标)